mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-23 02:05:33 +07:00
Implement include optional=true (#3022)
* feat(niri): support `include optional=true "filename.kdl"` * chore: warn if optional include ENOENT * chore: validate include directive arguments and properties Add proper validation to reject: - Extra arguments beyond the path - Unknown properties (other than "optional") - Unexpected child nodes * docs: implement suggested typographical/prose changes * fixes --------- Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
This commit is contained in:
+55
-5
@@ -291,7 +291,51 @@ where
|
||||
}
|
||||
|
||||
"include" => {
|
||||
let path: PathBuf = utils::parse_arg_node("include", node, ctx)?;
|
||||
// Parse the path argument
|
||||
let mut iter_args = node.arguments.iter();
|
||||
let path_val = iter_args.next().ok_or_else(|| {
|
||||
DecodeError::missing(
|
||||
node,
|
||||
"additional argument for include path is required",
|
||||
)
|
||||
})?;
|
||||
let path: PathBuf = knuffel::traits::DecodeScalar::decode(path_val, ctx)?;
|
||||
|
||||
// Check for extra arguments
|
||||
if let Some(val) = iter_args.next() {
|
||||
ctx.emit_error(DecodeError::unexpected(
|
||||
&val.literal,
|
||||
"argument",
|
||||
"unexpected argument",
|
||||
));
|
||||
}
|
||||
|
||||
// Parse the optional property
|
||||
let mut optional = false;
|
||||
for (name, val) in &node.properties {
|
||||
match &***name {
|
||||
"optional" => {
|
||||
optional = knuffel::traits::DecodeScalar::decode(val, ctx)?;
|
||||
}
|
||||
name_str => {
|
||||
ctx.emit_error(DecodeError::unexpected(
|
||||
name,
|
||||
"property",
|
||||
format!("unexpected property `{}`", name_str.escape_default()),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for unexpected children
|
||||
for child in node.children() {
|
||||
ctx.emit_error(DecodeError::unexpected(
|
||||
child,
|
||||
"node",
|
||||
format!("unexpected node `{}`", child.node_name.escape_default()),
|
||||
));
|
||||
}
|
||||
|
||||
let base = ctx.get::<BasePath>().unwrap();
|
||||
let path = base.0.join(path);
|
||||
|
||||
@@ -369,10 +413,16 @@ where
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
ctx.emit_error(DecodeError::missing(
|
||||
node,
|
||||
format!("failed to read included config from {path:?}: {err}"),
|
||||
));
|
||||
if optional && err.kind() == std::io::ErrorKind::NotFound {
|
||||
// Warn about missing optional includes
|
||||
warn!("optional include not found: {path:?}");
|
||||
} else {
|
||||
// Report all other errors normally
|
||||
ctx.emit_error(DecodeError::missing(
|
||||
node,
|
||||
format!("failed to read included config from {path:?}: {err}"),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user