feat: print-config subset of config (#3179)
* feat: print-config subset of config * only print format helpers with format config * improve help text * also change argument name
This commit is contained in:
parent
9d443dff9f
commit
c3e33ea1c7
151
src/configure.rs
151
src/configure.rs
|
@ -73,7 +73,7 @@ fn handle_update_configuration(doc: &mut Document, name: &str, value: &str) -> R
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_configuration(use_default: bool) {
|
pub fn print_configuration(use_default: bool, paths: &[&str]) {
|
||||||
let config = if use_default {
|
let config = if use_default {
|
||||||
// Get default config
|
// Get default config
|
||||||
let default_config = crate::configs::FullConfig::default();
|
let default_config = crate::configs::FullConfig::default();
|
||||||
|
@ -88,31 +88,100 @@ pub fn print_configuration(use_default: bool) {
|
||||||
toml::value::Value::try_from(user_config).unwrap()
|
toml::value::Value::try_from(user_config).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let string_config = toml::to_string_pretty(&config).unwrap();
|
|
||||||
|
|
||||||
println!("# Warning: This config does not include keys that have an unset value\n");
|
println!("# Warning: This config does not include keys that have an unset value\n");
|
||||||
println!(
|
|
||||||
"# $all is shorthand for {}",
|
|
||||||
PROMPT_ORDER
|
|
||||||
.iter()
|
|
||||||
.map(|module_name| format!("${}", module_name))
|
|
||||||
.collect::<String>()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Unwrapping is fine because config is based on FullConfig
|
// These are only used for format specifiers so don't print them if we aren't showing formats.
|
||||||
let custom_modules = config.get("custom").unwrap().as_table().unwrap();
|
if paths.is_empty()
|
||||||
if !use_default && !custom_modules.is_empty() {
|
|| paths
|
||||||
|
.iter()
|
||||||
|
.any(|&path| path == "format" || path == "right_format")
|
||||||
|
{
|
||||||
println!(
|
println!(
|
||||||
"# $custom (excluding any modules already listed in `format`) is shorthand for {}",
|
"# $all is shorthand for {}",
|
||||||
custom_modules
|
PROMPT_ORDER
|
||||||
.keys()
|
.iter()
|
||||||
.map(|module_name| format!("${{custom.{}}}", module_name))
|
.map(|module_name| format!("${}", module_name))
|
||||||
.collect::<String>()
|
.collect::<String>()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Unwrapping is fine because config is based on FullConfig
|
||||||
|
let custom_modules = config.get("custom").unwrap().as_table().unwrap();
|
||||||
|
if !use_default && !custom_modules.is_empty() {
|
||||||
|
println!(
|
||||||
|
"# $custom (excluding any modules already listed in `format`) is shorthand for {}",
|
||||||
|
custom_modules
|
||||||
|
.keys()
|
||||||
|
.map(|module_name| format!("${{custom.{}}}", module_name))
|
||||||
|
.collect::<String>()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let print_config = if paths.is_empty() {
|
||||||
|
config
|
||||||
|
} else {
|
||||||
|
extract_toml_paths(config, paths)
|
||||||
|
};
|
||||||
|
|
||||||
|
let string_config = toml::to_string_pretty(&print_config).unwrap();
|
||||||
|
|
||||||
println!("{}", string_config);
|
println!("{}", string_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn extract_toml_paths(mut config: toml::Value, paths: &[&str]) -> toml::Value {
|
||||||
|
// Extract all the requested sections into a new configuration.
|
||||||
|
let mut subset = toml::value::Table::new();
|
||||||
|
let config = if let Some(config) = config.as_table_mut() {
|
||||||
|
config
|
||||||
|
} else {
|
||||||
|
// This function doesn't make any sense if the root is not a table.
|
||||||
|
return toml::Value::Table(subset);
|
||||||
|
};
|
||||||
|
|
||||||
|
'paths: for &path in paths {
|
||||||
|
let path_segments: Vec<_> = path.split('.').collect();
|
||||||
|
let (&end, parents) = path_segments.split_last().unwrap_or((&"", &[]));
|
||||||
|
|
||||||
|
// Locate the parent table to remove the value from.
|
||||||
|
let mut source_cursor = &mut *config;
|
||||||
|
for &segment in parents {
|
||||||
|
source_cursor = if let Some(child) = source_cursor
|
||||||
|
.get_mut(segment)
|
||||||
|
.and_then(|value| value.as_table_mut())
|
||||||
|
{
|
||||||
|
child
|
||||||
|
} else {
|
||||||
|
// We didn't find a value for this path, so move on to the next path.
|
||||||
|
continue 'paths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract the value to move.
|
||||||
|
let value = if let Some(value) = source_cursor.remove(end) {
|
||||||
|
value
|
||||||
|
} else {
|
||||||
|
// We didn't find a value for this path, so move on to the next path.
|
||||||
|
continue 'paths;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create a destination for that value.
|
||||||
|
let mut destination_cursor = &mut subset;
|
||||||
|
for &segment in &path_segments[..path_segments.len() - 1] {
|
||||||
|
// Because we initialize `subset` to be a table, and only add additional values that
|
||||||
|
// exist in `config`, it's impossible for the value here to not be a table.
|
||||||
|
destination_cursor = destination_cursor
|
||||||
|
.entry(segment)
|
||||||
|
.or_insert_with(|| toml::Value::Table(toml::value::Table::new()))
|
||||||
|
.as_table_mut()
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
destination_cursor.insert(end.to_owned(), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
toml::Value::Table(subset)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn toggle_configuration(name: &str, key: &str) {
|
pub fn toggle_configuration(name: &str, key: &str) {
|
||||||
let mut doc = get_configuration_edit();
|
let mut doc = get_configuration_edit();
|
||||||
|
|
||||||
|
@ -306,6 +375,54 @@ mod tests {
|
||||||
assert_eq!(STD_EDITOR, actual);
|
assert_eq!(STD_EDITOR, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_extract_toml_paths() {
|
||||||
|
let config = toml::toml! {
|
||||||
|
extract_root = true
|
||||||
|
ignore_root = false
|
||||||
|
|
||||||
|
[extract_section]
|
||||||
|
ok = true
|
||||||
|
|
||||||
|
[extract_section.subsection]
|
||||||
|
ok = true
|
||||||
|
|
||||||
|
[ignore_section]
|
||||||
|
ok = false
|
||||||
|
|
||||||
|
[extract_subsection]
|
||||||
|
ok = false
|
||||||
|
|
||||||
|
[extract_subsection.extracted]
|
||||||
|
ok = true
|
||||||
|
|
||||||
|
[extract_subsection.ignored]
|
||||||
|
ok = false
|
||||||
|
};
|
||||||
|
let expected_config = toml::toml! {
|
||||||
|
extract_root = true
|
||||||
|
|
||||||
|
[extract_section]
|
||||||
|
ok = true
|
||||||
|
|
||||||
|
[extract_section.subsection]
|
||||||
|
ok = true
|
||||||
|
|
||||||
|
[extract_subsection.extracted]
|
||||||
|
ok = true
|
||||||
|
};
|
||||||
|
let actual_config = extract_toml_paths(
|
||||||
|
config,
|
||||||
|
&[
|
||||||
|
"extract_root",
|
||||||
|
"extract_section",
|
||||||
|
"extract_subsection.extracted",
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(expected_config, actual_config);
|
||||||
|
}
|
||||||
|
|
||||||
fn create_doc() -> Document {
|
fn create_doc() -> Document {
|
||||||
let config = concat!(
|
let config = concat!(
|
||||||
" # comment\n",
|
" # comment\n",
|
||||||
|
|
12
src/main.rs
12
src/main.rs
|
@ -166,6 +166,12 @@ fn main() {
|
||||||
.long("default")
|
.long("default")
|
||||||
.help("Print the default instead of the computed config")
|
.help("Print the default instead of the computed config")
|
||||||
.takes_value(false),
|
.takes_value(false),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("name")
|
||||||
|
.help("Configuration keys to print")
|
||||||
|
.multiple(true)
|
||||||
|
.required(false),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
|
@ -265,7 +271,11 @@ fn main() {
|
||||||
}
|
}
|
||||||
("print-config", Some(sub_m)) => {
|
("print-config", Some(sub_m)) => {
|
||||||
let print_default = sub_m.is_present("default");
|
let print_default = sub_m.is_present("default");
|
||||||
configure::print_configuration(print_default)
|
let paths = sub_m
|
||||||
|
.values_of("name")
|
||||||
|
.map(|paths| paths.collect::<Vec<&str>>())
|
||||||
|
.unwrap_or_default();
|
||||||
|
configure::print_configuration(print_default, &paths)
|
||||||
}
|
}
|
||||||
("toggle", Some(sub_m)) => {
|
("toggle", Some(sub_m)) => {
|
||||||
if let Some(name) = sub_m.value_of("name") {
|
if let Some(name) = sub_m.value_of("name") {
|
||||||
|
|
Loading…
Reference in New Issue