nu_explore/explore/
command.rs1use crate::explore::config::ExploreConfig;
4use crate::explore::nu_common::create_lscolors;
5use crate::explore::pager::PagerConfig;
6use crate::explore::run_pager;
7use nu_ansi_term::Style;
8use nu_color_config::StyleComputer;
9use nu_engine::command_prelude::*;
10
11#[derive(Clone)]
13pub struct Explore;
14
15impl Command for Explore {
16 fn name(&self) -> &str {
17 "explore"
18 }
19
20 fn description(&self) -> &str {
21 "Explore acts as a table pager, just like `less` does for text."
22 }
23
24 fn signature(&self) -> nu_protocol::Signature {
25 Signature::build("explore")
29 .input_output_types(vec![(Type::Any, Type::Any)])
30 .named(
31 "head",
32 SyntaxShape::Boolean,
33 "Show or hide column headers (default true)",
34 None,
35 )
36 .switch("index", "Show row indexes when viewing a list", Some('i'))
37 .switch(
38 "tail",
39 "Start with the viewport scrolled to the bottom",
40 Some('t'),
41 )
42 .switch(
43 "peek",
44 "When quitting, output the value of the cell the cursor was on",
45 Some('p'),
46 )
47 .category(Category::Viewers)
48 }
49
50 fn extra_description(&self) -> &str {
51 r#"Press `:` then `h` to get a help menu."#
52 }
53
54 fn run(
55 &self,
56 engine_state: &EngineState,
57 stack: &mut Stack,
58 call: &Call,
59 input: PipelineData,
60 ) -> Result<PipelineData, ShellError> {
61 let show_head: bool = call.get_flag(engine_state, stack, "head")?.unwrap_or(true);
62 let show_index: bool = call.has_flag(engine_state, stack, "index")?;
63 let tail: bool = call.has_flag(engine_state, stack, "tail")?;
64 let peek_value: bool = call.has_flag(engine_state, stack, "peek")?;
65
66 let nu_config = stack.get_config(engine_state);
67 let style_computer = StyleComputer::from_config(engine_state, stack);
68
69 let mut explore_config = ExploreConfig::from_nu_config(&nu_config);
70 explore_config.table.show_header = show_head;
71 explore_config.table.show_index = show_index;
72 explore_config.table.separator_style = lookup_color(&style_computer, "separator");
73
74 let lscolors = create_lscolors(engine_state, stack);
75 let cwd = engine_state.cwd(Some(stack)).map_or(String::new(), |path| {
76 path.to_str().unwrap_or("").to_string()
77 });
78
79 let config = PagerConfig::new(
80 &nu_config,
81 &explore_config,
82 &style_computer,
83 &lscolors,
84 peek_value,
85 tail,
86 &cwd,
87 );
88
89 let result = run_pager(engine_state, &mut stack.clone(), input, config);
90
91 match result {
92 Ok(Some(value)) => Ok(PipelineData::value(value, None)),
93 Ok(None) => Ok(PipelineData::value(Value::default(), None)),
94 Err(err) => {
95 let shell_error = match err.downcast::<ShellError>() {
96 Ok(e) => e,
97 Err(e) => ShellError::GenericError {
98 error: e.to_string(),
99 msg: "".into(),
100 span: None,
101 help: None,
102 inner: vec![],
103 },
104 };
105
106 Ok(PipelineData::value(
107 Value::error(shell_error, call.head),
108 None,
109 ))
110 }
111 }
112 }
113
114 fn examples(&self) -> Vec<Example<'_>> {
115 vec![
116 Example {
117 description: "Explore the system host information record",
118 example: r#"sys host | explore"#,
119 result: None,
120 },
121 Example {
122 description: "Explore the output of `ls` without column names",
123 example: r#"ls | explore --head false"#,
124 result: None,
125 },
126 Example {
127 description: "Explore a list of Markdown files' contents, with row indexes",
128 example: r#"glob *.md | each {|| open } | explore --index"#,
129 result: None,
130 },
131 Example {
132 description: "Explore a JSON file, then save the last visited sub-structure to a file",
133 example: r#"open file.json | explore --peek | to json | save part.json"#,
134 result: None,
135 },
136 ]
137 }
138}
139
140fn lookup_color(style_computer: &StyleComputer, key: &str) -> Style {
141 style_computer.compute(key, &Value::nothing(Span::unknown()))
142}