Skip to main content

nu_cmd_lang/core_commands/
try_.rs

1use nu_engine::command_prelude::*;
2use nu_protocol::engine::CommandType;
3
4#[derive(Clone)]
5pub struct Try;
6
7impl Command for Try {
8    fn name(&self) -> &str {
9        "try"
10    }
11
12    fn description(&self) -> &str {
13        "Try to run a block, if it fails optionally run a catch closure."
14    }
15
16    fn signature(&self) -> nu_protocol::Signature {
17        Signature::build("try")
18            .input_output_types(vec![(Type::Any, Type::Any)])
19            .required("try_block", SyntaxShape::Block, "Block to run.")
20            .optional(
21                "catch",
22                SyntaxShape::OneOf(vec![
23                    SyntaxShape::Keyword(
24                        b"catch".to_vec(),
25                        Box::new(SyntaxShape::OneOf(vec![
26                            SyntaxShape::Closure(None),
27                            SyntaxShape::Closure(Some(vec![SyntaxShape::Any])),
28                        ])),
29                    ),
30                    SyntaxShape::Keyword(
31                        b"finally".to_vec(),
32                        Box::new(SyntaxShape::OneOf(vec![
33                            SyntaxShape::Closure(None),
34                            SyntaxShape::Closure(Some(vec![SyntaxShape::Any])),
35                        ])),
36                    ),
37                ]),
38                "Closure to run if try block fails.",
39            )
40            .optional(
41                "finally",
42                SyntaxShape::OneOf(vec![
43                    SyntaxShape::Keyword(
44                        b"catch".to_vec(),
45                        Box::new(SyntaxShape::OneOf(vec![
46                            SyntaxShape::Closure(None),
47                            SyntaxShape::Closure(Some(vec![SyntaxShape::Any])),
48                        ])),
49                    ),
50                    SyntaxShape::Keyword(
51                        b"finally".to_vec(),
52                        Box::new(SyntaxShape::OneOf(vec![
53                            SyntaxShape::Closure(None),
54                            SyntaxShape::Closure(Some(vec![SyntaxShape::Any])),
55                        ])),
56                    ),
57                ]),
58                "Closure to run anyway.",
59            )
60            .category(Category::Core)
61    }
62
63    fn extra_description(&self) -> &str {
64        r#"This command is a parser keyword. For details, check:
65  https://www.nushell.sh/book/thinking_in_nu.html"#
66    }
67
68    fn command_type(&self) -> CommandType {
69        CommandType::Keyword
70    }
71
72    fn run(
73        &self,
74        _engine_state: &EngineState,
75        _stack: &mut Stack,
76        _call: &Call,
77        _input: PipelineData,
78    ) -> Result<PipelineData, ShellError> {
79        // This is compiled specially by the IR compiler. The code here is never used when
80        // running in IR mode.
81        eprintln!(
82            "Tried to execute 'run' for the 'try' command: this code path should never be reached in IR mode"
83        );
84        unreachable!();
85    }
86
87    fn examples(&self) -> Vec<Example<'_>> {
88        vec![
89            Example {
90                description: "Try to run a division by zero.",
91                example: "try { 1 / 0 }",
92                result: None,
93            },
94            Example {
95                description: "Try to run a division by zero and return a string instead.",
96                example: "try { 1 / 0 } catch { 'divided by zero' }",
97                result: Some(Value::test_string("divided by zero")),
98            },
99            Example {
100                description: "Try to run a division by zero and report the message.",
101                example: "try { 1 / 0 } catch { |err| $err.msg }",
102                result: None,
103            },
104            Example {
105                description: "Try to run a division by zero, report the message, and run finally",
106                example: "try { 1 / 0 } catch { |err| print $err.msg } finally { 'clean' }",
107                result: None,
108            },
109        ]
110    }
111}
112
113#[cfg(test)]
114mod test {
115    use super::*;
116
117    #[test]
118    fn test_examples() {
119        use crate::test_examples;
120
121        test_examples(Try {})
122    }
123}