build.rs: add proc-macro to generate Override structs for configuration

memfd
Manos Pitsidianakis 2020-06-20 23:28:50 +03:00
parent 1db2c16f95
commit 0169025d50
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
13 changed files with 653 additions and 220 deletions

7
Cargo.lock generated
View File

@ -795,6 +795,8 @@ dependencies = [
"notify",
"notify-rust",
"pcre2",
"proc-macro2",
"quote",
"rmp",
"rmp-serde",
"rmpv",
@ -806,6 +808,7 @@ dependencies = [
"smallvec",
"structopt",
"svg",
"syn",
"termion",
"toml",
"unicode-segmentation",
@ -1622,9 +1625,9 @@ checksum = "0b65a64d32a41db2a8081aa03c1ccca26f246ff681add693f8b01307b137da79"
[[package]]
name = "syn"
version = "1.0.30"
version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93a56fabc59dce20fe48b6c832cc249c713e7ed88fa28b0ee0a3bfcaae5fe4e2"
checksum = "b5304cfdf27365b7585c25d4af91b35016ed21ef88f17ced89c7093b43dba8b6"
dependencies = [
"proc-macro2",
"quote",

View File

@ -52,6 +52,10 @@ pcre2 = { version = "0.2.3", optional = true }
structopt = { version = "0.3.14", default-features = false }
svg_crate = { version = "0.8.0", optional = true, package = "svg" }
[build-dependencies]
syn = { version = "1.0.31", features = [] }
quote = "^1.0"
proc-macro2 = "1.0.18"
[profile.release]
lto = true

View File

@ -19,8 +19,22 @@
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
extern crate proc_macro;
extern crate quote;
extern crate syn;
mod config_macros;
fn main() {
println!("cargo:rerun-if-changed=build.rs");
config_macros::override_derive(&[
("src/conf/pager.rs", "PagerSettings"),
("src/conf/listing.rs", "ListingSettings"),
("src/conf/notifications.rs", "NotificationsSettings"),
("src/conf/shortcuts.rs", "Shortcuts"),
("src/conf/composing.rs", "ComposingSettings"),
("src/conf/tags.rs", "TagsSettings"),
("src/conf/pgp.rs", "PGPSettings"),
]);
#[cfg(feature = "cli-docs")]
{
const MANDOC_OPTS: &[&'static str] = &["-T", "utf8", "-I", "os=Generated by mandoc(1)"];

185
config_macros.rs 100644
View File

@ -0,0 +1,185 @@
/*
* meli -
*
* Copyright Manos Pitsidianakis
*
* This file is part of meli.
*
* meli is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* meli is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
use std::fs::File;
use std::io::prelude::*;
use std::process::{Command, Stdio};
use quote::{format_ident, quote};
// Write ConfigStructOverride to overrides.rs
pub fn override_derive(filenames: &[(&str, &str)]) {
let mut output_file =
File::create("src/conf/overrides.rs").expect("Unable to open output file");
let mut output_string = r##"/*
* meli - conf/overrides.rs
*
* Copyright 2020 Manos Pitsidianakis
*
* This file is part of meli.
*
* meli is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* meli is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
//! This module is automatically generated by build.rs.
use super::*;
"##
.to_string();
'file_loop: for (filename, ident) in filenames {
println!("cargo:rerun-if-changed={}", filename);
let mut file = File::open(&filename).expect(&format!("Unable to open file `{}`", filename));
let mut src = String::new();
file.read_to_string(&mut src).expect("Unable to read file");
let syntax = syn::parse_file(&src).expect("Unable to parse file");
if syntax.items.iter().any(|item| {
if let syn::Item::Struct(s) = item {
if s.ident.to_string().ends_with("Override") {
println!("ident {} exists, skipping {}", ident, filename);
return true;
}
}
false
}) {
continue 'file_loop;
}
for item in syntax.items.iter() {
if let syn::Item::Struct(s) = item {
if s.ident != ident {
continue;
}
if s.ident.to_string().ends_with("Override") {
unreachable!();
}
let override_ident: syn::Ident = format_ident!("{}Override", s.ident);
let mut field_tokentrees = vec![];
let mut field_idents = vec![];
for f in &s.fields {
let ident = &f.ident;
let ty = &f.ty;
let attrs = f
.attrs
.iter()
.filter_map(|f| {
let mut new_attr = f.clone();
if let quote::__private::TokenTree::Group(g) =
f.tokens.clone().into_iter().next().unwrap()
{
let attr_inner_value = f.tokens.to_string();
if !attr_inner_value.starts_with("( default")
&& !attr_inner_value.starts_with("( default =")
{
return None;
}
if attr_inner_value.starts_with("( default =") {
let rest = g.stream().clone().into_iter().skip(4);
new_attr.tokens = quote! { ( #(#rest)*) };
if new_attr.tokens.to_string().as_str() == "( )" {
return None;
}
} else if attr_inner_value.starts_with("( default") {
let rest = g.stream().clone().into_iter().skip(2);
new_attr.tokens = quote! { ( #(#rest)*) };
if new_attr.tokens.to_string().as_str() == "( )" {
return None;
}
}
}
Some(new_attr)
})
.collect::<Vec<_>>();
let t = quote! {
#(#attrs)*
#[serde(default)]
pub #ident : Option<#ty>
};
field_idents.push(ident);
field_tokentrees.push(t);
}
//let fields = &s.fields;
let literal_struct = quote! {
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct #override_ident {
#(#field_tokentrees),*
}
impl Default for #override_ident {
fn default() -> Self {
#override_ident {
#(#field_idents: None),*
}
}
}
};
output_string.extend(literal_struct.to_string().chars());
output_string.push_str("\n\n");
}
}
}
/*
let mut rustfmt = Command::new("rustfmt")
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.expect("failed to execute rustfmt");
{
// limited borrow of stdin
let stdin = rustfmt
.stdin
.as_mut()
.expect("failed to get rustfmt stdin");
stdin
.write_all(output_string.as_bytes())
.expect("failed to write to rustfmit stdin");
}
let output = rustfmt
.wait_with_output()
.expect("failed to wait on rustfmt child");
if !output.stderr.is_empty() {
panic!(format!("{}", String::from_utf8_lossy(&output.stderr)));
}
output_file.write_all(&output.stdout).unwrap();
*/
output_file.write_all(output_string.as_bytes()).unwrap();
}

View File

@ -26,6 +26,12 @@ extern crate serde;
extern crate toml;
extern crate xdg;
use crate::conf::deserializers::non_empty_string;
use crate::terminal::Color;
use melib::search::Query;
use std::collections::HashSet;
mod overrides;
pub use overrides::*;
pub mod composing;
pub mod notifications;
pub mod pager;
@ -46,10 +52,10 @@ pub use self::shortcuts::*;
pub use self::tags::*;
use self::default_vals::*;
use self::listing::{ListingSettings, ListingSettingsOverride};
use self::notifications::{NotificationsSettings, NotificationsSettingsOverride};
use self::listing::ListingSettings;
use self::notifications::NotificationsSettings;
use self::terminal::TerminalSettings;
use crate::pager::{PagerSettings, PagerSettingsOverride};
use crate::pager::PagerSettings;
use crate::plugins::Plugin;
use melib::conf::{AccountSettings, MailboxConf, ToggleFlag};
use melib::error::*;
@ -101,38 +107,6 @@ macro_rules! mailbox_settings {
}};
}
#[macro_export]
macro_rules! override_def {
($override_name:ident,
$(#[$outer:meta])*
pub struct $name:ident { $( $(#[$fouter:meta])* $fname:ident : $ft:ty),*,
}) => {
$(#[$outer])*
pub struct $name {
$(
$(#[$fouter])*
pub $fname : $ft
),*
}
$(#[$outer])*
pub struct $override_name {
$(
#[serde(default = "crate::conf::default_vals::none")]
pub $fname : Option<$ft>
),*
}
impl Default for $override_name {
fn default() -> Self {
$override_name {
$(
$fname : None
),*
}
}
}
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct MailUIConf {
#[serde(default)]

View File

@ -21,34 +21,30 @@
//! Configuration for composing email.
use super::default_vals::{false_val, none, true_val};
use crate::override_def;
use std::collections::HashMap;
override_def!(
ComposingSettingsOverride,
/// Settings for writing and sending new e-mail
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ComposingSettings {
/// A command to pipe new emails to
/// Required
#[serde(alias = "mailer-cmd")]
mailer_cmd: String,
/// Command to launch editor. Can have arguments. Draft filename is given as the last argument. If it's missing, the environment variable $EDITOR is looked up.
#[serde(default = "none", alias = "editor-cmd")]
editor_cmd: Option<String>,
/// Embed editor (for terminal interfaces) instead of forking and waiting.
#[serde(default = "false_val")]
embed: bool,
/// Set "format=flowed" in plain text attachments.
/// Default: true
#[serde(default = "true_val", alias = "format-flowed")]
format_flowed: bool,
/// Set default header values for new drafts
/// Default: empty
#[serde(default, alias = "default-header-values")]
default_header_values: HashMap<String, String>,
}
);
/// Settings for writing and sending new e-mail
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ComposingSettings {
/// A command to pipe new emails to
/// Required
#[serde(alias = "mailer-cmd")]
pub mailer_cmd: String,
/// Command to launch editor. Can have arguments. Draft filename is given as the last argument. If it's missing, the environment variable $EDITOR is looked up.
#[serde(default = "none", alias = "editor-cmd")]
pub editor_cmd: Option<String>,
/// Embed editor (for terminal interfaces) instead of forking and waiting.
#[serde(default = "false_val")]
pub embed: bool,
/// Set "format=flowed" in plain text attachments.
/// Default: true
#[serde(default = "true_val", alias = "format-flowed")]
pub format_flowed: bool,
/// Set default header values for new drafts
/// Default: empty
#[serde(default, alias = "default-header-values")]
pub default_header_values: HashMap<String, String>,
}
impl Default for ComposingSettings {
fn default() -> Self {

View File

@ -20,38 +20,34 @@
*/
use super::{default_vals::*, IndexStyle};
use crate::override_def;
use melib::search::Query;
override_def!(
ListingSettingsOverride,
/// Settings for mail listings
#[derive(Debug, Deserialize, Clone, Serialize)]
pub struct ListingSettings {
/// Number of context lines when going to next page.
/// Default: 0
#[serde(default = "zero_val", alias = "context-lines")]
context_lines: usize,
/// Settings for mail listings
#[derive(Debug, Deserialize, Clone, Serialize)]
pub struct ListingSettings {
/// Number of context lines when going to next page.
/// Default: 0
#[serde(default = "zero_val", alias = "context-lines")]
pub context_lines: usize,
/// Datetime formatting passed verbatim to strftime(3).
/// Default: %Y-%m-%d %T
#[serde(default = "none", alias = "datetime-fmt")]
datetime_fmt: Option<String>,
/// Datetime formatting passed verbatim to strftime(3).
/// Default: %Y-%m-%d %T
#[serde(default = "none", alias = "datetime-fmt")]
pub datetime_fmt: Option<String>,
/// Show recent dates as `X {minutes,hours,days} ago`, up to 7 days.
/// Default: true
#[serde(default = "true_val", alias = "recent-dates")]
recent_dates: bool,
/// Show recent dates as `X {minutes,hours,days} ago`, up to 7 days.
/// Default: true
#[serde(default = "true_val", alias = "recent-dates")]
pub recent_dates: bool,
/// Show only envelopes that match this query
/// Default: None
#[serde(default = "none")]
filter: Option<Query>,
/// Show only envelopes that match this query
/// Default: None
#[serde(default = "none")]
pub filter: Option<Query>,
#[serde(default, alias = "index-style")]
index_style: IndexStyle,
}
);
#[serde(default, alias = "index-style")]
pub index_style: IndexStyle,
}
impl Default for ListingSettings {
fn default() -> Self {

View File

@ -20,28 +20,24 @@
*/
use super::default_vals::{internal_value_false, none};
use crate::override_def;
override_def!(
NotificationsSettingsOverride,
/// Settings for the notifications function.
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct NotificationsSettings {
/// A command to pipe notifications through
/// Default: None
#[serde(default = "none")]
script: Option<String>,
/// A file location which has its size changed when new mail arrives (max 128 bytes). Can be
/// used to trigger new mail notifications eg with `xbiff(1)`
/// Default: None
#[serde(default = "none", alias = "xbiff-file-path")]
xbiff_file_path: Option<String>,
#[serde(default = "internal_value_false", alias = "play-sound")]
play_sound: super::ToggleFlag,
#[serde(default = "none", alias = "sound-file")]
sound_file: Option<String>,
}
);
/// Settings for the notifications function.
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct NotificationsSettings {
/// A command to pipe notifications through
/// Default: None
#[serde(default = "none")]
pub script: Option<String>,
/// A file location which has its size changed when new mail arrives (max 128 bytes). Can be
/// used to trigger new mail notifications eg with `xbiff(1)`
/// Default: None
#[serde(default = "none", alias = "xbiff-file-path")]
pub xbiff_file_path: Option<String>,
#[serde(default = "internal_value_false", alias = "play-sound")]
pub play_sound: super::ToggleFlag,
#[serde(default = "none", alias = "sound-file")]
pub sound_file: Option<String>,
}
impl Default for NotificationsSettings {
fn default() -> Self {

View File

@ -0,0 +1,281 @@
/*
* meli - conf/overrides.rs
*
* Copyright 2020 Manos Pitsidianakis
*
* This file is part of meli.
*
* meli is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* meli is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
//! This module is automatically generated by build.rs.
use super::*;
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct PagerSettingsOverride {
#[doc = " Number of context lines when going to next page."]
#[doc = " Default: 0"]
#[serde(alias = "pager-context")]
#[serde(default)]
pub pager_context: Option<usize>,
#[doc = " Stop at the end instead of displaying next mail."]
#[doc = " Default: false"]
#[serde(alias = "pager-stop")]
#[serde(default)]
pub pager_stop: Option<bool>,
#[doc = " Always show headers when scrolling."]
#[doc = " Default: true"]
#[serde(alias = "headers-sticky")]
#[serde(default)]
pub headers_sticky: Option<bool>,
#[doc = " The height of the pager in mail view, in percent."]
#[doc = " Default: 80"]
#[serde(alias = "pager-ratio")]
#[serde(default)]
pub pager_ratio: Option<usize>,
#[doc = " A command to pipe mail output through for viewing in pager."]
#[doc = " Default: None"]
#[serde(deserialize_with = "non_empty_string")]
#[serde(default)]
pub filter: Option<Option<String>>,
#[doc = " A command to pipe html output before displaying it in a pager"]
#[doc = " Default: None"]
#[serde(deserialize_with = "non_empty_string", alias = "html-filter")]
#[serde(default)]
pub html_filter: Option<Option<String>>,
#[doc = " Respect \"format=flowed\""]
#[doc = " Default: true"]
#[serde(alias = "format-flowed")]
#[serde(default)]
pub format_flowed: Option<bool>,
#[doc = " Split long lines that would overflow on the x axis."]
#[doc = " Default: true"]
#[serde(alias = "split-long-lines")]
#[serde(default)]
pub split_long_lines: Option<bool>,
#[doc = " Minimum text width in columns."]
#[doc = " Default: 80"]
#[serde(alias = "minimum-width")]
#[serde(default)]
pub minimum_width: Option<usize>,
#[doc = " Choose `text/html` alternative if `text/plain` is empty in `multipart/alternative`"]
#[doc = " attachments."]
#[doc = " Default: true"]
#[serde(alias = "auto-choose-multipart-alternative")]
#[serde(default)]
pub auto_choose_multipart_alternative: Option<ToggleFlag>,
}
impl Default for PagerSettingsOverride {
fn default() -> Self {
PagerSettingsOverride {
pager_context: None,
pager_stop: None,
headers_sticky: None,
pager_ratio: None,
filter: None,
html_filter: None,
format_flowed: None,
split_long_lines: None,
minimum_width: None,
auto_choose_multipart_alternative: None,
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ListingSettingsOverride {
#[doc = " Number of context lines when going to next page."]
#[doc = " Default: 0"]
#[serde(alias = "context-lines")]
#[serde(default)]
pub context_lines: Option<usize>,
#[doc = " Datetime formatting passed verbatim to strftime(3)."]
#[doc = " Default: %Y-%m-%d %T"]
#[serde(alias = "datetime-fmt")]
#[serde(default)]
pub datetime_fmt: Option<Option<String>>,
#[doc = " Show recent dates as `X {minutes,hours,days} ago`, up to 7 days."]
#[doc = " Default: true"]
#[serde(alias = "recent-dates")]
#[serde(default)]
pub recent_dates: Option<bool>,
#[doc = " Show only envelopes that match this query"]
#[doc = " Default: None"]
#[serde(default)]
pub filter: Option<Option<Query>>,
#[serde(alias = "index-style")]
#[serde(default)]
pub index_style: Option<IndexStyle>,
}
impl Default for ListingSettingsOverride {
fn default() -> Self {
ListingSettingsOverride {
context_lines: None,
datetime_fmt: None,
recent_dates: None,
filter: None,
index_style: None,
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct NotificationsSettingsOverride {
#[doc = " A command to pipe notifications through"]
#[doc = " Default: None"]
#[serde(default)]
pub script: Option<Option<String>>,
#[doc = " A file location which has its size changed when new mail arrives (max 128 bytes). Can be"]
#[doc = " used to trigger new mail notifications eg with `xbiff(1)`"]
#[doc = " Default: None"]
#[serde(alias = "xbiff-file-path")]
#[serde(default)]
pub xbiff_file_path: Option<Option<String>>,
#[serde(alias = "play-sound")]
#[serde(default)]
pub play_sound: Option<super::ToggleFlag>,
#[serde(alias = "sound-file")]
#[serde(default)]
pub sound_file: Option<Option<String>>,
}
impl Default for NotificationsSettingsOverride {
fn default() -> Self {
NotificationsSettingsOverride {
script: None,
xbiff_file_path: None,
play_sound: None,
sound_file: None,
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ShortcutsOverride {
#[serde(default)]
pub general: Option<GeneralShortcuts>,
#[serde(default)]
pub listing: Option<ListingShortcuts>,
#[serde(default)]
pub composing: Option<ComposingShortcuts>,
#[serde(alias = "compact-listing")]
#[serde(default)]
pub compact_listing: Option<CompactListingShortcuts>,
#[serde(alias = "contact-list")]
#[serde(default)]
pub contact_list: Option<ContactListShortcuts>,
#[serde(alias = "envelope-view")]
#[serde(default)]
pub envelope_view: Option<EnvelopeViewShortcuts>,
#[serde(alias = "thread-view")]
#[serde(default)]
pub thread_view: Option<ThreadViewShortcuts>,
#[serde(default)]
pub pager: Option<PagerShortcuts>,
}
impl Default for ShortcutsOverride {
fn default() -> Self {
ShortcutsOverride {
general: None,
listing: None,
composing: None,
compact_listing: None,
contact_list: None,
envelope_view: None,
thread_view: None,
pager: None,
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ComposingSettingsOverride {
#[doc = " A command to pipe new emails to"]
#[doc = " Required"]
#[serde(default)]
pub mailer_cmd: Option<String>,
#[doc = " Command to launch editor. Can have arguments. Draft filename is given as the last argument. If it's missing, the environment variable $EDITOR is looked up."]
#[serde(alias = "editor-cmd")]
#[serde(default)]
pub editor_cmd: Option<Option<String>>,
#[doc = " Embed editor (for terminal interfaces) instead of forking and waiting."]
#[serde(default)]
pub embed: Option<bool>,
#[doc = " Set \"format=flowed\" in plain text attachments."]
#[doc = " Default: true"]
#[serde(alias = "format-flowed")]
#[serde(default)]
pub format_flowed: Option<bool>,
#[doc = " Set default header values for new drafts"]
#[doc = " Default: empty"]
#[serde(alias = "default-header-values")]
#[serde(default)]
pub default_header_values: Option<HashMap<String, String>>,
}
impl Default for ComposingSettingsOverride {
fn default() -> Self {
ComposingSettingsOverride {
mailer_cmd: None,
editor_cmd: None,
embed: None,
format_flowed: None,
default_header_values: None,
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct TagsSettingsOverride {
#[serde(deserialize_with = "tag_color_de")]
#[serde(default)]
pub colors: Option<HashMap<u64, Color>>,
#[serde(deserialize_with = "tag_set_de", alias = "ignore-tags")]
#[serde(default)]
pub ignore_tags: Option<HashSet<u64>>,
}
impl Default for TagsSettingsOverride {
fn default() -> Self {
TagsSettingsOverride {
colors: None,
ignore_tags: None,
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct PGPSettingsOverride {
#[doc = " auto verify signed e-mail according to RFC3156"]
#[serde(alias = "auto-verify-signatures")]
#[serde(default)]
pub auto_verify_signatures: Option<bool>,
#[doc = " always sign sent messages"]
#[serde(alias = "auto-sign")]
#[serde(default)]
pub auto_sign: Option<bool>,
#[serde(default)]
pub key: Option<Option<String>>,
#[doc = " gpg binary name or file location to use"]
#[serde(alias = "gpg-binary")]
#[serde(default)]
pub gpg_binary: Option<Option<String>>,
}
impl Default for PGPSettingsOverride {
fn default() -> Self {
PGPSettingsOverride {
auto_verify_signatures: None,
auto_sign: None,
key: None,
gpg_binary: None,
}
}
}

View File

@ -23,73 +23,69 @@
use super::default_vals::*;
use super::deserializers::*;
use crate::override_def;
use melib::ToggleFlag;
override_def!(
PagerSettingsOverride,
/// Settings for the pager function.
#[derive(Debug, Deserialize, Clone, Serialize)]
pub struct PagerSettings {
/// Number of context lines when going to next page.
/// Default: 0
#[serde(default = "zero_val", alias = "pager-context")]
pager_context: usize,
/// Settings for the pager function.
#[derive(Debug, Deserialize, Clone, Serialize)]
pub struct PagerSettings {
/// Number of context lines when going to next page.
/// Default: 0
#[serde(default = "zero_val", alias = "pager-context")]
pub pager_context: usize,
/// Stop at the end instead of displaying next mail.
/// Default: false
#[serde(default = "false_val", alias = "pager-stop")]
pager_stop: bool,
/// Stop at the end instead of displaying next mail.
/// Default: false
#[serde(default = "false_val", alias = "pager-stop")]
pub pager_stop: bool,
/// Always show headers when scrolling.
/// Default: true
#[serde(default = "true_val", alias = "headers-sticky")]
headers_sticky: bool,
/// Always show headers when scrolling.
/// Default: true
#[serde(default = "true_val", alias = "headers-sticky")]
pub headers_sticky: bool,
/// The height of the pager in mail view, in percent.
/// Default: 80
#[serde(default = "eighty_val", alias = "pager-ratio")]
pager_ratio: usize,
/// The height of the pager in mail view, in percent.
/// Default: 80
#[serde(default = "eighty_val", alias = "pager-ratio")]
pub pager_ratio: usize,
/// A command to pipe mail output through for viewing in pager.
/// Default: None
#[serde(default = "none", deserialize_with = "non_empty_string")]
filter: Option<String>,
/// A command to pipe mail output through for viewing in pager.
/// Default: None
#[serde(default = "none", deserialize_with = "non_empty_string")]
pub filter: Option<String>,
/// A command to pipe html output before displaying it in a pager
/// Default: None
#[serde(
default = "none",
deserialize_with = "non_empty_string",
alias = "html-filter"
)]
html_filter: Option<String>,
/// A command to pipe html output before displaying it in a pager
/// Default: None
#[serde(
default = "none",
deserialize_with = "non_empty_string",
alias = "html-filter"
)]
pub html_filter: Option<String>,
/// Respect "format=flowed"
/// Default: true
#[serde(default = "true_val", alias = "format-flowed")]
format_flowed: bool,
/// Respect "format=flowed"
/// Default: true
#[serde(default = "true_val", alias = "format-flowed")]
pub format_flowed: bool,
/// Split long lines that would overflow on the x axis.
/// Default: true
#[serde(default = "true_val", alias = "split-long-lines")]
split_long_lines: bool,
/// Split long lines that would overflow on the x axis.
/// Default: true
#[serde(default = "true_val", alias = "split-long-lines")]
pub split_long_lines: bool,
/// Minimum text width in columns.
/// Default: 80
#[serde(default = "eighty_val", alias = "minimum-width")]
minimum_width: usize,
/// Minimum text width in columns.
/// Default: 80
#[serde(default = "eighty_val", alias = "minimum-width")]
pub minimum_width: usize,
/// Choose `text/html` alternative if `text/plain` is empty in `multipart/alternative`
/// attachments.
/// Default: true
#[serde(
default = "internal_value_true",
alias = "auto-choose-multipart-alternative"
)]
auto_choose_multipart_alternative: ToggleFlag,
}
);
/// Choose `text/html` alternative if `text/plain` is empty in `multipart/alternative`
/// attachments.
/// Default: true
#[serde(
default = "internal_value_true",
alias = "auto-choose-multipart-alternative"
)]
pub auto_choose_multipart_alternative: ToggleFlag,
}
impl Default for PagerSettings {
fn default() -> Self {

View File

@ -20,30 +20,26 @@
*/
use super::default_vals::*;
use crate::override_def;
override_def!(
PGPSettingsOverride,
/// Settings for digital signing and encryption
#[derive(Debug, Deserialize, Clone, Serialize)]
pub struct PGPSettings {
/// auto verify signed e-mail according to RFC3156
#[serde(default = "true_val", alias = "auto-verify-signatures")]
auto_verify_signatures: bool,
/// Settings for digital signing and encryption
#[derive(Debug, Deserialize, Clone, Serialize)]
pub struct PGPSettings {
/// auto verify signed e-mail according to RFC3156
#[serde(default = "true_val", alias = "auto-verify-signatures")]
pub auto_verify_signatures: bool,
/// always sign sent messages
#[serde(default = "false_val", alias = "auto-sign")]
auto_sign: bool,
/// always sign sent messages
#[serde(default = "false_val", alias = "auto-sign")]
pub auto_sign: bool,
// https://tools.ietf.org/html/rfc4880#section-12.2
#[serde(default = "none")]
key: Option<String>,
// https://tools.ietf.org/html/rfc4880#section-12.2
#[serde(default = "none")]
pub key: Option<String>,
/// gpg binary name or file location to use
#[serde(default, alias = "gpg-binary")]
gpg_binary: Option<String>,
}
);
/// gpg binary name or file location to use
#[serde(default, alias = "gpg-binary")]
pub gpg_binary: Option<String>,
}
impl Default for PGPSettings {
fn default() -> Self {

View File

@ -19,7 +19,6 @@
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
use crate::override_def;
use crate::terminal::Key;
use std::collections::HashMap;
@ -33,28 +32,25 @@ macro_rules! shortcut {
};
}
override_def!(
ShortcutsOverride,
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Shortcuts {
#[serde(default)]
general: GeneralShortcuts,
#[serde(default)]
listing: ListingShortcuts,
#[serde(default)]
composing: ComposingShortcuts,
#[serde(default, alias = "compact-listing")]
compact_listing: CompactListingShortcuts,
#[serde(default, alias = "contact-list")]
contact_list: ContactListShortcuts,
#[serde(default, alias = "envelope-view")]
envelope_view: EnvelopeViewShortcuts,
#[serde(default, alias = "thread-view")]
thread_view: ThreadViewShortcuts,
#[serde(default)]
pager: PagerShortcuts,
}
);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Shortcuts {
#[serde(default)]
pub general: GeneralShortcuts,
#[serde(default)]
pub listing: ListingShortcuts,
#[serde(default)]
pub composing: ComposingShortcuts,
#[serde(default, alias = "compact-listing")]
pub compact_listing: CompactListingShortcuts,
#[serde(default, alias = "contact-list")]
pub contact_list: ContactListShortcuts,
#[serde(default, alias = "envelope-view")]
pub envelope_view: EnvelopeViewShortcuts,
#[serde(default, alias = "thread-view")]
pub thread_view: ThreadViewShortcuts,
#[serde(default)]
pub pager: PagerShortcuts,
}
impl Default for Shortcuts {
fn default() -> Self {

View File

@ -21,22 +21,18 @@
//! E-mail tag configuration and {de,}serializing.
use crate::override_def;
use crate::terminal::Color;
use serde::{Deserialize, Deserializer};
use std::collections::{hash_map::DefaultHasher, HashMap, HashSet};
use std::hash::Hasher;
override_def!(
TagsSettingsOverride,
#[derive(Debug, Deserialize, Clone, Serialize)]
pub struct TagsSettings {
#[serde(default, deserialize_with = "tag_color_de")]
colors: HashMap<u64, Color>,
#[serde(default, deserialize_with = "tag_set_de", alias = "ignore-tags")]
ignore_tags: HashSet<u64>,
}
);
#[derive(Debug, Deserialize, Clone, Serialize)]
pub struct TagsSettings {
#[serde(default, deserialize_with = "tag_color_de")]
pub colors: HashMap<u64, Color>,
#[serde(default, deserialize_with = "tag_set_de", alias = "ignore-tags")]
pub ignore_tags: HashSet<u64>,
}
impl Default for TagsSettings {
fn default() -> Self {