allow flatshape (command line syntax) theming (#502)

* allow flatshape (command line syntax) theming

* renamed crate, organized
This commit is contained in:
Darren Schroeder 2021-12-16 06:17:29 -06:00 committed by GitHub
parent 17a7a85c78
commit 9a864b5017
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 379 additions and 162 deletions

36
Cargo.lock generated
View File

@ -842,8 +842,9 @@ dependencies = [
"ctrlc",
"dialoguer",
"miette",
"nu-ansi-term 0.39.0",
"nu-ansi-term",
"nu-cli",
"nu-color-config",
"nu-command",
"nu-engine",
"nu-json",
@ -1630,18 +1631,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "nu-ansi-term"
version = "0.39.0"
dependencies = [
"doc-comment",
"overload",
"regex",
"serde",
"serde_json",
"winapi",
]
[[package]]
name = "nu-ansi-term"
version = "0.39.0"
@ -1657,7 +1646,8 @@ name = "nu-cli"
version = "0.1.0"
dependencies = [
"miette",
"nu-ansi-term 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)",
"nu-ansi-term",
"nu-color-config",
"nu-engine",
"nu-parser",
"nu-path",
@ -1666,6 +1656,17 @@ dependencies = [
"thiserror",
]
[[package]]
name = "nu-color-config"
version = "0.1.0"
dependencies = [
"nu-ansi-term",
"nu-json",
"nu-protocol",
"nu-table",
"serde",
]
[[package]]
name = "nu-command"
version = "0.1.0"
@ -1692,7 +1693,8 @@ dependencies = [
"lscolors",
"md-5",
"meval",
"nu-ansi-term 0.39.0",
"nu-ansi-term",
"nu-color-config",
"nu-engine",
"nu-json",
"nu-parser",
@ -1807,7 +1809,7 @@ version = "0.36.0"
dependencies = [
"ansi-cut",
"atty",
"nu-ansi-term 0.39.0",
"nu-ansi-term",
"nu-protocol",
"regex",
"strip-ansi-escapes",
@ -2518,7 +2520,7 @@ source = "git+https://github.com/nushell/reedline?branch=main#e512512dd4af9f3aad
dependencies = [
"chrono",
"crossterm",
"nu-ansi-term 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)",
"nu-ansi-term",
"serde",
"strip-ansi-escapes",
"unicode-segmentation",

View File

@ -33,7 +33,9 @@ nu-protocol = { path = "./crates/nu-protocol" }
nu-plugin = { path = "./crates/nu-plugin", optional = true }
nu-table = { path = "./crates/nu-table" }
nu-term-grid = { path = "./crates/nu-term-grid" }
nu-ansi-term = { path = "./crates/nu-ansi-term" }
# nu-ansi-term = { path = "./crates/nu-ansi-term" }
nu-ansi-term = "0.39.0"
nu-color-config = { path = "./crates/nu-color-config" }
miette = "3.0.0"
ctrlc = "3.2.1"
crossterm_winapi = "0.9.0"

View File

@ -8,8 +8,10 @@ nu-engine = { path = "../nu-engine" }
nu-path = { path = "../nu-path" }
nu-parser = { path = "../nu-parser" }
nu-protocol = { path = "../nu-protocol" }
# nu-ansi-term = { path = "../nu-ansi-term" }
nu-ansi-term = "0.39.0"
nu-color-config = { path = "../nu-color-config" }
miette = { version = "3.0.0", features = ["fancy"] }
thiserror = "1.0.29"
nu-ansi-term = "0.39.0"
reedline = { git = "https://github.com/nushell/reedline", branch = "main" }

View File

@ -1,10 +1,13 @@
use nu_ansi_term::Style;
use nu_color_config::get_shape_color;
use nu_parser::{flatten_block, parse, FlatShape};
use nu_protocol::engine::{EngineState, StateWorkingSet};
use nu_protocol::Config;
use reedline::{Highlighter, StyledText};
pub struct NuHighlighter {
pub engine_state: EngineState,
pub config: Config,
}
impl Highlighter for NuHighlighter {
@ -36,92 +39,104 @@ impl Highlighter for NuHighlighter {
[(shape.0.start - global_span_offset)..(shape.0.end - global_span_offset)]
.to_string();
match shape.1 {
FlatShape::Custom(..) => output.push((Style::new().bold(), next_token)),
FlatShape::External => {
// nushell ExternalCommand
output.push((Style::new().fg(nu_ansi_term::Color::Cyan), next_token))
}
FlatShape::ExternalArg => {
// nushell ExternalWord
FlatShape::Garbage => output.push((
// nushell Garbage
get_shape_color(shape.1.to_string(), &self.config),
next_token,
)),
FlatShape::Bool => {
// nushell ?
output.push((
Style::new().fg(nu_ansi_term::Color::Green).bold(),
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::Garbage => output.push((
// nushell Garbage
Style::new()
.fg(nu_ansi_term::Color::White)
.on(nu_ansi_term::Color::Red)
.bold(),
next_token,
)),
FlatShape::InternalCall => output.push((
// nushell InternalCommand
Style::new().fg(nu_ansi_term::Color::Cyan).bold(),
next_token,
)),
FlatShape::Int => {
// nushell Int
output.push((
Style::new().fg(nu_ansi_term::Color::Purple).bold(),
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::Float => {
// nushell Decimal
output.push((
Style::new().fg(nu_ansi_term::Color::Purple).bold(),
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::Range => output.push((
// nushell DotDot ?
Style::new().fg(nu_ansi_term::Color::Yellow).bold(),
get_shape_color(shape.1.to_string(), &self.config),
next_token,
)),
FlatShape::Bool => {
// nushell ?
output.push((Style::new().fg(nu_ansi_term::Color::LightCyan), next_token))
FlatShape::InternalCall => output.push((
// nushell InternalCommand
get_shape_color(shape.1.to_string(), &self.config),
next_token,
)),
FlatShape::External => {
// nushell ExternalCommand
output.push((
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::ExternalArg => {
// nushell ExternalWord
output.push((
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::Literal => {
// nushell ?
output.push((Style::new().fg(nu_ansi_term::Color::Blue), next_token))
output.push((
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::Operator => output.push((
// nushell Operator
Style::new().fg(nu_ansi_term::Color::Yellow),
get_shape_color(shape.1.to_string(), &self.config),
next_token,
)),
FlatShape::Signature => output.push((
// nushell ?
Style::new().fg(nu_ansi_term::Color::Green).bold(),
get_shape_color(shape.1.to_string(), &self.config),
next_token,
)),
FlatShape::String => {
// nushell String
output.push((Style::new().fg(nu_ansi_term::Color::Green), next_token))
}
FlatShape::Flag => {
// nushell Flag
output.push((
Style::new().fg(nu_ansi_term::Color::Blue).bold(),
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::Filepath => output.push((
// nushell Path
Style::new().fg(nu_ansi_term::Color::Cyan),
get_shape_color(shape.1.to_string(), &self.config),
next_token,
)),
FlatShape::GlobPattern => output.push((
// nushell GlobPattern
Style::new().fg(nu_ansi_term::Color::Cyan).bold(),
get_shape_color(shape.1.to_string(), &self.config),
next_token,
)),
FlatShape::Variable => output.push((
// nushell Variable
Style::new().fg(nu_ansi_term::Color::Purple),
get_shape_color(shape.1.to_string(), &self.config),
next_token,
)),
FlatShape::Flag => {
// nushell Flag
output.push((
get_shape_color(shape.1.to_string(), &self.config),
next_token,
))
}
FlatShape::Custom(..) => output.push((
get_shape_color(shape.1.to_string(), &self.config),
next_token,
)),
}

View File

@ -0,0 +1,13 @@
[package]
name = "nu-color-config"
version = "0.1.0"
edition = "2018"
[dependencies]
nu-protocol = { path = "../nu-protocol" }
# nu-ansi-term = { path = "../nu-ansi-term" }
nu-ansi-term = "0.39.0"
nu-json = { path = "../nu-json" }
nu-table = { path = "../nu-table" }
serde = { version="1.0.123", features=["derive"] }

View File

@ -1,7 +1,7 @@
use crate::nu_style::{color_from_hex, color_string_to_nustyle};
use nu_ansi_term::{Color, Style};
use nu_protocol::Config;
use nu_table::{Alignment, TextStyle};
use serde::Deserialize;
use std::collections::HashMap;
//TODO: should this be implemented again?
@ -15,105 +15,6 @@ use std::collections::HashMap;
// }
// }
#[derive(Deserialize, PartialEq, Debug)]
struct NuStyle {
fg: Option<String>,
bg: Option<String>,
attr: Option<String>,
}
fn parse_nustyle(nu_style: NuStyle) -> Style {
// get the nu_ansi_term::Color foreground color
let fg_color = match nu_style.fg {
Some(fg) => color_from_hex(&fg).expect("error with foreground color"),
_ => None,
};
// get the nu_ansi_term::Color background color
let bg_color = match nu_style.bg {
Some(bg) => color_from_hex(&bg).expect("error with background color"),
_ => None,
};
// get the attributes
let color_attr = match nu_style.attr {
Some(attr) => attr,
_ => "".to_string(),
};
// setup the attributes available in nu_ansi_term::Style
let mut bold = false;
let mut dimmed = false;
let mut italic = false;
let mut underline = false;
let mut blink = false;
let mut reverse = false;
let mut hidden = false;
let mut strikethrough = false;
// since we can combine styles like bold-italic, iterate through the chars
// and set the bools for later use in the nu_ansi_term::Style application
for ch in color_attr.to_lowercase().chars() {
match ch {
'l' => blink = true,
'b' => bold = true,
'd' => dimmed = true,
'h' => hidden = true,
'i' => italic = true,
'r' => reverse = true,
's' => strikethrough = true,
'u' => underline = true,
'n' => (),
_ => (),
}
}
// here's where we build the nu_ansi_term::Style
Style {
foreground: fg_color,
background: bg_color,
is_blink: blink,
is_bold: bold,
is_dimmed: dimmed,
is_hidden: hidden,
is_italic: italic,
is_reverse: reverse,
is_strikethrough: strikethrough,
is_underline: underline,
}
}
fn color_string_to_nustyle(color_string: String) -> Style {
// eprintln!("color_string: {}", &color_string);
if color_string.chars().count() < 1 {
Style::default()
} else {
let nu_style = match nu_json::from_str::<NuStyle>(&color_string) {
Ok(s) => s,
Err(_) => NuStyle {
fg: None,
bg: None,
attr: None,
},
};
parse_nustyle(nu_style)
}
}
fn color_from_hex(hex_color: &str) -> std::result::Result<Option<Color>, std::num::ParseIntError> {
// right now we only allow hex colors with hashtag and 6 characters
let trimmed = hex_color.trim_matches('#');
if trimmed.len() != 6 {
Ok(None)
} else {
// make a nu_ansi_term::Color::Rgb color by converting hex to decimal
Ok(Some(Color::Rgb(
u8::from_str_radix(&trimmed[..2], 16)?,
u8::from_str_radix(&trimmed[2..4], 16)?,
u8::from_str_radix(&trimmed[4..6], 16)?,
)))
}
}
pub fn lookup_ansi_color_style(s: String) -> Style {
if s.starts_with('#') {
match color_from_hex(&s) {

View File

@ -0,0 +1,7 @@
mod color_config;
mod nu_style;
mod shape_color;
pub use color_config::*;
pub use nu_style::*;
pub use shape_color::*;

View File

@ -0,0 +1,103 @@
use nu_ansi_term::{Color, Style};
use serde::Deserialize;
#[derive(Deserialize, PartialEq, Debug)]
struct NuStyle {
fg: Option<String>,
bg: Option<String>,
attr: Option<String>,
}
fn parse_nustyle(nu_style: NuStyle) -> Style {
// get the nu_ansi_term::Color foreground color
let fg_color = match nu_style.fg {
Some(fg) => color_from_hex(&fg).expect("error with foreground color"),
_ => None,
};
// get the nu_ansi_term::Color background color
let bg_color = match nu_style.bg {
Some(bg) => color_from_hex(&bg).expect("error with background color"),
_ => None,
};
// get the attributes
let color_attr = match nu_style.attr {
Some(attr) => attr,
_ => "".to_string(),
};
// setup the attributes available in nu_ansi_term::Style
let mut bold = false;
let mut dimmed = false;
let mut italic = false;
let mut underline = false;
let mut blink = false;
let mut reverse = false;
let mut hidden = false;
let mut strikethrough = false;
// since we can combine styles like bold-italic, iterate through the chars
// and set the bools for later use in the nu_ansi_term::Style application
for ch in color_attr.to_lowercase().chars() {
match ch {
'l' => blink = true,
'b' => bold = true,
'd' => dimmed = true,
'h' => hidden = true,
'i' => italic = true,
'r' => reverse = true,
's' => strikethrough = true,
'u' => underline = true,
'n' => (),
_ => (),
}
}
// here's where we build the nu_ansi_term::Style
Style {
foreground: fg_color,
background: bg_color,
is_blink: blink,
is_bold: bold,
is_dimmed: dimmed,
is_hidden: hidden,
is_italic: italic,
is_reverse: reverse,
is_strikethrough: strikethrough,
is_underline: underline,
}
}
pub fn color_string_to_nustyle(color_string: String) -> Style {
// eprintln!("color_string: {}", &color_string);
if color_string.chars().count() < 1 {
Style::default()
} else {
let nu_style = match nu_json::from_str::<NuStyle>(&color_string) {
Ok(s) => s,
Err(_) => NuStyle {
fg: None,
bg: None,
attr: None,
},
};
parse_nustyle(nu_style)
}
}
pub fn color_from_hex(
hex_color: &str,
) -> std::result::Result<Option<Color>, std::num::ParseIntError> {
// right now we only allow hex colors with hashtag and 6 characters
let trimmed = hex_color.trim_matches('#');
if trimmed.len() != 6 {
Ok(None)
} else {
// make a nu_ansi_term::Color::Rgb color by converting hex to decimal
Ok(Some(Color::Rgb(
u8::from_str_radix(&trimmed[..2], 16)?,
u8::from_str_radix(&trimmed[2..4], 16)?,
u8::from_str_radix(&trimmed[4..6], 16)?,
)))
}
}

View File

@ -0,0 +1,145 @@
use crate::color_config::lookup_ansi_color_style;
use nu_ansi_term::{Color, Style};
use nu_protocol::Config;
pub fn get_shape_color(shape: String, conf: &Config) -> Style {
match shape.as_ref() {
"flatshape_garbage" => {
if conf.color_config.contains_key("flatshape_garbage") {
let int_color = &conf.color_config["flatshape_garbage"];
lookup_ansi_color_style(int_color.to_string())
} else {
Style::new().fg(Color::White).on(Color::Red).bold()
}
}
"flatshape_bool" => {
if conf.color_config.contains_key("flatshape_bool") {
let int_color = &conf.color_config["flatshape_bool"];
lookup_ansi_color_style(int_color.to_string())
} else {
Style::new().fg(Color::LightCyan)
}
}
"flatshape_int" => {
if conf.color_config.contains_key("flatshape_int") {
let int_color = &conf.color_config["flatshape_int"];
lookup_ansi_color_style(int_color.to_string())
} else {
Style::new().fg(Color::Purple).bold()
}
}
"flatshape_float" => {
if conf.color_config.contains_key("flatshape_float") {
let int_color = &conf.color_config["flatshape_float"];
lookup_ansi_color_style(int_color.to_string())
} else {
Style::new().fg(Color::Purple).bold()
}
}
"flatshape_range" => {
if conf.color_config.contains_key("flatshape_range") {
let int_color = &conf.color_config["flatshape_range"];
lookup_ansi_color_style(int_color.to_string())
} else {
Style::new().fg(Color::Yellow).bold()
}
}
"flatshape_internalcall" => {
if conf.color_config.contains_key("flatshape_internalcall") {
let int_color = &conf.color_config["flatshape_internalcall"];
lookup_ansi_color_style(int_color.to_string())
} else {
Style::new().fg(Color::Cyan).bold()
}
}
"flatshape_external" => {
if conf.color_config.contains_key("flatshape_external") {
let int_color = &conf.color_config["flatshape_external"];
lookup_ansi_color_style(int_color.to_string())
} else {
Style::new().fg(Color::Cyan)
}
}
"flatshape_externalarg" => {
if conf.color_config.contains_key("flatshape_externalarg") {
let int_color = &conf.color_config["flatshape_externalarg"];
lookup_ansi_color_style(int_color.to_string())
} else {
Style::new().fg(Color::Green).bold()
}
}
"flatshape_literal" => {
if conf.color_config.contains_key("flatshape_literal") {
let int_color = &conf.color_config["flatshape_literal"];
lookup_ansi_color_style(int_color.to_string())
} else {
Style::new().fg(Color::Blue)
}
}
"flatshape_operator" => {
if conf.color_config.contains_key("flatshape_operator") {
let int_color = &conf.color_config["flatshape_operator"];
lookup_ansi_color_style(int_color.to_string())
} else {
Style::new().fg(Color::Yellow)
}
}
"flatshape_signature" => {
if conf.color_config.contains_key("flatshape_signature") {
let int_color = &conf.color_config["flatshape_signature"];
lookup_ansi_color_style(int_color.to_string())
} else {
Style::new().fg(Color::Green).bold()
}
}
"flatshape_string" => {
if conf.color_config.contains_key("flatshape_string") {
let int_color = &conf.color_config["flatshape_string"];
lookup_ansi_color_style(int_color.to_string())
} else {
Style::new().fg(Color::Green)
}
}
"flatshape_filepath" => {
if conf.color_config.contains_key("flatshape_filepath") {
let int_color = &conf.color_config["flatshape_filepath"];
lookup_ansi_color_style(int_color.to_string())
} else {
Style::new().fg(Color::Cyan)
}
}
"flatshape_globpattern" => {
if conf.color_config.contains_key("flatshape_globpattern") {
let int_color = &conf.color_config["flatshape_globpattern"];
lookup_ansi_color_style(int_color.to_string())
} else {
Style::new().fg(Color::Cyan).bold()
}
}
"flatshape_variable" => {
if conf.color_config.contains_key("flatshape_variable") {
let int_color = &conf.color_config["flatshape_variable"];
lookup_ansi_color_style(int_color.to_string())
} else {
Style::new().fg(Color::Purple)
}
}
"flatshape_flag" => {
if conf.color_config.contains_key("flatshape_flag") {
let int_color = &conf.color_config["flatshape_flag"];
lookup_ansi_color_style(int_color.to_string())
} else {
Style::new().fg(Color::Blue).bold()
}
}
"flatshape_custom" => {
if conf.color_config.contains_key("flatshape_custom") {
let int_color = &conf.color_config["flatshape_custom"];
lookup_ansi_color_style(int_color.to_string())
} else {
Style::new().bold()
}
}
_ => Style::default(),
}
}

View File

@ -15,7 +15,9 @@ nu-protocol = { path = "../nu-protocol" }
nu-table = { path = "../nu-table" }
nu-term-grid = { path = "../nu-term-grid" }
nu-parser = { path = "../nu-parser" }
nu-ansi-term = { path = "../nu-ansi-term" }
# nu-ansi-term = { path = "../nu-ansi-term" }
nu-ansi-term = "0.39.0"
nu-color-config = { path = "../nu-color-config" }
# Potential dependencies for extras
url = "2.2.1"

View File

@ -1,4 +1,3 @@
mod color_config;
mod griddle;
mod icons;
mod table;

View File

@ -1,6 +1,5 @@
use super::color_config::style_primitive;
use crate::viewers::color_config::get_color_config;
use lscolors::{LsColors, Style};
use nu_color_config::{get_color_config, style_primitive};
use nu_protocol::ast::{Call, PathMember};
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{

View File

@ -2,6 +2,7 @@ use nu_protocol::ast::{
Block, Expr, Expression, ImportPatternMember, PathMember, Pipeline, Statement,
};
use nu_protocol::{engine::StateWorkingSet, Span};
use std::fmt::{Display, Formatter, Result};
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum FlatShape {
@ -24,6 +25,30 @@ pub enum FlatShape {
Custom(String),
}
impl Display for FlatShape {
fn fmt(&self, f: &mut Formatter) -> Result {
match self {
FlatShape::Garbage => write!(f, "flatshape_garbage"),
FlatShape::Bool => write!(f, "flatshape_bool"),
FlatShape::Int => write!(f, "flatshape_int"),
FlatShape::Float => write!(f, "flatshape_float"),
FlatShape::Range => write!(f, "flatshape_range"),
FlatShape::InternalCall => write!(f, "flatshape_internalcall"),
FlatShape::External => write!(f, "flatshape_external"),
FlatShape::ExternalArg => write!(f, "flatshape_externalarg"),
FlatShape::Literal => write!(f, "flatshape_literal"),
FlatShape::Operator => write!(f, "flatshape_operator"),
FlatShape::Signature => write!(f, "flatshape_signature"),
FlatShape::String => write!(f, "flatshape_string"),
FlatShape::Filepath => write!(f, "flatshape_filepath"),
FlatShape::GlobPattern => write!(f, "flatshape_globpattern"),
FlatShape::Variable => write!(f, "flatshape_variable"),
FlatShape::Flag => write!(f, "flatshape_flag"),
FlatShape::Custom(_) => write!(f, "flatshape_custom"),
}
}
}
pub fn flatten_block(working_set: &StateWorkingSet, block: &Block) -> Vec<(Span, FlatShape)> {
let mut output = vec![];
for stmt in &block.stmts {

View File

@ -12,7 +12,8 @@ name = "table"
path = "src/main.rs"
[dependencies]
nu-ansi-term = { path = "../nu-ansi-term" }
# nu-ansi-term = { path = "../nu-ansi-term" }
nu-ansi-term = "0.39.0"
nu-protocol = { path = "../nu-protocol"}
regex = "1.4"
unicode-width = "0.1.8"

View File

@ -317,6 +317,7 @@ fn main() -> Result<()> {
}))
.with_highlighter(Box::new(NuHighlighter {
engine_state: engine_state.clone(),
config: config.clone(),
}))
.with_animation(config.animate_prompt)
// .with_completion_action_handler(Box::new(