-
-
Notifications
You must be signed in to change notification settings - Fork 476
/
Copy pathset.rs
137 lines (117 loc) · 4.22 KB
/
set.rs
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use eyre::{Result, bail, eyre};
use toml_edit::DocumentMut;
use crate::config::settings::{SETTINGS_META, SettingsFile, SettingsType};
use crate::{config, duration, file};
/// Add/update a setting
///
/// This modifies the contents of ~/.config/mise/config.toml
#[derive(Debug, clap::Args)]
#[clap(visible_aliases = ["create"], after_long_help = AFTER_LONG_HELP, verbatim_doc_comment)]
pub struct SettingsSet {
/// The setting to set
#[clap()]
pub setting: String,
/// The value to set
pub value: String,
/// Use the local config file instead of the global one
#[clap(long, short)]
pub local: bool,
}
impl SettingsSet {
pub fn run(self) -> Result<()> {
set(&self.setting, &self.value, false, self.local)
}
}
pub fn set(mut key: &str, value: &str, add: bool, local: bool) -> Result<()> {
let parsed_value = if let Some(meta) = SETTINGS_META.get(key) {
match meta.type_ {
SettingsType::Bool => parse_bool(value)?,
SettingsType::Integer => parse_i64(value)?,
SettingsType::Duration => parse_duration(value)?,
SettingsType::Url | SettingsType::Path | SettingsType::String => value.into(),
SettingsType::ListString => parse_list_by_comma(value)?,
SettingsType::ListPath => parse_list_by_colon(value)?,
}
} else {
bail!("Unknown setting: {}", key);
};
let path = if local {
config::local_toml_config_path()
} else {
config::global_config_path()
};
file::create_dir_all(path.parent().unwrap())?;
let raw = file::read_to_string(&path).unwrap_or_default();
let mut config: DocumentMut = raw.parse()?;
if !config.contains_key("settings") {
config["settings"] = toml_edit::Item::Table(toml_edit::Table::new());
}
if let Some(mut settings) = config["settings"].as_table_mut() {
if let Some((parent, child)) = key.split_once('.') {
key = child;
settings = settings
.entry(parent)
.or_insert({
let mut t = toml_edit::Table::new();
t.set_implicit(true);
toml_edit::Item::Table(t)
})
.as_table_mut()
.unwrap();
}
let new_value: toml_edit::Value = if add {
if let Some(existing_arr) = settings.get(key).and_then(|item| item.as_array()).cloned()
{
let mut arr = existing_arr;
// Dedupe by comparing to the original &str
if !arr.iter().any(|it| it.as_str() == Some(value)) {
arr.push(value);
}
toml_edit::Value::Array(arr)
} else {
parsed_value.clone()
}
} else {
parsed_value.clone()
};
settings.insert(key, new_value.into());
// validate
let _: SettingsFile = toml::from_str(&config.to_string())?;
file::write(&path, config.to_string())?;
}
Ok(())
}
fn parse_list_by_comma(value: &str) -> Result<toml_edit::Value> {
if value.is_empty() || value == "[]" {
return Ok(toml_edit::Array::new().into());
}
Ok(value.split(',').map(|s| s.trim().to_string()).collect())
}
fn parse_list_by_colon(value: &str) -> Result<toml_edit::Value> {
if value.is_empty() || value == "[]" {
return Ok(toml_edit::Array::new().into());
}
Ok(value.split(':').map(|s| s.trim().to_string()).collect())
}
fn parse_bool(value: &str) -> Result<toml_edit::Value> {
match value.to_lowercase().as_str() {
"1" | "true" | "yes" | "y" => Ok(true.into()),
"0" | "false" | "no" | "n" => Ok(false.into()),
_ => Err(eyre!("{} must be true or false", value)),
}
}
fn parse_i64(value: &str) -> Result<toml_edit::Value> {
match value.parse::<i64>() {
Ok(value) => Ok(value.into()),
Err(_) => Err(eyre!("{} must be a number", value)),
}
}
fn parse_duration(value: &str) -> Result<toml_edit::Value> {
duration::parse_duration(value)?;
Ok(value.into())
}
static AFTER_LONG_HELP: &str = color_print::cstr!(
r#"<bold><underline>Examples:</underline></bold>
$ <bold>mise settings idiomatic_version_file=true</bold>
"#
);