mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 15:25:06 +02:00
Add minor theme support (#2449)
* WIP - compiling but not working * semi-working * making progress * working except for table lines * fmt + clippy * cleaned up some comments * working line colors * fmt, clippy, updated sample config.toml * removed extra comments
This commit is contained in:
@ -1,10 +1,12 @@
|
||||
use crate::commands::table::options::{ConfigExtensions, NuConfig as TableConfiguration};
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
use crate::primitive::get_color_config;
|
||||
use nu_data::value::{format_leaf, style_leaf};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_table::{draw_table, Alignment, StyledString, TextStyle};
|
||||
use std::collections::HashMap;
|
||||
use std::time::Instant;
|
||||
|
||||
const STREAM_PAGE_SIZE: usize = 1000;
|
||||
@ -44,19 +46,14 @@ pub fn from_list(
|
||||
values: &[Value],
|
||||
configuration: &TableConfiguration,
|
||||
starting_idx: usize,
|
||||
color_hm: &HashMap<String, ansi_term::Style>,
|
||||
) -> nu_table::Table {
|
||||
let header_style = TextStyle {
|
||||
is_bold: configuration.header_bold(),
|
||||
alignment: configuration.header_alignment(),
|
||||
color: configuration.header_color(),
|
||||
};
|
||||
|
||||
let header_style = configuration.header_style();
|
||||
let mut headers: Vec<StyledString> = nu_protocol::merge_descriptors(values)
|
||||
.into_iter()
|
||||
.map(|x| StyledString::new(x, header_style.clone()))
|
||||
.map(|x| StyledString::new(x, header_style))
|
||||
.collect();
|
||||
let entries = values_to_entries(values, &mut headers, configuration, starting_idx);
|
||||
|
||||
let entries = values_to_entries(values, &mut headers, configuration, starting_idx, &color_hm);
|
||||
nu_table::Table {
|
||||
headers,
|
||||
data: entries,
|
||||
@ -69,9 +66,9 @@ fn values_to_entries(
|
||||
headers: &mut Vec<StyledString>,
|
||||
configuration: &TableConfiguration,
|
||||
starting_idx: usize,
|
||||
color_hm: &HashMap<String, ansi_term::Style>,
|
||||
) -> Vec<Vec<StyledString>> {
|
||||
let disable_indexes = configuration.disabled_indexes();
|
||||
|
||||
let mut entries = vec![];
|
||||
|
||||
if headers.is_empty() {
|
||||
@ -89,11 +86,11 @@ fn values_to_entries(
|
||||
..
|
||||
} => StyledString::new(
|
||||
format_leaf(&UntaggedValue::nothing()).plain_string(100_000),
|
||||
style_leaf(&UntaggedValue::nothing()),
|
||||
style_leaf(&UntaggedValue::nothing(), &color_hm),
|
||||
),
|
||||
_ => StyledString::new(
|
||||
format_leaf(value).plain_string(100_000),
|
||||
style_leaf(value),
|
||||
style_leaf(value, &color_hm),
|
||||
),
|
||||
}
|
||||
} else {
|
||||
@ -106,12 +103,12 @@ fn values_to_entries(
|
||||
|
||||
StyledString::new(
|
||||
format_leaf(data.borrow()).plain_string(100_000),
|
||||
style_leaf(data.borrow()),
|
||||
style_leaf(data.borrow(), &color_hm),
|
||||
)
|
||||
}
|
||||
_ => StyledString::new(
|
||||
format_leaf(&UntaggedValue::nothing()).plain_string(100_000),
|
||||
style_leaf(&UntaggedValue::nothing()),
|
||||
style_leaf(&UntaggedValue::nothing(), &color_hm),
|
||||
),
|
||||
}
|
||||
}
|
||||
@ -119,16 +116,22 @@ fn values_to_entries(
|
||||
.collect();
|
||||
|
||||
// Indices are green, bold, right-aligned:
|
||||
// unless we change them :)
|
||||
if !disable_indexes {
|
||||
row.insert(
|
||||
0,
|
||||
StyledString::new(
|
||||
(starting_idx + idx).to_string(),
|
||||
TextStyle {
|
||||
alignment: Alignment::Right,
|
||||
color: Some(ansi_term::Color::Green),
|
||||
is_bold: true,
|
||||
},
|
||||
TextStyle::new().alignment(Alignment::Right).style(
|
||||
color_hm
|
||||
.get("index_color")
|
||||
.unwrap_or(
|
||||
&ansi_term::Style::default()
|
||||
.bold()
|
||||
.fg(ansi_term::Color::Green),
|
||||
)
|
||||
.to_owned(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -141,11 +144,10 @@ fn values_to_entries(
|
||||
0,
|
||||
StyledString::new(
|
||||
"#".to_owned(),
|
||||
TextStyle {
|
||||
alignment: Alignment::Center,
|
||||
color: Some(ansi_term::Color::Green),
|
||||
is_bold: true,
|
||||
},
|
||||
TextStyle::new()
|
||||
.alignment(Alignment::Center)
|
||||
.fg(ansi_term::Color::Green)
|
||||
.bold(Some(true)),
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -161,8 +163,14 @@ async fn table(
|
||||
let registry = registry.clone();
|
||||
let mut args = args.evaluate_once(®istry).await?;
|
||||
let mut finished = false;
|
||||
// Ideally, get_color_config would get all the colors configured in the config.toml
|
||||
// and create a style based on those settings. However, there are few places where
|
||||
// this just won't work right now, like header styling, because a style needs to know
|
||||
// more than just color, it needs fg & bg color, bold, dimmed, italic, underline,
|
||||
// blink, reverse, hidden, strikethrough and most of those aren't available in the
|
||||
// config.toml.... yet.
|
||||
let color_hm = get_color_config();
|
||||
|
||||
// let host = args.host.clone();
|
||||
let mut start_number = match args.get("start_number") {
|
||||
Some(Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Int(i)),
|
||||
@ -234,9 +242,9 @@ async fn table(
|
||||
let input: Vec<Value> = new_input.into();
|
||||
|
||||
if !input.is_empty() {
|
||||
let t = from_list(&input, &configuration, start_number);
|
||||
let t = from_list(&input, &configuration, start_number, &color_hm);
|
||||
|
||||
draw_table(&t, term_width);
|
||||
draw_table(&t, term_width, &color_hm);
|
||||
}
|
||||
|
||||
start_number += input.len();
|
||||
|
@ -1,62 +1,51 @@
|
||||
pub use nu_data::config::NuConfig;
|
||||
use nu_data::primitive::lookup_ansi_color_style;
|
||||
use nu_protocol::{UntaggedValue, Value};
|
||||
use nu_source::Tag;
|
||||
use nu_table::TextStyle;
|
||||
use std::fmt::Debug;
|
||||
|
||||
pub trait ConfigExtensions: Debug + Send {
|
||||
fn header_alignment(&self) -> nu_table::Alignment;
|
||||
fn header_color(&self) -> Option<ansi_term::Color>;
|
||||
fn header_bold(&self) -> bool;
|
||||
fn table_mode(&self) -> nu_table::Theme;
|
||||
fn disabled_indexes(&self) -> bool;
|
||||
fn text_color(&self) -> Option<ansi_term::Color>;
|
||||
fn line_color(&self) -> Option<ansi_term::Color>;
|
||||
fn header_style(&self) -> TextStyle;
|
||||
}
|
||||
|
||||
pub fn header_alignment(config: &NuConfig) -> nu_table::Alignment {
|
||||
pub fn header_alignment_from_value(align_value: Option<&Value>) -> nu_table::Alignment {
|
||||
match align_value {
|
||||
Some(v) => match v
|
||||
.as_string()
|
||||
.unwrap_or_else(|_| "none".to_string())
|
||||
.as_ref()
|
||||
{
|
||||
"l" | "left" => nu_table::Alignment::Left,
|
||||
"c" | "center" => nu_table::Alignment::Center,
|
||||
"r" | "right" => nu_table::Alignment::Right,
|
||||
_ => nu_table::Alignment::Center,
|
||||
},
|
||||
_ => nu_table::Alignment::Center,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_color_from_key_and_subkey(config: &NuConfig, key: &str, subkey: &str) -> Value {
|
||||
let vars = config.vars.lock();
|
||||
|
||||
let alignment = vars.get("header_align");
|
||||
|
||||
if alignment.is_none() {
|
||||
return nu_table::Alignment::Center;
|
||||
let mut v: Value =
|
||||
UntaggedValue::Primitive(nu_protocol::Primitive::String("nocolor".to_string()))
|
||||
.into_value(Tag::unknown());
|
||||
if let Some(config_vars) = vars.get(key) {
|
||||
for (kee, value) in config_vars.row_entries() {
|
||||
if kee == subkey {
|
||||
v = value.to_owned();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
alignment.map_or(nu_table::Alignment::Left, |a| {
|
||||
a.as_string().map_or(nu_table::Alignment::Center, |a| {
|
||||
match a.to_lowercase().as_str() {
|
||||
"center" | "c" => nu_table::Alignment::Center,
|
||||
"right" | "r" => nu_table::Alignment::Right,
|
||||
_ => nu_table::Alignment::Center,
|
||||
}
|
||||
})
|
||||
})
|
||||
v
|
||||
}
|
||||
|
||||
pub fn get_color_for_config_key(config: &NuConfig, key: &str) -> Option<ansi_term::Color> {
|
||||
let vars = config.vars.lock();
|
||||
|
||||
Some(match vars.get(key) {
|
||||
Some(c) => match c.as_string() {
|
||||
Ok(color) => match color.to_lowercase().as_str() {
|
||||
"g" | "green" => ansi_term::Color::Green,
|
||||
"r" | "red" => ansi_term::Color::Red,
|
||||
"u" | "blue" => ansi_term::Color::Blue,
|
||||
"b" | "black" => ansi_term::Color::Black,
|
||||
"y" | "yellow" => ansi_term::Color::Yellow,
|
||||
"p" | "purple" => ansi_term::Color::Purple,
|
||||
"c" | "cyan" => ansi_term::Color::Cyan,
|
||||
"w" | "white" => ansi_term::Color::White,
|
||||
_ => ansi_term::Color::Green,
|
||||
},
|
||||
_ => ansi_term::Color::Green,
|
||||
},
|
||||
_ => ansi_term::Color::Green,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn header_bold(config: &NuConfig) -> bool {
|
||||
let vars = config.vars.lock();
|
||||
|
||||
vars.get("header_bold")
|
||||
pub fn header_bold_from_value(bold_value: Option<&Value>) -> bool {
|
||||
bold_value
|
||||
.map(|x| x.as_bool().unwrap_or(true))
|
||||
.unwrap_or(true)
|
||||
}
|
||||
@ -84,24 +73,25 @@ pub fn disabled_indexes(config: &NuConfig) -> bool {
|
||||
}
|
||||
|
||||
impl ConfigExtensions for NuConfig {
|
||||
fn header_alignment(&self) -> nu_table::Alignment {
|
||||
header_alignment(self)
|
||||
}
|
||||
fn header_style(&self) -> TextStyle {
|
||||
// FIXME: I agree, this is the long way around, please suggest and alternative.
|
||||
let head_color = get_color_from_key_and_subkey(self, "color_config", "header_color");
|
||||
let head_color_style = lookup_ansi_color_style(
|
||||
head_color
|
||||
.as_string()
|
||||
.unwrap_or_else(|_| "green".to_string()),
|
||||
);
|
||||
let head_bold = get_color_from_key_and_subkey(self, "color_config", "header_bold");
|
||||
let head_bold_bool = header_bold_from_value(Some(&head_bold));
|
||||
let head_align = get_color_from_key_and_subkey(self, "color_config", "header_align");
|
||||
let head_alignment = header_alignment_from_value(Some(&head_align));
|
||||
|
||||
fn header_color(&self) -> Option<ansi_term::Color> {
|
||||
get_color_for_config_key(self, "header_color")
|
||||
}
|
||||
|
||||
fn text_color(&self) -> Option<ansi_term::Color> {
|
||||
get_color_for_config_key(self, "text_color")
|
||||
}
|
||||
|
||||
fn line_color(&self) -> Option<ansi_term::Color> {
|
||||
get_color_for_config_key(self, "line_color")
|
||||
}
|
||||
|
||||
fn header_bold(&self) -> bool {
|
||||
header_bold(self)
|
||||
TextStyle::new()
|
||||
.alignment(head_alignment)
|
||||
.bold(Some(head_bold_bool))
|
||||
.fg(head_color_style
|
||||
.foreground
|
||||
.unwrap_or(ansi_term::Color::Green))
|
||||
}
|
||||
|
||||
fn table_mode(&self) -> nu_table::Theme {
|
||||
|
Reference in New Issue
Block a user