mirror of
https://github.com/nushell/nushell
synced 2024-11-10 23:24:14 +00:00
using menu trait (#861)
This commit is contained in:
parent
04395ee05c
commit
267ff4b0cf
5 changed files with 142 additions and 107 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -2863,7 +2863,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reedline"
|
name = "reedline"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "git+https://github.com/nushell/reedline?branch=main#d7f42e5de4aeee9332dc8eaff07e68923401edcf"
|
source = "git+https://github.com/nushell/reedline?branch=main#c0ec7dc2fd4181c11065f7e19c59fed2ffc83653"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
|
|
|
@ -14,10 +14,8 @@ pub struct NushellPrompt {
|
||||||
right_prompt_string: Option<String>,
|
right_prompt_string: Option<String>,
|
||||||
default_prompt_indicator: String,
|
default_prompt_indicator: String,
|
||||||
default_vi_insert_prompt_indicator: String,
|
default_vi_insert_prompt_indicator: String,
|
||||||
default_vi_visual_prompt_indicator: String,
|
default_vi_normal_prompt_indicator: String,
|
||||||
default_menu_prompt_indicator: String,
|
|
||||||
default_multiline_indicator: String,
|
default_multiline_indicator: String,
|
||||||
default_history_prompt_indicator: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for NushellPrompt {
|
impl Default for NushellPrompt {
|
||||||
|
@ -33,10 +31,8 @@ impl NushellPrompt {
|
||||||
right_prompt_string: None,
|
right_prompt_string: None,
|
||||||
default_prompt_indicator: "〉".to_string(),
|
default_prompt_indicator: "〉".to_string(),
|
||||||
default_vi_insert_prompt_indicator: ": ".to_string(),
|
default_vi_insert_prompt_indicator: ": ".to_string(),
|
||||||
default_vi_visual_prompt_indicator: "v ".to_string(),
|
default_vi_normal_prompt_indicator: "〉".to_string(),
|
||||||
default_menu_prompt_indicator: "| ".to_string(),
|
|
||||||
default_multiline_indicator: "::: ".to_string(),
|
default_multiline_indicator: "::: ".to_string(),
|
||||||
default_history_prompt_indicator: "? ".to_string(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,8 +52,8 @@ impl NushellPrompt {
|
||||||
self.default_vi_insert_prompt_indicator = prompt_vi_insert_string;
|
self.default_vi_insert_prompt_indicator = prompt_vi_insert_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_prompt_vi_visual(&mut self, prompt_vi_visual_string: String) {
|
pub fn update_prompt_vi_normal(&mut self, prompt_vi_normal_string: String) {
|
||||||
self.default_vi_visual_prompt_indicator = prompt_vi_visual_string;
|
self.default_vi_normal_prompt_indicator = prompt_vi_normal_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_prompt_multiline(&mut self, prompt_multiline_indicator_string: String) {
|
pub fn update_prompt_multiline(&mut self, prompt_multiline_indicator_string: String) {
|
||||||
|
@ -71,20 +67,15 @@ impl NushellPrompt {
|
||||||
prompt_indicator_string: String,
|
prompt_indicator_string: String,
|
||||||
prompt_multiline_indicator_string: String,
|
prompt_multiline_indicator_string: String,
|
||||||
prompt_vi: (String, String),
|
prompt_vi: (String, String),
|
||||||
prompt_menus: (String, String),
|
|
||||||
) {
|
) {
|
||||||
let (prompt_vi_insert_string, prompt_vi_visual_string) = prompt_vi;
|
let (prompt_vi_insert_string, prompt_vi_normal_string) = prompt_vi;
|
||||||
let (prompt_indicator_menu, prompt_history_indicator_menu) = prompt_menus;
|
|
||||||
|
|
||||||
self.left_prompt_string = left_prompt_string;
|
self.left_prompt_string = left_prompt_string;
|
||||||
self.right_prompt_string = right_prompt_string;
|
self.right_prompt_string = right_prompt_string;
|
||||||
self.default_prompt_indicator = prompt_indicator_string;
|
self.default_prompt_indicator = prompt_indicator_string;
|
||||||
self.default_vi_insert_prompt_indicator = prompt_vi_insert_string;
|
self.default_vi_insert_prompt_indicator = prompt_vi_insert_string;
|
||||||
self.default_vi_visual_prompt_indicator = prompt_vi_visual_string;
|
self.default_vi_normal_prompt_indicator = prompt_vi_normal_string;
|
||||||
self.default_multiline_indicator = prompt_multiline_indicator_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 {
|
fn default_wrapped_custom_string(&self, str: String) -> String {
|
||||||
|
@ -95,19 +86,27 @@ impl NushellPrompt {
|
||||||
impl Prompt for NushellPrompt {
|
impl Prompt for NushellPrompt {
|
||||||
fn render_prompt_left(&self) -> Cow<str> {
|
fn render_prompt_left(&self) -> Cow<str> {
|
||||||
if let Some(prompt_string) = &self.left_prompt_string {
|
if let Some(prompt_string) = &self.left_prompt_string {
|
||||||
prompt_string.into()
|
prompt_string.replace("\n", "\r\n").into()
|
||||||
} else {
|
} else {
|
||||||
let default = DefaultPrompt::new();
|
let default = DefaultPrompt::new();
|
||||||
default.render_prompt_left().to_string().into()
|
default
|
||||||
|
.render_prompt_left()
|
||||||
|
.to_string()
|
||||||
|
.replace("\n", "\r\n")
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_prompt_right(&self) -> Cow<str> {
|
fn render_prompt_right(&self) -> Cow<str> {
|
||||||
if let Some(prompt_string) = &self.right_prompt_string {
|
if let Some(prompt_string) = &self.right_prompt_string {
|
||||||
prompt_string.into()
|
prompt_string.replace("\n", "\r\n").into()
|
||||||
} else {
|
} else {
|
||||||
let default = DefaultPrompt::new();
|
let default = DefaultPrompt::new();
|
||||||
default.render_prompt_right().to_string().into()
|
default
|
||||||
|
.render_prompt_right()
|
||||||
|
.to_string()
|
||||||
|
.replace("\n", "\r\n")
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,13 +115,10 @@ impl Prompt for NushellPrompt {
|
||||||
PromptEditMode::Default => self.default_prompt_indicator.as_str().into(),
|
PromptEditMode::Default => self.default_prompt_indicator.as_str().into(),
|
||||||
PromptEditMode::Emacs => self.default_prompt_indicator.as_str().into(),
|
PromptEditMode::Emacs => self.default_prompt_indicator.as_str().into(),
|
||||||
PromptEditMode::Vi(vi_mode) => match vi_mode {
|
PromptEditMode::Vi(vi_mode) => match vi_mode {
|
||||||
PromptViMode::Normal => self.default_prompt_indicator.as_str().into(),
|
PromptViMode::Normal => self.default_vi_normal_prompt_indicator.as_str().into(),
|
||||||
PromptViMode::Insert => self.default_vi_insert_prompt_indicator.as_str().into(),
|
PromptViMode::Insert => self.default_vi_insert_prompt_indicator.as_str().into(),
|
||||||
PromptViMode::Visual => self.default_vi_visual_prompt_indicator.as_str().into(),
|
|
||||||
},
|
},
|
||||||
PromptEditMode::Custom(str) => self.default_wrapped_custom_string(str).into(),
|
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(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,16 +12,14 @@ pub(crate) const PROMPT_COMMAND: &str = "PROMPT_COMMAND";
|
||||||
pub(crate) const PROMPT_COMMAND_RIGHT: &str = "PROMPT_COMMAND_RIGHT";
|
pub(crate) const PROMPT_COMMAND_RIGHT: &str = "PROMPT_COMMAND_RIGHT";
|
||||||
pub(crate) const PROMPT_INDICATOR: &str = "PROMPT_INDICATOR";
|
pub(crate) const PROMPT_INDICATOR: &str = "PROMPT_INDICATOR";
|
||||||
pub(crate) const PROMPT_INDICATOR_VI_INSERT: &str = "PROMPT_INDICATOR_VI_INSERT";
|
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_VI_NORMAL: &str = "PROMPT_INDICATOR_VI_NORMAL";
|
||||||
pub(crate) const PROMPT_INDICATOR_MENU: &str = "PROMPT_INDICATOR_MENU";
|
|
||||||
pub(crate) const PROMPT_MULTILINE_INDICATOR: &str = "PROMPT_MULTILINE_INDICATOR";
|
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(
|
pub(crate) fn get_prompt_indicators(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
engine_state: &EngineState,
|
engine_state: &EngineState,
|
||||||
stack: &Stack,
|
stack: &Stack,
|
||||||
) -> (String, String, String, String, String, String) {
|
) -> (String, String, String, String) {
|
||||||
let prompt_indicator = match stack.get_env_var(engine_state, PROMPT_INDICATOR) {
|
let prompt_indicator = match stack.get_env_var(engine_state, PROMPT_INDICATOR) {
|
||||||
Some(pi) => pi.into_string("", config),
|
Some(pi) => pi.into_string("", config),
|
||||||
None => "〉".to_string(),
|
None => "〉".to_string(),
|
||||||
|
@ -32,9 +30,9 @@ pub(crate) fn get_prompt_indicators(
|
||||||
None => ": ".to_string(),
|
None => ": ".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let prompt_vi_visual = match stack.get_env_var(engine_state, PROMPT_INDICATOR_VI_VISUAL) {
|
let prompt_vi_normal = match stack.get_env_var(engine_state, PROMPT_INDICATOR_VI_NORMAL) {
|
||||||
Some(pviv) => pviv.into_string("", config),
|
Some(pviv) => pviv.into_string("", config),
|
||||||
None => "v ".to_string(),
|
None => "〉".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let prompt_multiline = match stack.get_env_var(engine_state, PROMPT_MULTILINE_INDICATOR) {
|
let prompt_multiline = match stack.get_env_var(engine_state, PROMPT_MULTILINE_INDICATOR) {
|
||||||
|
@ -42,23 +40,11 @@ pub(crate) fn get_prompt_indicators(
|
||||||
None => "::: ".to_string(),
|
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_history = match stack.get_env_var(engine_state, PROMPT_INDICATOR_HISTORY) {
|
|
||||||
Some(ph) => ph.into_string("", config),
|
|
||||||
None => "? ".to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
(
|
(
|
||||||
prompt_indicator,
|
prompt_indicator,
|
||||||
prompt_vi_insert,
|
prompt_vi_insert,
|
||||||
prompt_vi_visual,
|
prompt_vi_normal,
|
||||||
prompt_multiline,
|
prompt_multiline,
|
||||||
prompt_menu,
|
|
||||||
prompt_history,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,10 +93,8 @@ pub(crate) fn update_prompt<'prompt>(
|
||||||
let (
|
let (
|
||||||
prompt_indicator_string,
|
prompt_indicator_string,
|
||||||
prompt_vi_insert_string,
|
prompt_vi_insert_string,
|
||||||
prompt_vi_visual_string,
|
prompt_vi_normal_string,
|
||||||
prompt_multiline_string,
|
prompt_multiline_string,
|
||||||
prompt_indicator_menu,
|
|
||||||
prompt_indicator_history,
|
|
||||||
) = get_prompt_indicators(config, engine_state, stack);
|
) = get_prompt_indicators(config, engine_state, stack);
|
||||||
|
|
||||||
let mut stack = stack.clone();
|
let mut stack = stack.clone();
|
||||||
|
@ -121,8 +105,7 @@ pub(crate) fn update_prompt<'prompt>(
|
||||||
get_prompt_string(PROMPT_COMMAND_RIGHT, config, engine_state, &mut stack),
|
get_prompt_string(PROMPT_COMMAND_RIGHT, config, engine_state, &mut stack),
|
||||||
prompt_indicator_string,
|
prompt_indicator_string,
|
||||||
prompt_multiline_string,
|
prompt_multiline_string,
|
||||||
(prompt_vi_insert_string, prompt_vi_visual_string),
|
(prompt_vi_insert_string, prompt_vi_normal_string),
|
||||||
(prompt_indicator_menu, prompt_indicator_history),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
nu_prompt as &dyn Prompt
|
nu_prompt as &dyn Prompt
|
||||||
|
|
|
@ -1,26 +1,34 @@
|
||||||
use crossterm::event::{KeyCode, KeyModifiers};
|
use crossterm::event::{KeyCode, KeyModifiers};
|
||||||
|
use nu_cli::NuCompleter;
|
||||||
use nu_color_config::lookup_ansi_color_style;
|
use nu_color_config::lookup_ansi_color_style;
|
||||||
use nu_protocol::{extract_value, Config, ParsedKeybinding, ShellError, Span, Type, Value};
|
use nu_protocol::{
|
||||||
|
engine::EngineState, extract_value, Config, ParsedKeybinding, ShellError, Span, Type, Value,
|
||||||
|
};
|
||||||
use reedline::{
|
use reedline::{
|
||||||
default_emacs_keybindings, default_vi_insert_keybindings, default_vi_normal_keybindings,
|
default_emacs_keybindings, default_vi_insert_keybindings, default_vi_normal_keybindings,
|
||||||
ContextMenuInput, EditCommand, HistoryMenuInput, Keybindings, ReedlineEvent,
|
ContextMenu, EditCommand, HistoryMenu, Keybindings, Reedline, ReedlineEvent,
|
||||||
};
|
};
|
||||||
|
|
||||||
// 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
|
// stored in the config variable
|
||||||
pub(crate) fn create_menu_input(config: &Config) -> ContextMenuInput {
|
pub(crate) fn add_context_menu(
|
||||||
let mut input = ContextMenuInput::default();
|
line_editor: Reedline,
|
||||||
|
engine_state: &EngineState,
|
||||||
|
config: &Config,
|
||||||
|
) -> Reedline {
|
||||||
|
let mut context_menu = ContextMenu::default();
|
||||||
|
context_menu = context_menu.with_completer(Box::new(NuCompleter::new(engine_state.clone())));
|
||||||
|
|
||||||
input = match config
|
context_menu = match config
|
||||||
.menu_config
|
.menu_config
|
||||||
.get("columns")
|
.get("columns")
|
||||||
.and_then(|value| value.as_integer().ok())
|
.and_then(|value| value.as_integer().ok())
|
||||||
{
|
{
|
||||||
Some(value) => input.with_columns(value as u16),
|
Some(value) => context_menu.with_columns(value as u16),
|
||||||
None => input,
|
None => context_menu,
|
||||||
};
|
};
|
||||||
|
|
||||||
input = input.with_col_width(
|
context_menu = context_menu.with_column_width(
|
||||||
config
|
config
|
||||||
.menu_config
|
.menu_config
|
||||||
.get("col_width")
|
.get("col_width")
|
||||||
|
@ -28,82 +36,133 @@ pub(crate) fn create_menu_input(config: &Config) -> ContextMenuInput {
|
||||||
.map(|value| value as usize),
|
.map(|value| value as usize),
|
||||||
);
|
);
|
||||||
|
|
||||||
input = match config
|
context_menu = match config
|
||||||
.menu_config
|
.menu_config
|
||||||
.get("col_padding")
|
.get("col_padding")
|
||||||
.and_then(|value| value.as_integer().ok())
|
.and_then(|value| value.as_integer().ok())
|
||||||
{
|
{
|
||||||
Some(value) => input.with_col_padding(value as usize),
|
Some(value) => context_menu.with_column_padding(value as usize),
|
||||||
None => input,
|
None => context_menu,
|
||||||
};
|
};
|
||||||
|
|
||||||
input = match config
|
context_menu = match config
|
||||||
.menu_config
|
.menu_config
|
||||||
.get("text_style")
|
.get("text_style")
|
||||||
.and_then(|value| value.as_string().ok())
|
.and_then(|value| value.as_string().ok())
|
||||||
{
|
{
|
||||||
Some(value) => input.with_text_style(lookup_ansi_color_style(&value)),
|
Some(value) => context_menu.with_text_style(lookup_ansi_color_style(&value)),
|
||||||
None => input,
|
None => context_menu,
|
||||||
};
|
};
|
||||||
|
|
||||||
input = match config
|
context_menu = match config
|
||||||
.menu_config
|
.menu_config
|
||||||
.get("selected_text_style")
|
.get("selected_text_style")
|
||||||
.and_then(|value| value.as_string().ok())
|
.and_then(|value| value.as_string().ok())
|
||||||
{
|
{
|
||||||
Some(value) => input.with_selected_text_style(lookup_ansi_color_style(&value)),
|
Some(value) => context_menu.with_selected_text_style(lookup_ansi_color_style(&value)),
|
||||||
None => input,
|
None => context_menu,
|
||||||
};
|
};
|
||||||
|
|
||||||
input
|
context_menu = match config
|
||||||
|
.menu_config
|
||||||
|
.get("marker")
|
||||||
|
.and_then(|value| value.as_string().ok())
|
||||||
|
{
|
||||||
|
Some(value) => context_menu.with_marker(value),
|
||||||
|
None => context_menu,
|
||||||
|
};
|
||||||
|
|
||||||
|
line_editor.with_menu(Box::new(context_menu))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates an input object for the history menu based on the dictionary
|
// Creates an input object for the history menu based on the dictionary
|
||||||
// stored in the config variable
|
// stored in the config variable
|
||||||
pub(crate) fn create_history_input(config: &Config) -> HistoryMenuInput {
|
pub(crate) fn add_history_menu(line_editor: Reedline, config: &Config) -> Reedline {
|
||||||
let mut input = HistoryMenuInput::default();
|
let mut history_menu = HistoryMenu::default();
|
||||||
|
|
||||||
input = match config
|
history_menu = match config
|
||||||
.history_config
|
.history_config
|
||||||
.get("page_size")
|
.get("page_size")
|
||||||
.and_then(|value| value.as_integer().ok())
|
.and_then(|value| value.as_integer().ok())
|
||||||
{
|
{
|
||||||
Some(value) => input.with_page_size(value as usize),
|
Some(value) => history_menu.with_page_size(value as usize),
|
||||||
None => input,
|
None => history_menu,
|
||||||
};
|
};
|
||||||
|
|
||||||
input = match config
|
history_menu = match config
|
||||||
.history_config
|
.history_config
|
||||||
.get("selector")
|
.get("selector")
|
||||||
.and_then(|value| value.as_string().ok())
|
.and_then(|value| value.as_string().ok())
|
||||||
{
|
{
|
||||||
Some(value) => {
|
Some(value) => {
|
||||||
let char = value.chars().next().unwrap_or(':');
|
let char = value.chars().next().unwrap_or(':');
|
||||||
input.with_row_char(char)
|
history_menu.with_row_char(char)
|
||||||
}
|
}
|
||||||
None => input,
|
None => history_menu,
|
||||||
};
|
};
|
||||||
|
|
||||||
input = match config
|
history_menu = match config
|
||||||
.history_config
|
.history_config
|
||||||
.get("text_style")
|
.get("text_style")
|
||||||
.and_then(|value| value.as_string().ok())
|
.and_then(|value| value.as_string().ok())
|
||||||
{
|
{
|
||||||
Some(value) => input.with_text_style(lookup_ansi_color_style(&value)),
|
Some(value) => history_menu.with_text_style(lookup_ansi_color_style(&value)),
|
||||||
None => input,
|
None => history_menu,
|
||||||
};
|
};
|
||||||
|
|
||||||
input = match config
|
history_menu = match config
|
||||||
.history_config
|
.history_config
|
||||||
.get("selected_text_style")
|
.get("selected_text_style")
|
||||||
.and_then(|value| value.as_string().ok())
|
.and_then(|value| value.as_string().ok())
|
||||||
{
|
{
|
||||||
Some(value) => input.with_selected_text_style(lookup_ansi_color_style(&value)),
|
Some(value) => history_menu.with_selected_text_style(lookup_ansi_color_style(&value)),
|
||||||
None => input,
|
None => history_menu,
|
||||||
};
|
};
|
||||||
|
|
||||||
input
|
history_menu = match config
|
||||||
|
.history_config
|
||||||
|
.get("marker")
|
||||||
|
.and_then(|value| value.as_string().ok())
|
||||||
|
{
|
||||||
|
Some(value) => history_menu.with_marker(value),
|
||||||
|
None => history_menu,
|
||||||
|
};
|
||||||
|
|
||||||
|
line_editor.with_menu(Box::new(history_menu))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_menu_keybindings(keybindings: &mut Keybindings) {
|
||||||
|
keybindings.add_binding(
|
||||||
|
KeyModifiers::CONTROL,
|
||||||
|
KeyCode::Char('i'),
|
||||||
|
ReedlineEvent::UntilFound(vec![
|
||||||
|
ReedlineEvent::Menu("history_menu".to_string()),
|
||||||
|
ReedlineEvent::MenuPageNext,
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
keybindings.add_binding(
|
||||||
|
KeyModifiers::CONTROL | KeyModifiers::SHIFT,
|
||||||
|
KeyCode::Char('i'),
|
||||||
|
ReedlineEvent::MenuPagePrevious,
|
||||||
|
);
|
||||||
|
|
||||||
|
keybindings.add_binding(
|
||||||
|
KeyModifiers::NONE,
|
||||||
|
KeyCode::Tab,
|
||||||
|
ReedlineEvent::UntilFound(vec![
|
||||||
|
ReedlineEvent::Menu("context_menu".to_string()),
|
||||||
|
ReedlineEvent::MenuNext,
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
keybindings.add_binding(
|
||||||
|
KeyModifiers::SHIFT,
|
||||||
|
KeyCode::BackTab,
|
||||||
|
ReedlineEvent::MenuPrevious,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
pub enum KeybindingsMode {
|
pub enum KeybindingsMode {
|
||||||
Emacs(Keybindings),
|
Emacs(Keybindings),
|
||||||
Vi {
|
Vi {
|
||||||
|
@ -117,6 +176,8 @@ pub(crate) fn create_keybindings(config: &Config) -> Result<KeybindingsMode, She
|
||||||
match config.edit_mode.as_str() {
|
match config.edit_mode.as_str() {
|
||||||
"emacs" => {
|
"emacs" => {
|
||||||
let mut keybindings = default_emacs_keybindings();
|
let mut keybindings = default_emacs_keybindings();
|
||||||
|
add_menu_keybindings(&mut keybindings);
|
||||||
|
|
||||||
// temporal keybinding with multiple events
|
// temporal keybinding with multiple events
|
||||||
keybindings.add_binding(
|
keybindings.add_binding(
|
||||||
KeyModifiers::SHIFT,
|
KeyModifiers::SHIFT,
|
||||||
|
@ -139,6 +200,9 @@ pub(crate) fn create_keybindings(config: &Config) -> Result<KeybindingsMode, She
|
||||||
let mut insert_keybindings = default_vi_insert_keybindings();
|
let mut insert_keybindings = default_vi_insert_keybindings();
|
||||||
let mut normal_keybindings = default_vi_normal_keybindings();
|
let mut normal_keybindings = default_vi_normal_keybindings();
|
||||||
|
|
||||||
|
add_menu_keybindings(&mut insert_keybindings);
|
||||||
|
add_menu_keybindings(&mut normal_keybindings);
|
||||||
|
|
||||||
for parsed_keybinding in parsed_keybindings {
|
for parsed_keybinding in parsed_keybindings {
|
||||||
if parsed_keybinding.mode.into_string("", config).as_str() == "vi_insert" {
|
if parsed_keybinding.mode.into_string("", config).as_str() == "vi_insert" {
|
||||||
add_keybinding(&mut insert_keybindings, parsed_keybinding, config)?
|
add_keybinding(&mut insert_keybindings, parsed_keybinding, config)?
|
||||||
|
@ -254,28 +318,27 @@ fn parse_event(value: Value, config: &Config) -> Result<ReedlineEvent, ShellErro
|
||||||
"nexthistory" => ReedlineEvent::NextHistory,
|
"nexthistory" => ReedlineEvent::NextHistory,
|
||||||
"previoushistory" => ReedlineEvent::PreviousHistory,
|
"previoushistory" => ReedlineEvent::PreviousHistory,
|
||||||
"repaint" => ReedlineEvent::Repaint,
|
"repaint" => ReedlineEvent::Repaint,
|
||||||
"contextmenu" => ReedlineEvent::ContextMenu,
|
|
||||||
"menudown" => ReedlineEvent::MenuDown,
|
"menudown" => ReedlineEvent::MenuDown,
|
||||||
"menuup" => ReedlineEvent::MenuUp,
|
"menuup" => ReedlineEvent::MenuUp,
|
||||||
"menuleft" => ReedlineEvent::MenuLeft,
|
"menuleft" => ReedlineEvent::MenuLeft,
|
||||||
"menuright" => ReedlineEvent::MenuRight,
|
"menuright" => ReedlineEvent::MenuRight,
|
||||||
"menunext" => ReedlineEvent::MenuNext,
|
"menunext" => ReedlineEvent::MenuNext,
|
||||||
"menuprevious" => ReedlineEvent::MenuPrevious,
|
"menuprevious" => ReedlineEvent::MenuPrevious,
|
||||||
"historymenu" => ReedlineEvent::HistoryMenu,
|
"menupagenext" => ReedlineEvent::MenuPageNext,
|
||||||
"historymenunext" => ReedlineEvent::HistoryMenuNext,
|
"menupageprevious" => ReedlineEvent::MenuPagePrevious,
|
||||||
"historymenuprevious" => ReedlineEvent::HistoryMenuPrevious,
|
"menu" => {
|
||||||
"historypagenext" => ReedlineEvent::HistoryPageNext,
|
let menu = extract_value("name", &cols, &vals, &span)?;
|
||||||
"historypageprevious" => ReedlineEvent::HistoryPagePrevious,
|
ReedlineEvent::Menu(menu.into_string("", config))
|
||||||
|
}
|
||||||
// TODO: add ReedlineEvent::Mouse
|
|
||||||
// TODO: add ReedlineEvent::Resize
|
|
||||||
// TODO: add ReedlineEvent::Paste
|
|
||||||
"edit" => {
|
"edit" => {
|
||||||
let edit = extract_value("edit", &cols, &vals, &span)?;
|
let edit = extract_value("edit", &cols, &vals, &span)?;
|
||||||
let edit = parse_edit(edit, config)?;
|
let edit = parse_edit(edit, config)?;
|
||||||
|
|
||||||
ReedlineEvent::Edit(vec![edit])
|
ReedlineEvent::Edit(vec![edit])
|
||||||
}
|
}
|
||||||
|
// TODO: add ReedlineEvent::Mouse
|
||||||
|
// TODO: add ReedlineEvent::Resize
|
||||||
|
// TODO: add ReedlineEvent::Paste
|
||||||
v => {
|
v => {
|
||||||
return Err(ShellError::UnsupportedConfigValue(
|
return Err(ShellError::UnsupportedConfigValue(
|
||||||
"Reedline event".to_string(),
|
"Reedline event".to_string(),
|
||||||
|
|
25
src/repl.rs
25
src/repl.rs
|
@ -1,5 +1,6 @@
|
||||||
use std::{sync::atomic::Ordering, time::Instant};
|
use std::{sync::atomic::Ordering, time::Instant};
|
||||||
|
|
||||||
|
use crate::reedline_config::{add_context_menu, add_history_menu};
|
||||||
use crate::{config_files, prompt_update, reedline_config};
|
use crate::{config_files, prompt_update, reedline_config};
|
||||||
use crate::{
|
use crate::{
|
||||||
reedline_config::KeybindingsMode,
|
reedline_config::KeybindingsMode,
|
||||||
|
@ -7,7 +8,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use miette::{IntoDiagnostic, Result};
|
use miette::{IntoDiagnostic, Result};
|
||||||
use nu_cli::{NuCompleter, NuHighlighter, NuValidator, NushellPrompt};
|
use nu_cli::{NuHighlighter, NuValidator, NushellPrompt};
|
||||||
use nu_color_config::get_color_config;
|
use nu_color_config::get_color_config;
|
||||||
use nu_engine::convert_env_values;
|
use nu_engine::convert_env_values;
|
||||||
use nu_parser::lex;
|
use nu_parser::lex;
|
||||||
|
@ -95,14 +96,8 @@ pub(crate) fn evaluate(engine_state: &mut EngineState) -> Result<()> {
|
||||||
ctrlc.store(false, Ordering::SeqCst);
|
ctrlc.store(false, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
|
|
||||||
let line_editor = Reedline::create()
|
let mut line_editor = Reedline::create()
|
||||||
.into_diagnostic()?
|
.into_diagnostic()?
|
||||||
// .with_completion_action_handler(Box::new(fuzzy_completion::FuzzyCompletion {
|
|
||||||
// completer: Box::new(NuCompleter::new(engine_state.clone())),
|
|
||||||
// }))
|
|
||||||
// .with_completion_action_handler(Box::new(
|
|
||||||
// ListCompletionHandler::default().with_completer(Box::new(completer)),
|
|
||||||
// ))
|
|
||||||
.with_highlighter(Box::new(NuHighlighter {
|
.with_highlighter(Box::new(NuHighlighter {
|
||||||
engine_state: engine_state.clone(),
|
engine_state: engine_state.clone(),
|
||||||
config: config.clone(),
|
config: config.clone(),
|
||||||
|
@ -111,19 +106,17 @@ pub(crate) fn evaluate(engine_state: &mut EngineState) -> Result<()> {
|
||||||
.with_validator(Box::new(NuValidator {
|
.with_validator(Box::new(NuValidator {
|
||||||
engine_state: engine_state.clone(),
|
engine_state: engine_state.clone(),
|
||||||
}))
|
}))
|
||||||
.with_ansi_colors(config.use_ansi_coloring)
|
.with_ansi_colors(config.use_ansi_coloring);
|
||||||
.with_menu_completer(
|
|
||||||
Box::new(NuCompleter::new(engine_state.clone())),
|
line_editor = add_context_menu(line_editor, engine_state, &config);
|
||||||
reedline_config::create_menu_input(&config),
|
line_editor = add_history_menu(line_editor, &config);
|
||||||
)
|
|
||||||
.with_history_menu(reedline_config::create_history_input(&config));
|
|
||||||
|
|
||||||
//FIXME: if config.use_ansi_coloring is false then we should
|
//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.
|
// turn off the hinter but I don't see any way to do that yet.
|
||||||
|
|
||||||
let color_hm = get_color_config(&config);
|
let color_hm = get_color_config(&config);
|
||||||
|
|
||||||
let line_editor = if let Some(history_path) = history_path.clone() {
|
line_editor = if let Some(history_path) = history_path.clone() {
|
||||||
let history = std::fs::read_to_string(&history_path);
|
let history = std::fs::read_to_string(&history_path);
|
||||||
if history.is_ok() {
|
if history.is_ok() {
|
||||||
line_editor
|
line_editor
|
||||||
|
@ -146,7 +139,7 @@ pub(crate) fn evaluate(engine_state: &mut EngineState) -> Result<()> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Changing the line editor based on the found keybindings
|
// Changing the line editor based on the found keybindings
|
||||||
let mut line_editor = match reedline_config::create_keybindings(&config) {
|
line_editor = match reedline_config::create_keybindings(&config) {
|
||||||
Ok(keybindings) => match keybindings {
|
Ok(keybindings) => match keybindings {
|
||||||
KeybindingsMode::Emacs(keybindings) => {
|
KeybindingsMode::Emacs(keybindings) => {
|
||||||
let edit_mode = Box::new(Emacs::new(keybindings));
|
let edit_mode = Box::new(Emacs::new(keybindings));
|
||||||
|
|
Loading…
Reference in a new issue