mirror of
https://github.com/nushell/nushell.git
synced 2025-08-15 02:32:51 +02:00
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:
@ -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(
|
||||
|
115
crates/nu-explore/src/nu_common/lscolor.rs
Normal file
115
crates/nu-explore/src/nu_common/lscolor.rs
Normal 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)
|
||||
}
|
@ -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};
|
||||
|
@ -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.
|
||||
|
@ -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));
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user