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
use std::{env, path::PathBuf};
use figment::{
Figment,
providers::{Env, Format, Json, Serialized},
};
use serde::{Deserialize, Serialize};
use crate::args::Cli;
/// The configuration for cjkfmt.
#[derive(Serialize, Deserialize)]
pub struct Config {
/// Maximum line width to allow. (default: 80)
pub max_width: u32,
}
impl Config {
pub fn from_cli_args(args: &Cli) -> Result<Self, Box<figment::Error>> {
// Resolve configuration directory.
// XDG_CONFIG_HOME is used if set, otherwise defaults to $HOME.
let config_home = env::var_os("XDG_CONFIG_HOME")
.map(PathBuf::from)
.or_else(env::home_dir);
let user_config_path = config_home.map(|p| p.join(".cjkfmt.json"));
// Load configuration from various sources:
// 1. Default values
// 2. JSON file `.cjkfmt.json` at the user's configuration directory
// (`XDG_CONFIG_HOME` if set, otherwise `$HOME/.config`)
// 3. JSON file `.cjkfmt.json` found in the current or ancestor directories
// 4. Environment variables prefixed with `CJKFMT_`
let config = Figment::new();
let config = config.merge(Serialized::defaults(Config::default()));
let config = if let Some(path) = user_config_path {
if path.exists() {
config.merge(Json::file_exact(path))
} else {
config
}
} else {
config
};
let config = config.merge(Json::file(".cjkfmt.json"));
let config = config.merge(Env::prefixed("CJKFMT_"));
let mut config: Self = config.extract()?;
// Override with command line arguments
if let Some(max_width) = args.max_width {
config.max_width = max_width;
}
Ok(config)
}
}
impl Default for Config {
fn default() -> Self {
Config { max_width: 80 }
}
}