nu_command/system/
complete.rs1use nu_engine::command_prelude::*;
2use nu_protocol::OutDest;
3
4#[derive(Clone)]
5pub struct Complete;
6
7impl Command for Complete {
8 fn name(&self) -> &str {
9 "complete"
10 }
11
12 fn signature(&self) -> Signature {
13 Signature::build("complete")
14 .category(Category::System)
15 .input_output_types(vec![(Type::Any, Type::record())])
16 }
17
18 fn description(&self) -> &str {
19 "Capture the outputs and exit code from an external piped in command in a nushell table."
20 }
21
22 fn extra_description(&self) -> &str {
23 r#"In order to capture stdout, stderr, and exit_code, externally piped in commands need to be wrapped with `do`"#
24 }
25
26 fn run(
27 &self,
28 _engine_state: &EngineState,
29 _stack: &mut Stack,
30 call: &Call,
31 input: PipelineData,
32 ) -> Result<PipelineData, ShellError> {
33 let head = call.head;
34 match input {
35 PipelineData::ByteStream(stream, ..) => {
36 let Ok(child) = stream.into_child() else {
37 return Err(ShellError::GenericError {
38 error: "Complete only works with external commands".into(),
39 msg: "complete only works on external commands".into(),
40 span: Some(call.head),
41 help: None,
42 inner: vec![],
43 });
44 };
45
46 let output = child.wait_with_output()?;
47 let exit_code = output.exit_status.code();
48 let mut record = Record::new();
49
50 if let Some(stdout) = output.stdout {
51 record.push(
52 "stdout",
53 match String::from_utf8(stdout) {
54 Ok(str) => Value::string(str, head),
55 Err(err) => Value::binary(err.into_bytes(), head),
56 },
57 );
58 }
59
60 if let Some(stderr) = output.stderr {
61 record.push(
62 "stderr",
63 match String::from_utf8(stderr) {
64 Ok(str) => Value::string(str, head),
65 Err(err) => Value::binary(err.into_bytes(), head),
66 },
67 );
68 }
69
70 record.push("exit_code", Value::int(exit_code.into(), head));
71
72 Ok(Value::record(record, call.head).into_pipeline_data())
73 }
74 PipelineData::Value(Value::Error { error, .. }, _) => Err(*error),
76 _ => Err(ShellError::GenericError {
77 error: "Complete only works with external commands".into(),
78 msg: "complete only works on external commands".into(),
79 span: Some(head),
80 help: None,
81 inner: vec![],
82 }),
83 }
84 }
85
86 fn examples(&self) -> Vec<Example> {
87 vec![Example {
88 description: "Run the external command to completion, capturing stdout, stderr, and exit_code",
89 example: "^external arg1 | complete",
90 result: None,
91 }]
92 }
93
94 fn pipe_redirection(&self) -> (Option<OutDest>, Option<OutDest>) {
95 (Some(OutDest::PipeSeparate), Some(OutDest::PipeSeparate))
96 }
97}