Patch explore 4 (#7517)

ref #7339 - This PR updates explore to take some of the colors from
nushell, namely the line colors and the ls_colors.

note: Not sure why this regression appeared maybe it's a feature or it's
no longer supposed to be supported?

Signed-off-by: Maxim Zhiburt <zhiburt@gmail.com>
Co-authored-by: Darren Schroeder <343840+fdncred@users.noreply.github.com>
This commit is contained in:
Maxim Zhiburt
2022-12-18 17:43:15 +03:00
committed by GitHub
parent 183be911d0
commit 28123841ba
14 changed files with 276 additions and 80 deletions

View File

@ -23,7 +23,7 @@ use views::{InformationView, Orientation, Preview, RecordView};
pub use pager::{PagerConfig, StyleConfig};
pub mod util {
pub use super::nu_common::{create_map, map_into_value};
pub use super::nu_common::{create_lscolors, create_map, map_into_value};
}
pub fn run_pager(

View File

@ -0,0 +1,115 @@
use std::fs::symlink_metadata;
use lscolors::LsColors;
use nu_ansi_term::{Color, Style};
use nu_engine::env_to_string;
use nu_protocol::engine::{EngineState, Stack};
use nu_utils::get_ls_colors;
use super::NuText;
pub fn create_lscolors(engine_state: &EngineState, stack: &Stack) -> LsColors {
let colors = stack
.get_env_var(engine_state, "LS_COLORS")
.and_then(|v| env_to_string("LS_COLORS", &v, engine_state, stack).ok());
get_ls_colors(colors)
}
pub fn lscolorize(header: &[String], data: &mut [Vec<NuText>], lscolors: &LsColors) {
for (col, col_name) in header.iter().enumerate() {
if col_name != "name" {
continue;
}
for row in data.iter_mut() {
let (path, text_style) = &mut row[col];
let style = get_path_style(path, lscolors);
if let Some(style) = style {
*text_style = text_style.style(style);
}
}
}
}
fn get_path_style(path: &str, ls_colors: &LsColors) -> Option<Style> {
let stripped_path = nu_utils::strip_ansi_unlikely(path);
let style = match symlink_metadata(stripped_path.as_ref()) {
Ok(metadata) => {
ls_colors.style_for_path_with_metadata(stripped_path.as_ref(), Some(&metadata))
}
Err(_) => ls_colors.style_for_path(stripped_path.as_ref()),
};
style.map(lsstyle_to_nu_style)
}
fn lsstyle_to_nu_style(s: &lscolors::Style) -> Style {
let mut out = Style::default();
if let Some(clr) = &s.background {
out.background = lscolor_to_nu_color(clr);
}
if let Some(clr) = &s.foreground {
out.foreground = lscolor_to_nu_color(clr);
}
if s.font_style.slow_blink | s.font_style.rapid_blink {
out.is_blink = true;
}
if s.font_style.bold {
out.is_bold = true;
}
if s.font_style.dimmed {
out.is_dimmed = true;
}
if s.font_style.hidden {
out.is_hidden = true;
}
if s.font_style.reverse {
out.is_reverse = true;
}
if s.font_style.italic {
out.is_italic = true;
}
if s.font_style.underline {
out.is_underline = true;
}
out
}
fn lscolor_to_nu_color(clr: &lscolors::Color) -> Option<Color> {
use lscolors::Color::*;
let clr = match clr {
Black => Color::Black,
BrightBlack => Color::DarkGray,
Red => Color::Red,
BrightRed => Color::LightRed,
Green => Color::Green,
BrightGreen => Color::LightGreen,
Yellow => Color::Yellow,
BrightYellow => Color::LightYellow,
Blue => Color::Blue,
BrightBlue => Color::LightBlue,
Magenta => Color::Magenta,
BrightMagenta => Color::LightMagenta,
Cyan => Color::Cyan,
BrightCyan => Color::LightCyan,
White => Color::White,
BrightWhite => Color::LightGray,
&Fixed(i) => Color::Fixed(i),
&RGB(r, g, b) => Color::Rgb(r, g, b),
};
Some(clr)
}

View File

@ -1,4 +1,5 @@
mod command;
mod lscolor;
mod string;
mod table;
mod value;
@ -15,6 +16,7 @@ pub type NuText = (String, TextStyle);
pub type CtrlC = Option<Arc<AtomicBool>>;
pub use command::{is_ignored_command, run_command_with_value, run_nu_command};
pub use lscolor::{create_lscolors, lscolorize};
pub use string::truncate_str;
pub use table::try_build_table;
pub use value::{collect_input, collect_pipeline, create_map, map_into_value, nu_str};

View File

@ -1,7 +1,7 @@
use std::collections::HashMap;
use nu_engine::get_columns;
use nu_protocol::{ast::PathMember, PipelineData, Value};
use nu_protocol::{ast::PathMember, ListStream, PipelineData, PipelineMetadata, RawStream, Value};
use super::NuSpan;
@ -9,25 +9,7 @@ pub fn collect_pipeline(input: PipelineData) -> (Vec<String>, Vec<Vec<Value>>) {
match input {
PipelineData::Empty => (vec![], vec![]),
PipelineData::Value(value, ..) => collect_input(value),
PipelineData::ListStream(mut stream, ..) => {
let mut records = vec![];
for item in stream.by_ref() {
records.push(item);
}
let mut cols = get_columns(&records);
let data = convert_records_to_dataset(&cols, records);
// trying to deal with 'not standart input'
if cols.is_empty() && !data.is_empty() {
let min_column_length = data.iter().map(|row| row.len()).min().unwrap_or(0);
if min_column_length > 0 {
cols = (0..min_column_length).map(|i| i.to_string()).collect();
}
}
(cols, data)
}
PipelineData::ListStream(stream, ..) => collect_list_stream(stream),
PipelineData::ExternalStream {
stdout,
stderr,
@ -35,55 +17,78 @@ pub fn collect_pipeline(input: PipelineData) -> (Vec<String>, Vec<Vec<Value>>) {
metadata,
span,
..
} => {
let mut columns = vec![];
let mut data = vec![];
} => collect_external_stream(stdout, stderr, exit_code, metadata, span),
}
}
if let Some(stdout) = stdout {
let value = stdout.into_string().map_or_else(
|error| Value::Error { error },
|string| Value::string(string.item, span),
);
fn collect_list_stream(mut stream: ListStream) -> (Vec<String>, Vec<Vec<Value>>) {
let mut records = vec![];
for item in stream.by_ref() {
records.push(item);
}
columns.push(String::from("stdout"));
data.push(value);
}
let mut cols = get_columns(&records);
let data = convert_records_to_dataset(&cols, records);
if let Some(stderr) = stderr {
let value = stderr.into_string().map_or_else(
|error| Value::Error { error },
|string| Value::string(string.item, span),
);
columns.push(String::from("stderr"));
data.push(value);
}
if let Some(exit_code) = exit_code {
let list = exit_code.collect::<Vec<_>>();
let val = Value::List { vals: list, span };
columns.push(String::from("exit_code"));
data.push(val);
}
if metadata.is_some() {
let val = Value::Record {
cols: vec![String::from("data_source")],
vals: vec![Value::String {
val: String::from("ls"),
span,
}],
span,
};
columns.push(String::from("metadata"));
data.push(val);
}
(columns, vec![data])
// trying to deal with 'non-standard input'
if cols.is_empty() && !data.is_empty() {
let min_column_length = data.iter().map(|row| row.len()).min().unwrap_or(0);
if min_column_length > 0 {
cols = (0..min_column_length).map(|i| i.to_string()).collect();
}
}
(cols, data)
}
fn collect_external_stream(
stdout: Option<RawStream>,
stderr: Option<RawStream>,
exit_code: Option<ListStream>,
metadata: Option<PipelineMetadata>,
span: NuSpan,
) -> (Vec<String>, Vec<Vec<Value>>) {
let mut columns = vec![];
let mut data = vec![];
if let Some(stdout) = stdout {
let value = stdout.into_string().map_or_else(
|error| Value::Error { error },
|string| Value::string(string.item, span),
);
columns.push(String::from("stdout"));
data.push(value);
}
if let Some(stderr) = stderr {
let value = stderr.into_string().map_or_else(
|error| Value::Error { error },
|string| Value::string(string.item, span),
);
columns.push(String::from("stderr"));
data.push(value);
}
if let Some(exit_code) = exit_code {
let list = exit_code.collect::<Vec<_>>();
let val = Value::List { vals: list, span };
columns.push(String::from("exit_code"));
data.push(val);
}
if metadata.is_some() {
let val = Value::Record {
cols: vec![String::from("data_source")],
vals: vec![Value::String {
val: String::from("ls"),
span,
}],
span,
};
columns.push(String::from("metadata"));
data.push(val);
}
(columns, vec![data])
}
/// Try to build column names and a table grid.

View File

@ -18,6 +18,7 @@ use crossterm::{
LeaveAlternateScreen,
},
};
use lscolors::LsColors;
use nu_color_config::{lookup_ansi_color_style, StyleComputer};
use nu_protocol::{
engine::{EngineState, Stack},
@ -142,6 +143,7 @@ impl<'a> Pager<'a> {
self.config.nu_config,
self.config.style_computer,
&self.config.config,
self.config.lscolors,
))
}
@ -161,6 +163,7 @@ pub enum Transition {
pub struct PagerConfig<'a> {
pub nu_config: &'a NuConfig,
pub style_computer: &'a StyleComputer<'a>,
pub lscolors: &'a LsColors,
pub config: ConfigMap,
pub style: StyleConfig,
pub peek_value: bool,
@ -173,12 +176,14 @@ impl<'a> PagerConfig<'a> {
pub fn new(
nu_config: &'a NuConfig,
style_computer: &'a StyleComputer,
lscolors: &'a LsColors,
config: ConfigMap,
) -> Self {
Self {
nu_config,
style_computer,
config,
lscolors,
peek_value: false,
exit_esc: true,
reverse: false,
@ -267,6 +272,7 @@ fn render_ui(
pager.config.nu_config,
pager.config.style_computer,
&pager.config.config,
pager.config.lscolors,
);
page.view.draw(f, available_area, cfg, &mut layout);
@ -422,6 +428,7 @@ fn run_command(
pager.config.nu_config,
pager.config.style_computer,
&pager.config.config,
pager.config.lscolors,
));
}
@ -430,6 +437,7 @@ fn run_command(
pager.config.nu_config,
pager.config.style_computer,
&pager.config.config,
pager.config.lscolors,
));
}
}
@ -458,6 +466,7 @@ fn run_command(
pager.config.nu_config,
pager.config.style_computer,
&pager.config.config,
pager.config.lscolors,
));
*view = Some(Page::raw(new_view, is_light));

