forked from extern/nushell
86cd387439
# Description Our config exists both as a `Config` struct for internal consumption and as a `Value`. The latter is exposed through `$env.config` and can be both set and read. Thus we have a complex bug-prone mechanism, that reads a `Value` and then tries to plug anything where the value is unrepresentable in `Config` with the correct state from `Config`. The parsing involves therefore mutation of the `Value` in a nested `Record` structure. Previously this was wholy done manually, with indices. To enable deletion for example, things had to be iterated over from the back. Also things were indexed in a bunch of places. This was hard to read and an invitation for bugs. With #10876 we can now use `Record::retain_mut` to traverse the records, modify anything that needs fixing, and drop invalid fields. # Parts: - Error messages now consistently use the correct spans pointing to the problematic value and the paths displayed in some messages are also aligned with the keys used for lookup. - Reconstruction of values has been fixed for: - `table.padding` - `buffer_editor` - `hooks.command_not_found` - `datetime_format` (partial solution) - Fix validation of `table.padding` input so value is not set (and underflows `usize` causing `table` to run forever with negative values) - New proper types for settings. Fully validated enums instead of strings: - `config.edit_mode` -> `EditMode` - Don't fall back to vi-mode on invalid string - `config.table.mode` -> `TableMode` - there is still a fall back to `rounded` if given an invalid `TableMode` as argument to the `nu` binary - `config.completions.algorithm` -> `CompletionAlgorithm` - `config.error_style` -> `ErrorStyle` - don't implicitly fall back to `fancy` when given an invalid value. - This should also shrink the size of `Config` as instead of 4x24 bytes those fields now need only 4x1 bytes in `Config` - Completely removed macros relying on the scope of `Value::into_config` so we can break it up into smaller parts in the future. - Factored everything into smaller files with the types and helpers for particular topics. - `NuCursorShape` now explicitly expresses the `Inherit` setting. conversion to option only happens at the interface to `reedline`
111 lines
3.3 KiB
Rust
111 lines
3.3 KiB
Rust
use nu_test_support::{nu, nu_repl_code};
|
|
|
|
#[test]
|
|
fn config_is_mutable() {
|
|
let actual = nu!(nu_repl_code(&[
|
|
r"$env.config = { ls: { clickable_links: true } }",
|
|
"$env.config.ls.clickable_links = false;",
|
|
"$env.config.ls.clickable_links"
|
|
]));
|
|
|
|
assert_eq!(actual.out, "false");
|
|
}
|
|
|
|
#[test]
|
|
fn config_preserved_after_do() {
|
|
let actual = nu!(nu_repl_code(&[
|
|
r"$env.config = { ls: { clickable_links: true } }",
|
|
"do -i { $env.config.ls.clickable_links = false }",
|
|
"$env.config.ls.clickable_links"
|
|
]));
|
|
|
|
assert_eq!(actual.out, "true");
|
|
}
|
|
|
|
#[test]
|
|
fn config_affected_when_mutated() {
|
|
let actual = nu!(nu_repl_code(&[
|
|
r#"$env.config = { filesize: { metric: false, format:"auto" } }"#,
|
|
r#"$env.config = { filesize: { metric: true, format:"auto" } }"#,
|
|
"20mib | into string"
|
|
]));
|
|
|
|
assert_eq!(actual.out, "21.0 MB");
|
|
}
|
|
|
|
#[test]
|
|
fn config_affected_when_deep_mutated() {
|
|
let actual = nu!(cwd: "crates/nu-utils/src/sample_config", nu_repl_code(&[
|
|
r#"source default_config.nu"#,
|
|
r#"$env.config.filesize.metric = true"#,
|
|
r#"20mib | into string"#]));
|
|
|
|
assert_eq!(actual.out, "21.0 MB");
|
|
}
|
|
|
|
#[test]
|
|
fn config_add_unsupported_key() {
|
|
let actual = nu!(cwd: "crates/nu-utils/src/sample_config", nu_repl_code(&[
|
|
r#"source default_config.nu"#,
|
|
r#"$env.config.foo = 2"#,
|
|
r#";"#]));
|
|
|
|
assert!(actual
|
|
.err
|
|
.contains("$env.config.foo is an unknown config setting"));
|
|
}
|
|
|
|
#[test]
|
|
fn config_add_unsupported_type() {
|
|
let actual = nu!(cwd: "crates/nu-utils/src/sample_config", nu_repl_code(&[r#"source default_config.nu"#,
|
|
r#"$env.config.ls = '' "#,
|
|
r#";"#]));
|
|
|
|
assert!(actual.err.contains("should be a record"));
|
|
}
|
|
|
|
#[test]
|
|
fn config_add_unsupported_value() {
|
|
let actual = nu!(cwd: "crates/nu-utils/src/sample_config", nu_repl_code(&[r#"source default_config.nu"#,
|
|
r#"$env.config.history.file_format = ''"#,
|
|
r#";"#]));
|
|
|
|
assert!(actual
|
|
.err
|
|
.contains("unrecognized $env.config.history.file_format option ''"));
|
|
assert!(actual
|
|
.err
|
|
.contains("expected either 'sqlite' or 'plaintext'"));
|
|
}
|
|
|
|
#[test]
|
|
#[ignore = "Figure out how to make test_bins::nu_repl() continue execution after shell errors"]
|
|
fn config_unsupported_key_reverted() {
|
|
let actual = nu!(cwd: "crates/nu-utils/src/sample_config", nu_repl_code(&[r#"source default_config.nu"#,
|
|
r#"$env.config.foo = 1"#,
|
|
r#"'foo' in $env.config"#]));
|
|
|
|
assert_eq!(actual.out, "false");
|
|
}
|
|
|
|
#[test]
|
|
#[ignore = "Figure out how to make test_bins::nu_repl() continue execution after shell errors"]
|
|
fn config_unsupported_type_reverted() {
|
|
let actual = nu!(cwd: "crates/nu-utils/src/sample_config", nu_repl_code(&[r#" source default_config.nu"#,
|
|
r#"$env.config.ls = ''"#,
|
|
r#"$env.config.ls | describe"#]));
|
|
|
|
assert_eq!(actual.out, "record");
|
|
}
|
|
|
|
#[test]
|
|
#[ignore = "Figure out how to make test_bins::nu_repl() continue execution after errors"]
|
|
fn config_unsupported_value_reverted() {
|
|
let actual = nu!(cwd: "crates/nu-utils/src/sample_config", nu_repl_code(&[r#" source default_config.nu"#,
|
|
r#"$env.config.history.file_format = 'plaintext'"#,
|
|
r#"$env.config.history.file_format = ''"#,
|
|
r#"$env.config.history.file_format | to json"#]));
|
|
|
|
assert_eq!(actual.out, "\"plaintext\"");
|
|
}
|