This PR fixes an issue with `explore` where you can "drill down" into the same value forever. For example: 1. Run `ls | explore` 2. Press Enter to enter cursor mode 3. Press Enter again to open the selected string in a new layer 4. Press Enter again to open that string in a new layer 5. Press Enter again to open that string in a new layer 6. Repeat and eventually you have a bajillion layers open with the same string IMO it only makes sense to "drill down" into lists and records. In a separate commit I also did a little refactoring, cleaning up naming and comments.
130 lines
3.2 KiB
Rust
130 lines
3.2 KiB
Rust
use super::ViewCommand;
|
|
use crate::{
|
|
nu_common::{collect_pipeline, has_simple_value, run_command_with_value},
|
|
pager::Frame,
|
|
views::{Layout, Orientation, Preview, RecordView, View, ViewConfig},
|
|
};
|
|
use anyhow::Result;
|
|
use nu_protocol::{
|
|
engine::{EngineState, Stack},
|
|
PipelineData, Value,
|
|
};
|
|
use ratatui::layout::Rect;
|
|
|
|
#[derive(Debug, Default, Clone)]
|
|
pub struct NuCmd {
|
|
command: String,
|
|
}
|
|
|
|
impl NuCmd {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
command: String::new(),
|
|
}
|
|
}
|
|
|
|
pub const NAME: &'static str = "nu";
|
|
}
|
|
|
|
impl ViewCommand for NuCmd {
|
|
type View = NuView;
|
|
|
|
fn name(&self) -> &'static str {
|
|
Self::NAME
|
|
}
|
|
|
|
fn usage(&self) -> &'static str {
|
|
""
|
|
}
|
|
|
|
fn parse(&mut self, args: &str) -> Result<()> {
|
|
args.trim().clone_into(&mut self.command);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn spawn(
|
|
&mut self,
|
|
engine_state: &EngineState,
|
|
stack: &mut Stack,
|
|
value: Option<Value>,
|
|
) -> Result<Self::View> {
|
|
let value = value.unwrap_or_default();
|
|
|
|
let pipeline = run_command_with_value(&self.command, &value, engine_state, stack)?;
|
|
|
|
let is_record = matches!(pipeline, PipelineData::Value(Value::Record { .. }, ..));
|
|
|
|
let (columns, values) = collect_pipeline(pipeline)?;
|
|
|
|
if let Some(value) = has_simple_value(&values) {
|
|
let text = value.to_abbreviated_string(&engine_state.config);
|
|
return Ok(NuView::Preview(Preview::new(&text)));
|
|
}
|
|
|
|
let mut view = RecordView::new(columns, values);
|
|
|
|
if is_record {
|
|
view.set_top_layer_orientation(Orientation::Left);
|
|
}
|
|
|
|
Ok(NuView::Records(view))
|
|
}
|
|
}
|
|
|
|
pub enum NuView {
|
|
Records(RecordView),
|
|
Preview(Preview),
|
|
}
|
|
|
|
impl View for NuView {
|
|
fn draw(&mut self, f: &mut Frame, area: Rect, cfg: ViewConfig<'_>, layout: &mut Layout) {
|
|
match self {
|
|
NuView::Records(v) => v.draw(f, area, cfg, layout),
|
|
NuView::Preview(v) => v.draw(f, area, cfg, layout),
|
|
}
|
|
}
|
|
|
|
fn handle_input(
|
|
&mut self,
|
|
engine_state: &EngineState,
|
|
stack: &mut Stack,
|
|
layout: &Layout,
|
|
info: &mut crate::pager::ViewInfo,
|
|
key: crossterm::event::KeyEvent,
|
|
) -> Option<crate::pager::Transition> {
|
|
match self {
|
|
NuView::Records(v) => v.handle_input(engine_state, stack, layout, info, key),
|
|
NuView::Preview(v) => v.handle_input(engine_state, stack, layout, info, key),
|
|
}
|
|
}
|
|
|
|
fn show_data(&mut self, i: usize) -> bool {
|
|
match self {
|
|
NuView::Records(v) => v.show_data(i),
|
|
NuView::Preview(v) => v.show_data(i),
|
|
}
|
|
}
|
|
|
|
fn collect_data(&self) -> Vec<crate::nu_common::NuText> {
|
|
match self {
|
|
NuView::Records(v) => v.collect_data(),
|
|
NuView::Preview(v) => v.collect_data(),
|
|
}
|
|
}
|
|
|
|
fn exit(&mut self) -> Option<Value> {
|
|
match self {
|
|
NuView::Records(v) => v.exit(),
|
|
NuView::Preview(v) => v.exit(),
|
|
}
|
|
}
|
|
|
|
fn setup(&mut self, config: ViewConfig<'_>) {
|
|
match self {
|
|
NuView::Records(v) => v.setup(config),
|
|
NuView::Preview(v) => v.setup(config),
|
|
}
|
|
}
|
|
}
|