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:
Reilly Wood 2024-05-23 06:51:39 -07:00 committed by GitHub
parent f53aa6fcbf
commit 0b5a4c0d95
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 55 additions and 51 deletions

View File

@ -8,24 +8,27 @@ use ratatui::{
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,
/// Column to start rendering from
col: usize,
}
impl<'a> ColoredTextW<'a> {
impl<'a> ColoredTextWidget<'a> {
pub fn new(text: &'a str, col: usize) -> Self {
Self { text, col }
}
pub fn what(&self, area: Rect) -> String {
cut_string(self.text, self.col, area.width as usize)
/// Return a window of the text that fits into the given width, with ANSI styles stripped.
pub fn get_plain_text(&self, max_width: usize) -> String {
cut_string(self.text, self.col, max_width)
.ansi_strip()
.into_owned()
}
}
impl Widget for ColoredTextW<'_> {
impl Widget for ColoredTextWidget<'_> {
fn render(self, area: Rect, buf: &mut ratatui::buffer::Buffer) {
let text = cut_string(self.text, self.col, area.width as usize);

View File

@ -1,5 +1,5 @@
mod binary;
mod coloredtextw;
mod colored_text_widget;
mod cursor;
mod interactive;
mod preview;

View File

@ -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::{
nu_common::{NuSpan, NuText},
pager::{report::Report, Frame, Transition, ViewInfo},
@ -43,13 +43,14 @@ impl View for Preview {
let lines = &self.lines[self.cursor.row_starts_at()..];
for (i, line) in lines.iter().enumerate().take(area.height as usize) {
let text = ColoredTextW::new(line, self.cursor.column());
let s = text.what(area);
let text_widget = ColoredTextWidget::new(line, self.cursor.column());
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);
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);
}
}

View File

@ -1,6 +1,6 @@
mod tablew;
mod table_widget;
use self::tablew::{TableStyle, TableW, TableWState};
use self::table_widget::{TableStyle, TableWidget, TableWidgetState};
use super::{
cursor::XYCursor,
util::{make_styled_string, nu_style_to_tui},
@ -25,7 +25,7 @@ use nu_protocol::{
use ratatui::{layout::Rect, widgets::Block};
use std::{borrow::Cow, collections::HashMap};
pub use self::tablew::Orientation;
pub use self::table_widget::Orientation;
#[derive(Debug, Clone)]
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 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 (row, column) = self.get_current_offset();
TableW::new(
TableWidget::new(
headers,
data,
style_computer,
@ -225,7 +225,7 @@ impl<'a> RecordView<'a> {
impl View for RecordView<'_> {
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);
f.render_stateful_widget(table, area, &mut table_layout);

View File

@ -18,13 +18,13 @@ use std::{
};
#[derive(Debug, Clone)]
pub struct TableW<'a> {
pub struct TableWidget<'a> {
columns: Cow<'a, [String]>,
data: Cow<'a, [Vec<NuText>]>,
index_row: usize,
index_column: usize,
style: TableStyle,
head_position: Orientation,
header_position: Orientation,
style_computer: &'a StyleComputer<'a>,
}
@ -38,14 +38,13 @@ pub enum Orientation {
#[derive(Debug, Default, Clone, Copy)]
pub struct TableStyle {
pub splitline_style: NuStyle,
pub shift_line_style: NuStyle,
pub show_index: bool,
pub show_header: bool,
pub column_padding_left: usize,
pub column_padding_right: usize,
}
impl<'a> TableW<'a> {
impl<'a> TableWidget<'a> {
#[allow(clippy::too_many_arguments)]
pub fn new(
columns: impl Into<Cow<'a, [String]>>,
@ -54,7 +53,7 @@ impl<'a> TableW<'a> {
index_row: usize,
index_column: usize,
style: TableStyle,
head_position: Orientation,
header_position: Orientation,
) -> Self {
Self {
columns: columns.into(),
@ -63,21 +62,21 @@ impl<'a> TableW<'a> {
index_row,
index_column,
style,
head_position,
header_position,
}
}
}
#[derive(Debug, Default)]
pub struct TableWState {
pub struct TableWidgetState {
pub layout: Layout,
pub count_rows: usize,
pub count_columns: usize,
pub data_height: u16,
}
impl StatefulWidget for TableW<'_> {
type State = TableWState;
impl StatefulWidget for TableWidget<'_> {
type State = TableWidgetState;
fn render(
self,
@ -89,7 +88,7 @@ impl StatefulWidget for TableW<'_> {
return;
}
let is_horizontal = matches!(self.head_position, Orientation::Top);
let is_horizontal = matches!(self.header_position, Orientation::Top);
if is_horizontal {
self.render_table_horizontal(area, buf, state);
} else {
@ -99,8 +98,8 @@ impl StatefulWidget for TableW<'_> {
}
// todo: refactoring these to methods as they have quite a bit in common.
impl<'a> TableW<'a> {
fn render_table_horizontal(self, area: Rect, buf: &mut Buffer, state: &mut TableWState) {
impl<'a> TableWidget<'a> {
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_r = self.style.column_padding_right as u16;
@ -108,7 +107,6 @@ impl<'a> TableW<'a> {
let show_head = self.style.show_header;
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_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_columns = 0;
state.data_height = data_height;
@ -191,11 +190,11 @@ impl<'a> TableW<'a> {
let pad = padding_l + padding_r;
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);
if shift {
do_render_shift_column = true;
if overflow {
show_overflow_indicator = true;
}
if w == 0 && !ok {
@ -232,14 +231,14 @@ impl<'a> TableW<'a> {
state.count_columns += 1;
if do_render_shift_column {
if show_overflow_indicator {
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_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);
}
@ -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 {
return;
}
@ -275,7 +274,6 @@ impl<'a> TableW<'a> {
let show_index = self.style.show_index;
let show_head = self.style.show_header;
let splitline_s = self.style.splitline_style;
let shift_column_s = self.style.shift_line_style;
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_columns = 0;
@ -375,11 +374,11 @@ impl<'a> TableW<'a> {
let available = area.width - left_w;
let is_last = col + 1 == self.data.len();
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);
if shift {
do_render_shift_column = true;
if overflow {
show_overflow_indicator = true;
}
if column_width == 0 && !ok {
@ -403,16 +402,16 @@ impl<'a> TableW<'a> {
state.count_columns += 1;
}
if do_render_shift_column {
if show_overflow_indicator {
break;
}
}
if do_render_shift_column {
if show_overflow_indicator {
let x = area.x + left_w;
left_w += render_space(buf, x, area.y, area.height, padding_l);
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;
left_w += render_space(buf, x, area.y, area.height, padding_r);
}
@ -433,13 +432,13 @@ fn truncate_column_width(
) -> (u16, bool, bool) {
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,
None => return (w, true, false),
};
if width == 0 {
return (0, false, shift_column);
return (0, false, overflow);
}
truncate_list(column, width as usize);
@ -447,7 +446,7 @@ fn truncate_column_width(
truncate_str(head, width as usize);
}
(width, false, shift_column)
(width, false, overflow)
}
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 {
alignment: Alignment::Left,
color_style: Some(style),
color_style: None,
};
repeat_vertical(buf, x, y, 1, height, '…', style);