feat: valw __check-config

This commit is contained in:
elwrcl committed 2026-10-03 03:37:45 +03:00
1 parent b294210a8f
commit 85559b1031
2 files changed
+63

No files matched your search

+56
View File
@@ -169,6 +169,20 @@ pub fn parse(text: &str) -> Result<(Config, Vec<String>)> {
Ok((config, unknown)) Ok((config, unknown))
} }
/// Checks a config file strictly, for home-manager's build: invalid values
/// and unknown keys are errors (at run time unknown keys only warn).
pub fn check(path: &Path) -> Result<()> {
let text = std::fs::read_to_string(path)
.with_context(|| format!("could not read {}", path.display()))?;
let (_, unknown) =
parse(&text).with_context(|| format!("invalid config file {}", path.display()))?;
match unknown.len() {
0 => Ok(()),
1 => bail!("unknown config key: {}", unknown[0]),
_ => bail!("unknown config keys: {}", unknown.join(", ")),
}
}
pub fn expand_home(path: &str, home: &Path) -> PathBuf { pub fn expand_home(path: &str, home: &Path) -> PathBuf {
if path == "~" || path == "$HOME" { if path == "~" || path == "$HOME" {
return home.to_path_buf(); return home.to_path_buf();
@@ -294,6 +308,48 @@ mod tests {
); );
} }
#[test]
fn check_accepts_valid_files() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("config.toml");
std::fs::write(
&path,
"[preview]\ntimeout_secs = 3\n[sound]\nvolume = 0.4\n",
)
.unwrap();
check(&path).unwrap();
std::fs::write(&path, "").unwrap();
check(&path).unwrap();
}
#[test]
fn check_rejects_invalid_values_with_valws_message() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("config.toml");
std::fs::write(&path, "[sound]\nvolume = 2.0\n").unwrap();
let err = format!("{:#}", check(&path).unwrap_err());
assert!(
err.contains("sound.volume must be between 0 and 1"),
"{err}"
);
}
#[test]
fn check_rejects_unknown_keys_by_name() {
let dir = tempfile::tempdir().unwrap();
let path = dir.path().join("config.toml");
std::fs::write(&path, "[preview]\ntimout_secs = 3\n").unwrap();
assert_eq!(
check(&path).unwrap_err().to_string(),
"unknown config key: preview.timout_secs"
);
std::fs::write(&path, "[preview]\ntimout_secs = 3\n[sund]\nx = 1\n").unwrap();
assert_eq!(
check(&path).unwrap_err().to_string(),
"unknown config keys: preview.timout_secs, sund"
);
}
#[test] #[test]
fn missing_file_gives_defaults() { fn missing_file_gives_defaults() {
let dir = tempfile::tempdir().unwrap(); let dir = tempfile::tempdir().unwrap();
+7
View File
@@ -84,6 +84,9 @@ enum Command {
/// Internal: the process that shows preview thumbnails. /// Internal: the process that shows preview thumbnails.
#[command(name = "__preview-host", hide = true)] #[command(name = "__preview-host", hide = true)]
PreviewHost, PreviewHost,
/// Internal: check a config file (home-manager runs it at build time).
#[command(name = "__check-config", hide = true)]
CheckConfig { file: PathBuf },
/// Internal: play the whole combo, for tuning the sounds by ear. /// Internal: play the whole combo, for tuning the sounds by ear.
#[command(name = "__combo-demo", hide = true)] #[command(name = "__combo-demo", hide = true)]
ComboDemo, ComboDemo,
@@ -188,6 +191,7 @@ fn run(cli: Cli) -> Result<()> {
Command::Window { common } => capture(Mode::Window, common), Command::Window { common } => capture(Mode::Window, common),
Command::Zoom { common } => capture(Mode::Zoom, common), Command::Zoom { common } => capture(Mode::Zoom, common),
Command::Edit { file } => editor::run(&file), Command::Edit { file } => editor::run(&file),
Command::CheckConfig { file } => config::check(&file),
Command::ComboDemo => sound::demo(&config::load(&config::default_path())?.sound), Command::ComboDemo => sound::demo(&config::load(&config::default_path())?.sound),
Command::Toolbar => { Command::Toolbar => {
let config = config::load(&config::default_path())?; let config = config::load(&config::default_path())?;
@@ -429,6 +433,8 @@ mod tests {
assert!(parses(&["__clipboard"])); assert!(parses(&["__clipboard"]));
assert!(parses(&["toolbar"])); assert!(parses(&["toolbar"]));
assert!(parses(&["__combo-demo"])); assert!(parses(&["__combo-demo"]));
assert!(parses(&["__check-config", "c.toml"]));
assert!(!parses(&["__check-config"]));
} }
#[test] #[test]
@@ -530,6 +536,7 @@ mod tests {
assert!(!help.contains("preview-host"), "{help}"); assert!(!help.contains("preview-host"), "{help}");
assert!(!help.contains("__clipboard"), "{help}"); assert!(!help.contains("__clipboard"), "{help}");
assert!(!help.contains("combo-demo"), "{help}"); assert!(!help.contains("combo-demo"), "{help}");
assert!(!help.contains("check-config"), "{help}");
} }
#[test] #[test]