1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use std::fmt;
pub enum ParseConfigError {
NoSuchConfig,
InvalidValue,
}
impl fmt::Display for ParseConfigError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::NoSuchConfig => f.write_str("no such config"),
Self::InvalidValue => f.write_str("invalid config value"),
}
}
}
macro_rules! config_values {
($($name:ident: $type:ty = $default:expr,)*) => {
pub static CONFIG_NAMES: &[&str] = &[$(stringify!($name),)*];
pub struct Config {
$(pub $name: $type,)*
}
impl Config {
pub fn parse_config(&mut self, key: &str, value: &str) -> Result<(), ParseConfigError> {
match key {
$(stringify!($name) => match value.parse() {
Ok(value) => self.$name = value,
Err(_) => return Err(ParseConfigError::InvalidValue),
},)*
_ => return Err(ParseConfigError::NoSuchConfig),
}
Ok(())
}
pub fn display_config(&self, key: &str) -> Option<DisplayConfig> {
match key {
$(stringify!($name) => Some(DisplayConfig {
config: self,
writter: |c, f| fmt::Display::fmt(&c.$name, f),
}),)*
_ => None,
}
}
}
impl Default for Config {
fn default() -> Self {
Self {
$($name: $default,)*
}
}
}
pub struct DisplayConfig<'a> {
config: &'a Config,
writter: fn(&Config, &mut fmt::Formatter) -> fmt::Result
}
impl<'a> fmt::Display for DisplayConfig<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
(self.writter)(self.config, f)
}
}
}
}
config_values! {
tab_size: u8 = 4,
indent_with_tabs: bool = false,
visual_empty: char = '~',
visual_space: char = '.',
visual_tab_first: char = '|',
visual_tab_repeat: char = ' ',
completion_min_len: u8 = 3,
picker_max_height: u8 = 8,
status_bar_max_height: u8 = 8,
}