View File

@ -7,6 +7,7 @@ mod record;
pub mod util;
use crossterm::event::KeyEvent;
use lscolors::LsColors;
use nu_color_config::StyleComputer;
use nu_protocol::{
engine::{EngineState, Stack},
@ -61,6 +62,7 @@ pub struct ViewConfig<'a> {
pub nu_config: &'a NuConfig,
pub style_computer: &'a StyleComputer<'a>,
pub config: &'a ConfigMap,
pub lscolors: &'a LsColors,
}
impl<'a> ViewConfig<'a> {
@ -68,11 +70,13 @@ impl<'a> ViewConfig<'a> {
nu_config: &'a NuConfig,
style_computer: &'a StyleComputer<'a>,
config: &'a ConfigMap,
lscolors: &'a LsColors,
) -> Self {
Self {
nu_config,
style_computer,
config,
lscolors,
}
}
}

View File

@ -11,7 +11,7 @@ use nu_protocol::{
use tui::{layout::Rect, widgets::Block};
use crate::{
nu_common::{collect_input, NuConfig, NuSpan, NuStyle, NuText},
nu_common::{collect_input, lscolorize, NuConfig, NuSpan, NuStyle, NuText},
pager::{
report::{Report, Severity},
ConfigMap, Frame, Transition, ViewInfo,
@ -208,7 +208,9 @@ impl<'a> RecordView<'a> {
fn create_tablew(&'a self, cfg: ViewConfig<'a>) -> TableW<'a> {
let layer = self.get_layer_last();
let 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);
lscolorize(&layer.columns, &mut data, cfg.lscolors);
let headers = layer.columns.as_ref();
let style_computer = cfg.style_computer;

View File

@ -107,13 +107,7 @@ pub fn nu_ansi_color_to_tui_color(clr: NuColor) -> Option<tui::style::Color> {
pub fn text_style_to_tui_style(style: TextStyle) -> tui::style::Style {
let mut out = tui::style::Style::default();
if let Some(style) = style.color_style {
if let Some(clr) = style.background {
out.bg = nu_ansi_color_to_tui_color(clr);
}
if let Some(clr) = style.foreground {
out.fg = nu_ansi_color_to_tui_color(clr);
}
out = nu_style_to_tui(style);
}
out