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