nu_cmd_base/
input_handler.rs1use nu_protocol::{PipelineData, ShellError, Signals, Span, Value, ast::CellPath};
2use std::sync::Arc;
3
4pub trait CmdArgument {
5 fn take_cell_paths(&mut self) -> Option<Vec<CellPath>>;
6}
7
8pub struct CellPathOnlyArgs {
13 cell_paths: Option<Vec<CellPath>>,
14}
15
16impl CmdArgument for CellPathOnlyArgs {
17 fn take_cell_paths(&mut self) -> Option<Vec<CellPath>> {
18 self.cell_paths.take()
19 }
20}
21
22impl From<Vec<CellPath>> for CellPathOnlyArgs {
23 fn from(cell_paths: Vec<CellPath>) -> Self {
24 Self {
25 cell_paths: (!cell_paths.is_empty()).then_some(cell_paths),
26 }
27 }
28}
29
30pub fn operate<C, A>(
39 cmd: C,
40 mut arg: A,
41 input: PipelineData,
42 span: Span,
43 signals: &Signals,
44) -> Result<PipelineData, ShellError>
45where
46 A: CmdArgument + Send + Sync + 'static,
47 C: Fn(&Value, &A, Span) -> Value + Send + Sync + 'static + Clone + Copy,
48{
49 match arg.take_cell_paths() {
50 None => input.map(
51 move |v| {
52 match v {
53 Value::Error { .. } => v,
55 _ => cmd(&v, &arg, span),
56 }
57 },
58 signals,
59 ),
60 Some(column_paths) => {
61 let arg = Arc::new(arg);
62 input.map(
63 move |mut v| {
64 for path in &column_paths {
65 let opt = arg.clone();
66 let r = v.update_cell_path(
67 &path.members,
68 Box::new(move |old| {
69 match old {
70 Value::Error { .. } => old.clone(),
72 _ => cmd(old, &opt, span),
73 }
74 }),
75 );
76 if let Err(error) = r {
77 return Value::error(error, span);
78 }
79 }
80 v
81 },
82 signals,
83 )
84 }
85 }
86}