menu options (#748)

This commit is contained in:
Fernando Herrera 2022-01-15 17:01:44 +00:00 committed by GitHub
parent f9c0d223c1
commit 89d99db94f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 126 additions and 49 deletions

2
Cargo.lock generated
View File

@ -2845,7 +2845,7 @@ dependencies = [
[[package]]
name = "reedline"
version = "0.2.0"
source = "git+https://github.com/nushell/reedline?branch=main#56025adb65f1c27078d64e5d6220827a6f0ebdb3"
source = "git+https://github.com/nushell/reedline?branch=main#4c3c23c9594ab2d58015fc75beb9fd884b763614"
dependencies = [
"chrono",
"crossterm",

View File

@ -4,9 +4,9 @@ use nu_protocol::Config;
use nu_table::{Alignment, TextStyle};
use std::collections::HashMap;
pub fn lookup_ansi_color_style(s: String) -> Style {
pub fn lookup_ansi_color_style(s: &str) -> Style {
if s.starts_with('#') {
match color_from_hex(&s) {
match color_from_hex(s) {
Ok(c) => match c {
Some(c) => c.normal(),
None => Style::default(),
@ -14,9 +14,9 @@ pub fn lookup_ansi_color_style(s: String) -> Style {
Err(_) => Style::default(),
}
} else if s.starts_with('{') {
color_string_to_nustyle(s)
color_string_to_nustyle(s.to_string())
} else {
match s.as_str() {
match s {
"g" | "green" => Color::Green.normal(),
"gb" | "green_bold" => Color::Green.bold(),
"gu" | "green_underline" => Color::Green.underline(),
@ -168,7 +168,7 @@ pub fn lookup_ansi_color_style(s: String) -> Style {
fn update_hashmap(key: &str, val: &str, hm: &mut HashMap<String, Style>) {
// eprintln!("key: {}, val: {}", &key, &val);
let color = lookup_ansi_color_style(val.to_string());
let color = lookup_ansi_color_style(val);
if let Some(v) = hm.get_mut(key) {
*v = color;
} else {
@ -210,7 +210,10 @@ pub fn get_color_config(config: &Config) -> HashMap<String, Style> {
hm.insert("hints".to_string(), Color::DarkGray.normal());
for (key, value) in &config.color_config {
update_hashmap(key, value, &mut hm);
let value = value
.as_string()
.expect("the only values for config color must be strings");
update_hashmap(key, &value, &mut hm);
// eprintln!(
// "config: {}:{}\t\t\thashmap: {}:{:?}",

View File

@ -4,7 +4,10 @@ use nu_protocol::Config;
pub fn get_shape_color(shape: String, conf: &Config) -> Style {
match conf.color_config.get(shape.as_str()) {
Some(int_color) => lookup_ansi_color_style(int_color.to_string()),
Some(int_color) => match int_color.as_string() {
Ok(int_color) => lookup_ansi_color_style(&int_color),
Err(_) => Style::default(),
},
None => match shape.as_ref() {
"flatshape_garbage" => Style::new().fg(Color::White).on(Color::Red).bold(),
"flatshape_bool" => Style::new().fg(Color::LightCyan),

View File

@ -43,7 +43,7 @@ pub struct Config {
pub filesize_metric: bool,
pub table_mode: String,
pub use_ls_colors: bool,
pub color_config: HashMap<String, String>,
pub color_config: HashMap<String, Value>,
pub use_grid_icons: bool,
pub footer_mode: FooterMode,
pub animate_prompt: bool,
@ -54,6 +54,7 @@ pub struct Config {
pub edit_mode: String,
pub max_history_size: i64,
pub log_level: String,
pub menu_config: HashMap<String, Value>,
}
impl Default for Config {
@ -73,6 +74,7 @@ impl Default for Config {
edit_mode: "emacs".into(),
max_history_size: 1000,
log_level: String::new(),
menu_config: HashMap::new(),
}
}
}
@ -107,42 +109,7 @@ impl Value {
config.use_ls_colors = value.as_bool()?;
}
"color_config" => {
let (cols, inner_vals) = value.as_record()?;
let mut hm = HashMap::new();
for (k, v) in cols.iter().zip(inner_vals) {
match &v {
Value::Record {
cols: inner_cols,
vals: inner_vals,
span: _,
} => {
// make a string from our config.color_config section that
// looks like this: { fg: "#rrggbb" bg: "#rrggbb" attr: "abc", }
// the real key here was to have quotes around the values but not
// require them around the keys.
// maybe there's a better way to generate this but i'm not sure
// what it is.
let key = k.to_string();
let mut val: String = inner_cols
.iter()
.zip(inner_vals)
.map(|(x, y)| {
let clony = y.clone();
format!("{}: \"{}\" ", x, clony.into_string(", ", &config))
})
.collect();
// now insert the braces at the front and the back to fake the json string
val.insert(0, '{');
val.push('}');
hm.insert(key, val);
}
_ => {
hm.insert(k.to_string(), v.as_string()?);
}
}
}
config.color_config = hm;
config.color_config = create_map(value, &config)?;
}
"use_grid_icons" => {
config.use_grid_icons = value.as_bool()?;
@ -191,6 +158,9 @@ impl Value {
"log_level" => {
config.log_level = value.as_string()?;
}
"menu_config" => {
config.menu_config = create_map(value, &config)?;
}
_ => {}
}
}
@ -198,3 +168,48 @@ impl Value {
Ok(config)
}
}
fn create_map(value: &Value, config: &Config) -> Result<HashMap<String, Value>, ShellError> {
let (cols, inner_vals) = value.as_record()?;
let mut hm: HashMap<String, Value> = HashMap::new();
for (k, v) in cols.iter().zip(inner_vals) {
match &v {
Value::Record {
cols: inner_cols,
vals: inner_vals,
span,
} => {
// make a string from our config.color_config section that
// looks like this: { fg: "#rrggbb" bg: "#rrggbb" attr: "abc", }
// the real key here was to have quotes around the values but not
// require them around the keys.
// maybe there's a better way to generate this but i'm not sure
// what it is.
let key = k.to_string();
let val: String = inner_cols
.iter()
.zip(inner_vals)
.map(|(x, y)| {
let clony = y.clone();
format!("{}: \"{}\" ", x, clony.into_string(", ", config))
})
.collect();
// now insert the braces at the front and the back to fake the json string
let val = Value::String {
val: format!("{{{}}}", val),
span: *span,
};
hm.insert(key, val);
}
_ => {
hm.insert(k.to_string(), v.clone());
}
}
}
Ok(hm)
}

View File

@ -9,7 +9,7 @@ use dialoguer::{
use log::trace;
use miette::{IntoDiagnostic, Result};
use nu_cli::{CliError, NuCompleter, NuHighlighter, NuValidator, NushellPrompt};
use nu_color_config::get_color_config;
use nu_color_config::{get_color_config, lookup_ansi_color_style};
use nu_command::create_default_context;
use nu_engine::{convert_env_values, eval_block};
use nu_parser::{lex, parse, trim_quotes, Token, TokenContents};
@ -19,8 +19,8 @@ use nu_protocol::{
Config, PipelineData, ShellError, Span, Value, CONFIG_VARIABLE_ID,
};
use reedline::{
default_emacs_keybindings, Completer, CompletionActionHandler, DefaultHinter, EditCommand,
Emacs, LineBuffer, Prompt, ReedlineEvent, Vi,
default_emacs_keybindings, Completer, CompletionActionHandler, ContextMenuInput, DefaultHinter,
EditCommand, Emacs, LineBuffer, Prompt, ReedlineEvent, Vi,
};
use std::{
io::Write,
@ -435,7 +435,11 @@ fn main() -> Result<()> {
}))
.with_edit_mode(edit_mode)
.with_ansi_colors(config.use_ansi_coloring)
.with_menu_completer(Box::new(NuCompleter::new(engine_state.clone())));
.with_menu_completer(
Box::new(NuCompleter::new(engine_state.clone())),
create_menu_input(&config),
);
//FIXME: if config.use_ansi_coloring is false then we should
// turn off the hinter but I don't see any way to do that yet.
@ -587,6 +591,58 @@ fn main() -> Result<()> {
}
}
// This creates an input object for the context menu based on the dictionary
// stored in the config variable
fn create_menu_input(config: &Config) -> ContextMenuInput {
let mut input = ContextMenuInput::default();
input = match config
.menu_config
.get("columns")
.and_then(|value| value.as_integer().ok())
{
Some(value) => input.with_columns(value as u16),
None => input,
};
input = input.with_col_width(
config
.menu_config
.get("col_width")
.and_then(|value| value.as_integer().ok())
.map(|value| value as usize),
);
input = match config
.menu_config
.get("col_padding")
.and_then(|value| value.as_integer().ok())
{
Some(value) => input.with_col_padding(value as usize),
None => input,
};
input = match config
.menu_config
.get("text_style")
.and_then(|value| value.as_string().ok())
{
Some(value) => input.with_text_style(lookup_ansi_color_style(&value)),
None => input,
};
input = match config
.menu_config
.get("selected_text_style")
.and_then(|value| value.as_string().ok())
{
Some(value) => input.with_selected_text_style(lookup_ansi_color_style(&value)),
None => input,
};
input
}
// This fill collect environment variables from std::env and adds them to a stack.
//
// In order to ensure the values have spans, it first creates a dummy file, writes the collected