diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-10 17:11:50 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-10 17:28:31 +0300 |
| commit | 3e8f9df14e6dd08a8d80d920b923870a80649f0b (patch) | |
| tree | ea854ca617d1ca21a09d1e7aa9246ffc5f6e842b /src/config | |
| parent | 66be0b655fe922867f1eed100a41d67038b6ffd6 (diff) | |
fix: improve config diagnostic delivery
Diffstat (limited to 'src/config')
| -rw-r--r-- | src/config/io.rs | 66 |
1 files changed, 53 insertions, 13 deletions
diff --git a/src/config/io.rs b/src/config/io.rs index f8c2eb90..6a4e83ce 100644 --- a/src/config/io.rs +++ b/src/config/io.rs @@ -154,22 +154,36 @@ pub fn config_path() -> PathBuf { } pub fn config_diagnostic_summary(diagnostics: &[String]) -> Option<String> { - const MAX_VISIBLE_DIAGNOSTICS: usize = 4; - if diagnostics.is_empty() { return None; } - let mut lines: Vec<String> = diagnostics + let target = config_path() + .file_name() + .and_then(|name| name.to_str()) + .unwrap_or("config.toml") + .to_string(); + let location = diagnostics .iter() - .take(MAX_VISIBLE_DIAGNOSTICS) - .map(|diagnostic| diagnostic.split_whitespace().collect::<Vec<_>>().join(" ")) - .collect(); - let hidden = diagnostics.len().saturating_sub(MAX_VISIBLE_DIAGNOSTICS); - if hidden > 0 { - lines.push(format!("and {hidden} more config warnings")); - } - Some(lines.join("\n")) + .find_map(|diagnostic| toml_error_location(diagnostic)) + .map(|(line, column)| format!("{target}:{line}:{column}")) + .unwrap_or_else(|| target.to_string()); + + Some(format!("{location}; herdr config check")) +} + +fn toml_error_location(diagnostic: &str) -> Option<(usize, usize)> { + let marker = "TOML parse error at line "; + let start = diagnostic.find(marker)? + marker.len(); + let rest = &diagnostic[start..]; + let (line, rest) = rest.split_once(", column ")?; + let column = rest + .split(|c: char| !c.is_ascii_digit()) + .next() + .unwrap_or_default(); + let line = line.parse().ok()?; + let column = column.parse().ok()?; + Some((line, column)) } pub fn load_live_config() -> Result<LoadedConfig, Vec<String>> { @@ -576,7 +590,7 @@ mod tests { } #[test] - fn config_diagnostic_summary_keeps_multiple_warnings_visible() { + fn config_diagnostic_summary_uses_compact_actionable_banner() { let diagnostics = vec![ "one".to_string(), "two".to_string(), @@ -587,7 +601,33 @@ mod tests { assert_eq!( config_diagnostic_summary(&diagnostics).as_deref(), - Some("one\ntwo\nthree\nfour\nand 1 more config warnings") + Some("config.toml; herdr config check") + ); + } + + #[test] + fn config_diagnostic_summary_includes_toml_error_location() { + let diagnostics = vec![ + "config parse error: TOML parse error at line 33, column 8\n |\n33 | type = \"popup\"\n | ^^^^^^^\nunknown variant `popup`; using defaults" + .to_string(), + ]; + + assert_eq!( + config_diagnostic_summary(&diagnostics).as_deref(), + Some("config.toml:33:8; herdr config check") + ); + } + + #[test] + fn config_diagnostic_summary_finds_location_after_warning() { + let diagnostics = vec![ + "unknown config section [toast]; ignoring section".to_string(), + "config parse error: TOML parse error at line 7, column 4".to_string(), + ]; + + assert_eq!( + config_diagnostic_summary(&diagnostics).as_deref(), + Some("config.toml:7:4; herdr config check") ); } |
