history-menu (#846)

This commit is contained in:
Fernando Herrera 2022-01-25 09:39:22 +00:00 committed by GitHub
parent 0cecaf82b1
commit 69954a362d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 87 additions and 12 deletions

2
Cargo.lock generated
View File

@ -2863,7 +2863,7 @@ dependencies = [
[[package]]
name = "reedline"
version = "0.2.0"
source = "git+https://github.com/nushell/reedline?branch=main#7a07ab2bcca2e0287a1efcf8ccdf9845229428c5"
source = "git+https://github.com/nushell/reedline?branch=main#d7f42e5de4aeee9332dc8eaff07e68923401edcf"
dependencies = [
"chrono",
"crossterm",

View File

@ -17,6 +17,7 @@ pub struct NushellPrompt {
default_vi_visual_prompt_indicator: String,
default_menu_prompt_indicator: String,
default_multiline_indicator: String,
default_history_prompt_indicator: String,
}
impl Default for NushellPrompt {
@ -35,6 +36,7 @@ impl NushellPrompt {
default_vi_visual_prompt_indicator: "v ".to_string(),
default_menu_prompt_indicator: "| ".to_string(),
default_multiline_indicator: "::: ".to_string(),
default_history_prompt_indicator: "? ".to_string(),
}
}
@ -67,11 +69,12 @@ impl NushellPrompt {
left_prompt_string: Option<String>,
right_prompt_string: Option<String>,
prompt_indicator_string: String,
prompt_indicator_menu: String,
prompt_multiline_indicator_string: String,
prompt_vi: (String, String),
prompt_menus: (String, String),
) {
let (prompt_vi_insert_string, prompt_vi_visual_string) = prompt_vi;
let (prompt_indicator_menu, prompt_history_indicator_menu) = prompt_menus;
self.left_prompt_string = left_prompt_string;
self.right_prompt_string = right_prompt_string;
@ -79,7 +82,9 @@ impl NushellPrompt {
self.default_vi_insert_prompt_indicator = prompt_vi_insert_string;
self.default_vi_visual_prompt_indicator = prompt_vi_visual_string;
self.default_multiline_indicator = prompt_multiline_indicator_string;
self.default_menu_prompt_indicator = prompt_indicator_menu;
self.default_history_prompt_indicator = prompt_history_indicator_menu;
}
fn default_wrapped_custom_string(&self, str: String) -> String {
@ -117,6 +122,7 @@ impl Prompt for NushellPrompt {
},
PromptEditMode::Custom(str) => self.default_wrapped_custom_string(str).into(),
PromptEditMode::Menu => self.default_menu_prompt_indicator.as_str().into(),
PromptEditMode::HistoryMenu => self.default_history_prompt_indicator.as_str().into(),
}
}

View File

@ -65,6 +65,7 @@ pub struct Config {
pub log_level: String,
pub menu_config: HashMap<String, Value>,
pub keybindings: Vec<ParsedKeybinding>,
pub history_config: HashMap<String, Value>,
}
impl Default for Config {
@ -86,6 +87,7 @@ impl Default for Config {
log_level: String::new(),
menu_config: HashMap::new(),
keybindings: Vec::new(),
history_config: HashMap::new(),
}
}
}
@ -243,6 +245,13 @@ impl Value {
eprintln!("$config.keybindings is not a valid keybindings list")
}
}
"history_config" => {
if let Ok(map) = create_map(value, &config) {
config.history_config = map;
} else {
eprintln!("$config.history_config is not a record")
}
}
x => {
eprintln!("$config.{} is an unknown config setting", x)
}

View File

@ -15,12 +15,13 @@ pub(crate) const PROMPT_INDICATOR_VI_INSERT: &str = "PROMPT_INDICATOR_VI_INSERT"
pub(crate) const PROMPT_INDICATOR_VI_VISUAL: &str = "PROMPT_INDICATOR_VI_VISUAL";
pub(crate) const PROMPT_INDICATOR_MENU: &str = "PROMPT_INDICATOR_MENU";
pub(crate) const PROMPT_MULTILINE_INDICATOR: &str = "PROMPT_MULTILINE_INDICATOR";
pub(crate) const PROMPT_INDICATOR_HISTORY: &str = "PROMPT_INDICATOR_HISTORY";
pub(crate) fn get_prompt_indicators(
config: &Config,
engine_state: &EngineState,
stack: &Stack,
) -> (String, String, String, String, String) {
) -> (String, String, String, String, String, String) {
let prompt_indicator = match stack.get_env_var(engine_state, PROMPT_INDICATOR) {
Some(pi) => pi.into_string("", config),
None => "".to_string(),
@ -36,22 +37,28 @@ pub(crate) fn get_prompt_indicators(
None => "v ".to_string(),
};
let prompt_multiline = match stack.get_env_var(engine_state, PROMPT_MULTILINE_INDICATOR) {
Some(pm) => pm.into_string("", config),
None => "::: ".to_string(),
};
let prompt_menu = match stack.get_env_var(engine_state, PROMPT_INDICATOR_MENU) {
Some(pm) => pm.into_string("", config),
None => "| ".to_string(),
};
let prompt_multiline = match stack.get_env_var(engine_state, PROMPT_MULTILINE_INDICATOR) {
Some(pm) => pm.into_string("", config),
None => "::: ".to_string(),
let prompt_history = match stack.get_env_var(engine_state, PROMPT_INDICATOR_HISTORY) {
Some(ph) => ph.into_string("", config),
None => "? ".to_string(),
};
(
prompt_indicator,
prompt_vi_insert,
prompt_vi_visual,
prompt_menu,
prompt_multiline,
prompt_menu,
prompt_history,
)
}
@ -101,8 +108,9 @@ pub(crate) fn update_prompt<'prompt>(
prompt_indicator_string,
prompt_vi_insert_string,
prompt_vi_visual_string,
prompt_indicator_menu,
prompt_multiline_string,
prompt_indicator_menu,
prompt_indicator_history,
) = get_prompt_indicators(config, engine_state, stack);
let mut stack = stack.clone();
@ -112,9 +120,9 @@ pub(crate) fn update_prompt<'prompt>(
get_prompt_string(PROMPT_COMMAND, config, engine_state, &mut stack),
get_prompt_string(PROMPT_COMMAND_RIGHT, config, engine_state, &mut stack),
prompt_indicator_string,
prompt_indicator_menu,
prompt_multiline_string,
(prompt_vi_insert_string, prompt_vi_visual_string),
(prompt_indicator_menu, prompt_indicator_history),
);
nu_prompt as &dyn Prompt

View File

@ -3,10 +3,10 @@ use nu_color_config::lookup_ansi_color_style;
use nu_protocol::{extract_value, Config, ParsedKeybinding, ShellError, Span, Type, Value};
use reedline::{
default_emacs_keybindings, default_vi_insert_keybindings, default_vi_normal_keybindings,
ContextMenuInput, EditCommand, Keybindings, ReedlineEvent,
ContextMenuInput, EditCommand, HistoryMenuInput, Keybindings, ReedlineEvent,
};
// This creates an input object for the context menu based on the dictionary
// Creates an input object for the context menu based on the dictionary
// stored in the config variable
pub(crate) fn create_menu_input(config: &Config) -> ContextMenuInput {
let mut input = ContextMenuInput::default();
@ -58,6 +58,52 @@ pub(crate) fn create_menu_input(config: &Config) -> ContextMenuInput {
input
}
// Creates an input object for the history menu based on the dictionary
// stored in the config variable
pub(crate) fn create_history_input(config: &Config) -> HistoryMenuInput {
let mut input = HistoryMenuInput::default();
input = match config
.history_config
.get("page_size")
.and_then(|value| value.as_integer().ok())
{
Some(value) => input.with_page_size(value as usize),
None => input,
};
input = match config
.history_config
.get("selector")
.and_then(|value| value.as_string().ok())
{
Some(value) => {
let char = value.chars().next().unwrap_or(':');
input.with_row_char(char)
}
None => input,
};
input = match config
.history_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
.history_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
}
pub enum KeybindingsMode {
Emacs(Keybindings),
Vi {
@ -215,6 +261,11 @@ fn parse_event(value: Value, config: &Config) -> Result<ReedlineEvent, ShellErro
"menuright" => ReedlineEvent::MenuRight,
"menunext" => ReedlineEvent::MenuNext,
"menuprevious" => ReedlineEvent::MenuPrevious,
"historymenu" => ReedlineEvent::HistoryMenu,
"historymenunext" => ReedlineEvent::HistoryMenuNext,
"historymenuprevious" => ReedlineEvent::HistoryMenuPrevious,
"historypagenext" => ReedlineEvent::HistoryPageNext,
"historypageprevious" => ReedlineEvent::HistoryPagePrevious,
// TODO: add ReedlineEvent::Mouse
// TODO: add ReedlineEvent::Resize

View File

@ -119,7 +119,8 @@ pub(crate) fn evaluate(ctrlc: Arc<AtomicBool>, engine_state: &mut EngineState) -
.with_menu_completer(
Box::new(NuCompleter::new(engine_state.clone())),
reedline_config::create_menu_input(&config),
);
)
.with_history_menu(reedline_config::create_history_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.