From fa88527f778907ebaa75ea929ba516d6784b00c4 Mon Sep 17 00:00:00 2001 From: Ilya Grigoriev Date: Fri, 28 Mar 2025 19:44:22 -0700 Subject: [PATCH] cli `--config` global option: allow spaces around `=` This is especially useful for complicated options like ``` --config 'revsets."immutable_heads()" = "none()"' ``` --- CHANGELOG.md | 3 +++ cli/src/config.rs | 29 ++++++++++++++++++++++++----- cli/tests/test_global_opts.rs | 8 ++++++++ docs/config.md | 1 - 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bc091ddb..4d7bcbd80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -89,6 +89,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). reversing colors rather than underlining, you can set `colors."diff token"={ underline = false, reverse = true }` in your config. +* The `--config` global option now allows whitespace around the equals sign, e.g. + `--config 'revsets."immutable_heads()" = "none()"'` is now legal. + ### Fixed bugs * `jj log -p --stat` now shows diff stats as well as the default color-words/git diff --git a/cli/src/config.rs b/cli/src/config.rs index 3fa23d9ae..879e314e3 100644 --- a/cli/src/config.rs +++ b/cli/src/config.rs @@ -579,7 +579,9 @@ fn parse_config_arg_item(item_str: &str) -> Result<(ConfigNamePathBuf, ConfigVal let split_candidates = item_str.as_bytes().iter().positions(|&b| b == b'='); let Some((name, value_str)) = split_candidates .map(|p| (&item_str[..p], &item_str[p + 1..])) - .map(|(name, value)| name.parse().map(|name| (name, value))) + // Trim spaces, similarly to TOML syntax; names or values with spaces would have to be + // specified with quotes. + .map(|(name, value)| name.trim().parse().map(|name| (name, value.trim()))) .find_or_last(Result::is_ok) .transpose() .map_err(|err| config_error_with_message("--config name cannot be parsed", err))? @@ -827,21 +829,38 @@ mod tests { assert!(parse_config_arg_item("").is_err()); assert!(parse_config_arg_item("a").is_err()); assert!(parse_config_arg_item("=").is_err()); - // The value parser is sensitive to leading whitespaces, which seems - // good because the parsing falls back to a bare string. - assert!(parse_config_arg_item("a = 'b'").is_err()); let (name, value) = parse_config_arg_item("a=b").unwrap(); assert_eq!(name, ConfigNamePathBuf::from_iter(["a"])); assert_eq!(value.as_str(), Some("b")); + let (name, value) = parse_config_arg_item("a = b").unwrap(); + assert_eq!(name, ConfigNamePathBuf::from_iter(["a"])); + assert_eq!(value.as_str(), Some("b")); + + let (name, value) = parse_config_arg_item("a = 'b'").unwrap(); + assert_eq!(name, ConfigNamePathBuf::from_iter(["a"])); + assert_eq!(value.as_str(), Some("b")); + + let (name, value) = parse_config_arg_item("a = ' '").unwrap(); + assert_eq!(name, ConfigNamePathBuf::from_iter(["a"])); + assert_eq!(value.as_str(), Some(" ")); + + let (name, value) = + parse_config_arg_item(r#"revsets."immutable_heads()" = "none()""#).unwrap(); + assert_eq!( + name, + ConfigNamePathBuf::from_iter(["revsets", "immutable_heads()"]) + ); + assert_eq!(value.as_str(), Some("none()")); + let (name, value) = parse_config_arg_item("a=").unwrap(); assert_eq!(name, ConfigNamePathBuf::from_iter(["a"])); assert_eq!(value.as_str(), Some("")); let (name, value) = parse_config_arg_item("a= ").unwrap(); assert_eq!(name, ConfigNamePathBuf::from_iter(["a"])); - assert_eq!(value.as_str(), Some(" ")); + assert_eq!(value.as_str(), Some("")); // This one is a bit cryptic, but b=c can be a bare string. let (name, value) = parse_config_arg_item("a=b=c").unwrap(); diff --git a/cli/tests/test_global_opts.rs b/cli/tests/test_global_opts.rs index 6eb0d97ac..071ad833e 100644 --- a/cli/tests/test_global_opts.rs +++ b/cli/tests/test_global_opts.rs @@ -462,6 +462,14 @@ fn test_color_config() { [EOF] "); + // Spaces around the = signs or dots are OK, by analogy with TOML + let output = work_dir.run_jj(["--config= ui . color = never", "log", "-T", "commit_id"]); + insta::assert_snapshot!(output, @r" + @ 230dd059e1b059aefc0da06a2e5a7dbf22362f22 + ◆ 0000000000000000000000000000000000000000 + [EOF] + "); + // --color overrides --config 'ui.color=...'. let output = work_dir.run_jj([ "--color", diff --git a/docs/config.md b/docs/config.md index 6290d50fa..e20e214ac 100644 --- a/docs/config.md +++ b/docs/config.md @@ -1573,7 +1573,6 @@ to specify additional configuration settings. This overrides settings defined in config files or environment variables. For example, ```shell -# Must not have spaces around the `=` jj --config ui.color=always --config ui.diff-editor=meld split ```