nu_cli/
nu_highlight.rs

1use std::sync::Arc;
2
3use nu_engine::command_prelude::*;
4use reedline::{Highlighter, StyledText};
5
6use crate::syntax_highlight::highlight_syntax;
7
8#[derive(Clone)]
9pub struct NuHighlight;
10
11impl Command for NuHighlight {
12    fn name(&self) -> &str {
13        "nu-highlight"
14    }
15
16    fn signature(&self) -> Signature {
17        Signature::build("nu-highlight")
18            .category(Category::Strings)
19            .switch(
20                "reject-garbage",
21                "Return an error if invalid syntax (garbage) was encountered",
22                Some('r'),
23            )
24            .input_output_types(vec![(Type::String, Type::String)])
25    }
26
27    fn description(&self) -> &str {
28        "Syntax highlight the input string."
29    }
30
31    fn search_terms(&self) -> Vec<&str> {
32        vec!["syntax", "color", "convert"]
33    }
34
35    fn run(
36        &self,
37        engine_state: &EngineState,
38        stack: &mut Stack,
39        call: &Call,
40        input: PipelineData,
41    ) -> Result<PipelineData, ShellError> {
42        let reject_garbage = call.has_flag(engine_state, stack, "reject-garbage")?;
43        let head = call.head;
44
45        let signals = engine_state.signals();
46
47        let engine_state = Arc::new(engine_state.clone());
48        let stack = Arc::new(stack.clone());
49
50        input.map(
51            move |x| match x.coerce_into_string() {
52                Ok(line) => {
53                    let result = highlight_syntax(&engine_state, &stack, &line, line.len());
54
55                    let highlights = match (reject_garbage, result.found_garbage) {
56                        (false, _) => result.text,
57                        (true, None) => result.text,
58                        (true, Some(span)) => {
59                            let error = ShellError::OutsideSpannedLabeledError {
60                                src: line,
61                                error: "encountered invalid syntax while highlighting".into(),
62                                msg: "invalid syntax".into(),
63                                span,
64                            };
65                            return Value::error(error, head);
66                        }
67                    };
68
69                    Value::string(highlights.render_simple(), head)
70                }
71                Err(err) => Value::error(err, head),
72            },
73            signals,
74        )
75    }
76
77    fn examples(&self) -> Vec<Example<'_>> {
78        vec![Example {
79            description: "Describe the type of a string",
80            example: "'let x = 3' | nu-highlight",
81            result: None,
82        }]
83    }
84}
85
86/// A highlighter that does nothing
87///
88/// Used to remove highlighting from a reedline instance
89/// (letting NuHighlighter structs be dropped)
90#[derive(Default)]
91pub struct NoOpHighlighter {}
92
93impl Highlighter for NoOpHighlighter {
94    fn highlight(&self, _line: &str, _cursor: usize) -> reedline::StyledText {
95        StyledText::new()
96    }
97}