1#![doc = include_str!("../README.md")]
2mod commands;
3mod default_context;
4mod explore;
5mod explore_regex;
6mod nu_common;
7mod pager;
8mod registry;
9mod views;
10
11use anyhow::Result;
12use commands::{ExpandCmd, HelpCmd, NuCmd, QuitCmd, TableCmd, TryCmd};
13use crossterm::terminal::size;
14pub use default_context::add_explore_context;
15pub use explore::Explore;
16use explore::ExploreConfig;
17use explore_regex::ExploreRegex;
18use nu_common::{collect_pipeline, has_simple_value};
19use nu_protocol::{
20 PipelineData, Value,
21 engine::{EngineState, Stack},
22};
23use pager::{Page, Pager, PagerConfig};
24use registry::CommandRegistry;
25use views::{BinaryView, Orientation, Preview, RecordView};
26
27mod util {
28 pub use super::nu_common::{create_lscolors, create_map};
29}
30
31fn run_pager(
32 engine_state: &EngineState,
33 stack: &mut Stack,
34 input: PipelineData,
35 config: PagerConfig,
36) -> Result<Option<Value>> {
37 let mut p = Pager::new(config.clone());
38 let commands = create_command_registry();
39
40 let is_record = matches!(input, PipelineData::Value(Value::Record { .. }, ..));
41 let is_binary = matches!(
42 input,
43 PipelineData::Value(Value::Binary { .. }, ..) | PipelineData::ByteStream(..)
44 );
45
46 if is_binary {
47 p.show_message("For help type :help");
48
49 let view = binary_view(input, config.explore_config)?;
50 return p.run(engine_state, stack, Some(view), commands);
51 }
52
53 let (columns, data) = collect_pipeline(input)?;
54
55 let has_no_input = columns.is_empty() && data.is_empty();
56 if has_no_input {
57 return p.run(engine_state, stack, help_view(), commands);
58 }
59
60 p.show_message("For help type :help");
61
62 if let Some(value) = has_simple_value(&data) {
63 let text = value.to_abbreviated_string(config.nu_config);
64 let view = Some(Page::new(Preview::new(&text), false));
65 return p.run(engine_state, stack, view, commands);
66 }
67
68 let view = create_record_view(columns, data, is_record, config);
69 p.run(engine_state, stack, view, commands)
70}
71
72fn create_record_view(
73 columns: Vec<String>,
74 data: Vec<Vec<Value>>,
75 is_record: bool,
77 config: PagerConfig,
78) -> Option<Page> {
79 let mut view = RecordView::new(columns, data, config.explore_config.clone());
80 if is_record {
81 view.set_top_layer_orientation(Orientation::Left);
82 }
83
84 if config.tail
85 && let Ok((w, h)) = size()
86 {
87 view.tail(w, h);
88 }
89
90 Some(Page::new(view, true))
91}
92
93fn help_view() -> Option<Page> {
94 Some(Page::new(HelpCmd::view(), false))
95}
96
97fn binary_view(input: PipelineData, config: &ExploreConfig) -> Result<Page> {
98 let data = match input {
99 PipelineData::Value(Value::Binary { val, .. }, _) => val,
100 PipelineData::ByteStream(bs, _) => bs.into_bytes()?,
101 _ => unreachable!("checked beforehand"),
102 };
103
104 let view = BinaryView::new(data, config);
105
106 Ok(Page::new(view, true))
107}
108
109fn create_command_registry() -> CommandRegistry {
110 let mut registry = CommandRegistry::new();
111 create_commands(&mut registry);
112 create_aliases(&mut registry);
113
114 registry
115}
116
117fn create_commands(registry: &mut CommandRegistry) {
118 registry.register_command_view(NuCmd::new(), true);
119 registry.register_command_view(TableCmd::new(), true);
120
121 registry.register_command_view(ExpandCmd::new(), false);
122 registry.register_command_view(TryCmd::new(), false);
123 registry.register_command_view(HelpCmd::default(), false);
124
125 registry.register_command_reactive(QuitCmd);
126}
127
128fn create_aliases(registry: &mut CommandRegistry) {
129 registry.create_aliases("h", HelpCmd::NAME);
130 registry.create_aliases("e", ExpandCmd::NAME);
131 registry.create_aliases("q", QuitCmd::NAME);
132 registry.create_aliases("q!", QuitCmd::NAME);
133}