mirror of
https://github.com/nushell/nushell.git
synced 2024-11-22 00:13:21 +01:00
explore
refactoring+clarification (#12940)
Another very boring PR cleaning up and documenting some of `explore`'s innards. Mostly renaming things that I found confusing or vague when reading through the code, also adding some comments.
This commit is contained in:
parent
f53aa6fcbf
commit
0b5a4c0d95
@ -8,24 +8,27 @@ use ratatui::{
|
|||||||
widgets::Widget,
|
widgets::Widget,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct ColoredTextW<'a> {
|
/// A widget that represents a single line of text with ANSI styles.
|
||||||
|
pub struct ColoredTextWidget<'a> {
|
||||||
text: &'a str,
|
text: &'a str,
|
||||||
|
/// Column to start rendering from
|
||||||
col: usize,
|
col: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ColoredTextW<'a> {
|
impl<'a> ColoredTextWidget<'a> {
|
||||||
pub fn new(text: &'a str, col: usize) -> Self {
|
pub fn new(text: &'a str, col: usize) -> Self {
|
||||||
Self { text, col }
|
Self { text, col }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn what(&self, area: Rect) -> String {
|
/// Return a window of the text that fits into the given width, with ANSI styles stripped.
|
||||||
cut_string(self.text, self.col, area.width as usize)
|
pub fn get_plain_text(&self, max_width: usize) -> String {
|
||||||
|
cut_string(self.text, self.col, max_width)
|
||||||
.ansi_strip()
|
.ansi_strip()
|
||||||
.into_owned()
|
.into_owned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for ColoredTextW<'_> {
|
impl Widget for ColoredTextWidget<'_> {
|
||||||
fn render(self, area: Rect, buf: &mut ratatui::buffer::Buffer) {
|
fn render(self, area: Rect, buf: &mut ratatui::buffer::Buffer) {
|
||||||
let text = cut_string(self.text, self.col, area.width as usize);
|
let text = cut_string(self.text, self.col, area.width as usize);
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
mod binary;
|
mod binary;
|
||||||
mod coloredtextw;
|
mod colored_text_widget;
|
||||||
mod cursor;
|
mod cursor;
|
||||||
mod interactive;
|
mod interactive;
|
||||||
mod preview;
|
mod preview;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use super::{coloredtextw::ColoredTextW, cursor::XYCursor, Layout, View, ViewConfig};
|
use super::{colored_text_widget::ColoredTextWidget, cursor::XYCursor, Layout, View, ViewConfig};
|
||||||
use crate::{
|
use crate::{
|
||||||
nu_common::{NuSpan, NuText},
|
nu_common::{NuSpan, NuText},
|
||||||
pager::{report::Report, Frame, Transition, ViewInfo},
|
pager::{report::Report, Frame, Transition, ViewInfo},
|
||||||
@ -43,13 +43,14 @@ impl View for Preview {
|
|||||||
|
|
||||||
let lines = &self.lines[self.cursor.row_starts_at()..];
|
let lines = &self.lines[self.cursor.row_starts_at()..];
|
||||||
for (i, line) in lines.iter().enumerate().take(area.height as usize) {
|
for (i, line) in lines.iter().enumerate().take(area.height as usize) {
|
||||||
let text = ColoredTextW::new(line, self.cursor.column());
|
let text_widget = ColoredTextWidget::new(line, self.cursor.column());
|
||||||
let s = text.what(area);
|
let plain_text = text_widget.get_plain_text(area.width as usize);
|
||||||
|
|
||||||
let area = Rect::new(area.x, area.y + i as u16, area.width, 1);
|
let area = Rect::new(area.x, area.y + i as u16, area.width, 1);
|
||||||
f.render_widget(text, area);
|
f.render_widget(text_widget, area);
|
||||||
|
|
||||||
layout.push(&s, area.x, area.y, area.width, area.height);
|
// push the plain text to layout so it can be searched
|
||||||
|
layout.push(&plain_text, area.x, area.y, area.width, area.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
mod tablew;
|
mod table_widget;
|
||||||
|
|
||||||
use self::tablew::{TableStyle, TableW, TableWState};
|
use self::table_widget::{TableStyle, TableWidget, TableWidgetState};
|
||||||
use super::{
|
use super::{
|
||||||
cursor::XYCursor,
|
cursor::XYCursor,
|
||||||
util::{make_styled_string, nu_style_to_tui},
|
util::{make_styled_string, nu_style_to_tui},
|
||||||
@ -25,7 +25,7 @@ use nu_protocol::{
|
|||||||
use ratatui::{layout::Rect, widgets::Block};
|
use ratatui::{layout::Rect, widgets::Block};
|
||||||
use std::{borrow::Cow, collections::HashMap};
|
use std::{borrow::Cow, collections::HashMap};
|
||||||
|
|
||||||
pub use self::tablew::Orientation;
|
pub use self::table_widget::Orientation;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct RecordView<'a> {
|
pub struct RecordView<'a> {
|
||||||
@ -175,7 +175,7 @@ impl<'a> RecordView<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_tablew(&'a self, cfg: ViewConfig<'a>) -> TableW<'a> {
|
fn create_tablew(&'a self, cfg: ViewConfig<'a>) -> TableWidget<'a> {
|
||||||
let layer = self.get_layer_last();
|
let layer = self.get_layer_last();
|
||||||
let mut data = convert_records_to_string(&layer.records, cfg.nu_config, cfg.style_computer);
|
let mut data = convert_records_to_string(&layer.records, cfg.nu_config, cfg.style_computer);
|
||||||
|
|
||||||
@ -185,7 +185,7 @@ impl<'a> RecordView<'a> {
|
|||||||
let style_computer = cfg.style_computer;
|
let style_computer = cfg.style_computer;
|
||||||
let (row, column) = self.get_current_offset();
|
let (row, column) = self.get_current_offset();
|
||||||
|
|
||||||
TableW::new(
|
TableWidget::new(
|
||||||
headers,
|
headers,
|
||||||
data,
|
data,
|
||||||
style_computer,
|
style_computer,
|
||||||
@ -225,7 +225,7 @@ impl<'a> RecordView<'a> {
|
|||||||
|
|
||||||
impl View for RecordView<'_> {
|
impl View for RecordView<'_> {
|
||||||
fn draw(&mut self, f: &mut Frame, area: Rect, cfg: ViewConfig<'_>, layout: &mut Layout) {
|
fn draw(&mut self, f: &mut Frame, area: Rect, cfg: ViewConfig<'_>, layout: &mut Layout) {
|
||||||
let mut table_layout = TableWState::default();
|
let mut table_layout = TableWidgetState::default();
|
||||||
let table = self.create_tablew(cfg);
|
let table = self.create_tablew(cfg);
|
||||||
f.render_stateful_widget(table, area, &mut table_layout);
|
f.render_stateful_widget(table, area, &mut table_layout);
|
||||||
|
|
||||||
|
@ -18,13 +18,13 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TableW<'a> {
|
pub struct TableWidget<'a> {
|
||||||
columns: Cow<'a, [String]>,
|
columns: Cow<'a, [String]>,
|
||||||
data: Cow<'a, [Vec<NuText>]>,
|
data: Cow<'a, [Vec<NuText>]>,
|
||||||
index_row: usize,
|
index_row: usize,
|
||||||
index_column: usize,
|
index_column: usize,
|
||||||
style: TableStyle,
|
style: TableStyle,
|
||||||
head_position: Orientation,
|
header_position: Orientation,
|
||||||
style_computer: &'a StyleComputer<'a>,
|
style_computer: &'a StyleComputer<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,14 +38,13 @@ pub enum Orientation {
|
|||||||
#[derive(Debug, Default, Clone, Copy)]
|
#[derive(Debug, Default, Clone, Copy)]
|
||||||
pub struct TableStyle {
|
pub struct TableStyle {
|
||||||
pub splitline_style: NuStyle,
|
pub splitline_style: NuStyle,
|
||||||
pub shift_line_style: NuStyle,
|
|
||||||
pub show_index: bool,
|
pub show_index: bool,
|
||||||
pub show_header: bool,
|
pub show_header: bool,
|
||||||
pub column_padding_left: usize,
|
pub column_padding_left: usize,
|
||||||
pub column_padding_right: usize,
|
pub column_padding_right: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TableW<'a> {
|
impl<'a> TableWidget<'a> {
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
columns: impl Into<Cow<'a, [String]>>,
|
columns: impl Into<Cow<'a, [String]>>,
|
||||||
@ -54,7 +53,7 @@ impl<'a> TableW<'a> {
|
|||||||
index_row: usize,
|
index_row: usize,
|
||||||
index_column: usize,
|
index_column: usize,
|
||||||
style: TableStyle,
|
style: TableStyle,
|
||||||
head_position: Orientation,
|
header_position: Orientation,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
columns: columns.into(),
|
columns: columns.into(),
|
||||||
@ -63,21 +62,21 @@ impl<'a> TableW<'a> {
|
|||||||
index_row,
|
index_row,
|
||||||
index_column,
|
index_column,
|
||||||
style,
|
style,
|
||||||
head_position,
|
header_position,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct TableWState {
|
pub struct TableWidgetState {
|
||||||
pub layout: Layout,
|
pub layout: Layout,
|
||||||
pub count_rows: usize,
|
pub count_rows: usize,
|
||||||
pub count_columns: usize,
|
pub count_columns: usize,
|
||||||
pub data_height: u16,
|
pub data_height: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StatefulWidget for TableW<'_> {
|
impl StatefulWidget for TableWidget<'_> {
|
||||||
type State = TableWState;
|
type State = TableWidgetState;
|
||||||
|
|
||||||
fn render(
|
fn render(
|
||||||
self,
|
self,
|
||||||
@ -89,7 +88,7 @@ impl StatefulWidget for TableW<'_> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let is_horizontal = matches!(self.head_position, Orientation::Top);
|
let is_horizontal = matches!(self.header_position, Orientation::Top);
|
||||||
if is_horizontal {
|
if is_horizontal {
|
||||||
self.render_table_horizontal(area, buf, state);
|
self.render_table_horizontal(area, buf, state);
|
||||||
} else {
|
} else {
|
||||||
@ -99,8 +98,8 @@ impl StatefulWidget for TableW<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// todo: refactoring these to methods as they have quite a bit in common.
|
// todo: refactoring these to methods as they have quite a bit in common.
|
||||||
impl<'a> TableW<'a> {
|
impl<'a> TableWidget<'a> {
|
||||||
fn render_table_horizontal(self, area: Rect, buf: &mut Buffer, state: &mut TableWState) {
|
fn render_table_horizontal(self, area: Rect, buf: &mut Buffer, state: &mut TableWidgetState) {
|
||||||
let padding_l = self.style.column_padding_left as u16;
|
let padding_l = self.style.column_padding_left as u16;
|
||||||
let padding_r = self.style.column_padding_right as u16;
|
let padding_r = self.style.column_padding_right as u16;
|
||||||
|
|
||||||
@ -108,7 +107,6 @@ impl<'a> TableW<'a> {
|
|||||||
let show_head = self.style.show_header;
|
let show_head = self.style.show_header;
|
||||||
|
|
||||||
let splitline_s = self.style.splitline_style;
|
let splitline_s = self.style.splitline_style;
|
||||||
let shift_column_s = self.style.shift_line_style;
|
|
||||||
|
|
||||||
let mut data_height = area.height;
|
let mut data_height = area.height;
|
||||||
let mut data_y = area.y;
|
let mut data_y = area.y;
|
||||||
@ -164,7 +162,8 @@ impl<'a> TableW<'a> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut do_render_shift_column = false;
|
// if there is more data than we can show, add an ellipsis to the column headers to hint at that
|
||||||
|
let mut show_overflow_indicator = false;
|
||||||
state.count_rows = data.len();
|
state.count_rows = data.len();
|
||||||
state.count_columns = 0;
|
state.count_columns = 0;
|
||||||
state.data_height = data_height;
|
state.data_height = data_height;
|
||||||
@ -191,11 +190,11 @@ impl<'a> TableW<'a> {
|
|||||||
|
|
||||||
let pad = padding_l + padding_r;
|
let pad = padding_l + padding_r;
|
||||||
let head = show_head.then_some(&mut head);
|
let head = show_head.then_some(&mut head);
|
||||||
let (w, ok, shift) =
|
let (w, ok, overflow) =
|
||||||
truncate_column_width(space, 1, use_space, pad, is_last, &mut column, head);
|
truncate_column_width(space, 1, use_space, pad, is_last, &mut column, head);
|
||||||
|
|
||||||
if shift {
|
if overflow {
|
||||||
do_render_shift_column = true;
|
show_overflow_indicator = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if w == 0 && !ok {
|
if w == 0 && !ok {
|
||||||
@ -232,14 +231,14 @@ impl<'a> TableW<'a> {
|
|||||||
|
|
||||||
state.count_columns += 1;
|
state.count_columns += 1;
|
||||||
|
|
||||||
if do_render_shift_column {
|
if show_overflow_indicator {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if do_render_shift_column && show_head {
|
if show_overflow_indicator && show_head {
|
||||||
width += render_space(buf, width, data_y, data_height, padding_l);
|
width += render_space(buf, width, data_y, data_height, padding_l);
|
||||||
width += render_shift_column(buf, width, head_y, 1, shift_column_s);
|
width += render_overflow_column(buf, width, head_y, 1);
|
||||||
width += render_space(buf, width, data_y, data_height, padding_r);
|
width += render_space(buf, width, data_y, data_height, padding_r);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,7 +263,7 @@ impl<'a> TableW<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_table_vertical(self, area: Rect, buf: &mut Buffer, state: &mut TableWState) {
|
fn render_table_vertical(self, area: Rect, buf: &mut Buffer, state: &mut TableWidgetState) {
|
||||||
if area.width == 0 || area.height == 0 {
|
if area.width == 0 || area.height == 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -275,7 +274,6 @@ impl<'a> TableW<'a> {
|
|||||||
let show_index = self.style.show_index;
|
let show_index = self.style.show_index;
|
||||||
let show_head = self.style.show_header;
|
let show_head = self.style.show_header;
|
||||||
let splitline_s = self.style.splitline_style;
|
let splitline_s = self.style.splitline_style;
|
||||||
let shift_column_s = self.style.shift_line_style;
|
|
||||||
|
|
||||||
let mut left_w = 0;
|
let mut left_w = 0;
|
||||||
|
|
||||||
@ -358,7 +356,8 @@ impl<'a> TableW<'a> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut do_render_shift_column = false;
|
// if there is more data than we can show, add an ellipsis to the column headers to hint at that
|
||||||
|
let mut show_overflow_indicator = false;
|
||||||
|
|
||||||
state.count_rows = columns.len();
|
state.count_rows = columns.len();
|
||||||
state.count_columns = 0;
|
state.count_columns = 0;
|
||||||
@ -375,11 +374,11 @@ impl<'a> TableW<'a> {
|
|||||||
let available = area.width - left_w;
|
let available = area.width - left_w;
|
||||||
let is_last = col + 1 == self.data.len();
|
let is_last = col + 1 == self.data.len();
|
||||||
let pad = padding_l + padding_r;
|
let pad = padding_l + padding_r;
|
||||||
let (column_width, ok, shift) =
|
let (column_width, ok, overflow) =
|
||||||
truncate_column_width(available, 1, column_width, pad, is_last, &mut column, None);
|
truncate_column_width(available, 1, column_width, pad, is_last, &mut column, None);
|
||||||
|
|
||||||
if shift {
|
if overflow {
|
||||||
do_render_shift_column = true;
|
show_overflow_indicator = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if column_width == 0 && !ok {
|
if column_width == 0 && !ok {
|
||||||
@ -403,16 +402,16 @@ impl<'a> TableW<'a> {
|
|||||||
state.count_columns += 1;
|
state.count_columns += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if do_render_shift_column {
|
if show_overflow_indicator {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if do_render_shift_column {
|
if show_overflow_indicator {
|
||||||
let x = area.x + left_w;
|
let x = area.x + left_w;
|
||||||
left_w += render_space(buf, x, area.y, area.height, padding_l);
|
left_w += render_space(buf, x, area.y, area.height, padding_l);
|
||||||
let x = area.x + left_w;
|
let x = area.x + left_w;
|
||||||
left_w += render_shift_column(buf, x, area.y, area.height, shift_column_s);
|
left_w += render_overflow_column(buf, x, area.y, area.height);
|
||||||
let x = area.x + left_w;
|
let x = area.x + left_w;
|
||||||
left_w += render_space(buf, x, area.y, area.height, padding_r);
|
left_w += render_space(buf, x, area.y, area.height, padding_r);
|
||||||
}
|
}
|
||||||
@ -433,13 +432,13 @@ fn truncate_column_width(
|
|||||||
) -> (u16, bool, bool) {
|
) -> (u16, bool, bool) {
|
||||||
let result = check_column_width(space, min, w, pad, is_last);
|
let result = check_column_width(space, min, w, pad, is_last);
|
||||||
|
|
||||||
let (width, shift_column) = match result {
|
let (width, overflow) = match result {
|
||||||
Some(result) => result,
|
Some(result) => result,
|
||||||
None => return (w, true, false),
|
None => return (w, true, false),
|
||||||
};
|
};
|
||||||
|
|
||||||
if width == 0 {
|
if width == 0 {
|
||||||
return (0, false, shift_column);
|
return (0, false, overflow);
|
||||||
}
|
}
|
||||||
|
|
||||||
truncate_list(column, width as usize);
|
truncate_list(column, width as usize);
|
||||||
@ -447,7 +446,7 @@ fn truncate_column_width(
|
|||||||
truncate_str(head, width as usize);
|
truncate_str(head, width as usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
(width, false, shift_column)
|
(width, false, overflow)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_column_width(
|
fn check_column_width(
|
||||||
@ -652,10 +651,11 @@ fn truncate_list(list: &mut [NuText], width: usize) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_shift_column(buf: &mut Buffer, x: u16, y: u16, height: u16, style: NuStyle) -> u16 {
|
/// Render a column with an ellipsis in the header to indicate that there is more data than can be displayed
|
||||||
|
fn render_overflow_column(buf: &mut Buffer, x: u16, y: u16, height: u16) -> u16 {
|
||||||
let style = TextStyle {
|
let style = TextStyle {
|
||||||
alignment: Alignment::Left,
|
alignment: Alignment::Left,
|
||||||
color_style: Some(style),
|
color_style: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
repeat_vertical(buf, x, y, 1, height, '…', style);
|
repeat_vertical(buf, x, y, 1, height, '…', style);
|
Loading…
Reference in New Issue
Block a user