use crate::commands::WholeStreamCommand; use crate::context::CommandRegistry; use crate::prelude::*; use nu_errors::ShellError; use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; use nu_source::Tagged; use nu_value_ext::ValueExt; #[derive(Deserialize)] struct DefaultArgs { column: Tagged, value: Value, } pub struct Default; #[async_trait] impl WholeStreamCommand for Default { fn name(&self) -> &str { "default" } fn signature(&self) -> Signature { Signature::build("default") .required("column name", SyntaxShape::String, "the name of the column") .required( "column value", SyntaxShape::Any, "the value of the column to default", ) } fn usage(&self) -> &str { "Sets a default row's column if missing." } async fn run( &self, args: CommandArgs, registry: &CommandRegistry, ) -> Result { default(args, registry).await } fn examples(&self) -> Vec { vec![Example { description: "Give a default 'target' to all file entries", example: "ls -af | default target 'nothing'", result: None, }] } } async fn default( args: CommandArgs, registry: &CommandRegistry, ) -> Result { let registry = registry.clone(); let (DefaultArgs { column, value }, input) = args.process(®istry).await?; Ok(input .map(move |item| { let should_add = match item { Value { value: UntaggedValue::Row(ref r), .. } => r.get_data(&column.item).borrow().is_none(), _ => false, }; if should_add { match item.insert_data_at_path(&column.item, value.clone()) { Some(new_value) => ReturnSuccess::value(new_value), None => ReturnSuccess::value(item), } } else { ReturnSuccess::value(item) } }) .to_output_stream()) } #[cfg(test)] mod tests { use super::Default; #[test] fn examples_work_as_expected() { use crate::examples::test as test_examples; test_examples(Default {}) } }