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