Extending PromptMode (#74)

* Revamp Prompt states

The idea here is that what we want to display on the screen which can
impact the prompt should be available as part of the prompt's interface.

So here are the things that can impact what we show with our prompt
- The line-editor can either be in Emacs mode or VI mode (for now)
  [These are exclusive to one another]
- The line-editor can be either in editing a command or searching
  history mode [These two states are also exclusive]
- Lastly the command can be either single-line or multi-line.

Now all these variables can happen togeter (i.e. they for a cross
prodcut)
- example 1: You can be in vi-normal mode and be editing history search
  term and that particular term earlier resulted in a multi-line
  command. (So, we need to showcase all these three variations together)

one way to do this is using a struct. I found that it was making the
more frequent case (of being in edit mode) overly complex so I chose to
expose the functionality as separate methonds.

* Cleanup custom strings from engine
This commit is contained in:
Sherub Thakur 2021-06-25 23:22:56 +05:30 committed by GitHub
parent 1ad2fcc46a
commit ca445820ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 82 additions and 22 deletions

View File

@ -2,7 +2,7 @@ use crate::{
clip_buffer::{get_default_clipboard, Clipboard}, clip_buffer::{get_default_clipboard, Clipboard},
default_emacs_keybindings, default_emacs_keybindings,
keybindings::{default_vi_insert_keybindings, default_vi_normal_keybindings, Keybindings}, keybindings::{default_vi_insert_keybindings, default_vi_normal_keybindings, Keybindings},
prompt::PromptMode, prompt::{PromptEditMode, PromptHistorySearch, PromptHistorySearchStatus, PromptViMode},
DefaultPrompt, Prompt, DefaultPrompt, Prompt,
}; };
use crate::{history::History, line_buffer::LineBuffer}; use crate::{history::History, line_buffer::LineBuffer};
@ -147,10 +147,11 @@ impl Reedline {
self.edit_mode self.edit_mode
} }
pub fn prompt_mode(&self) -> PromptMode { pub fn prompt_edit_mode(&self) -> PromptEditMode {
match self.edit_mode { match self.edit_mode {
EditMode::ViInsert => PromptMode::ViInsert, EditMode::ViInsert => PromptEditMode::Vi(PromptViMode::Insert),
_ => PromptMode::Normal, EditMode::ViNormal => PromptEditMode::Vi(PromptViMode::Normal),
EditMode::Emacs => PromptEditMode::Emacs,
} }
} }
@ -636,7 +637,7 @@ impl Reedline {
/// Used at the beginning of each [`Reedline::read_line()`] call. /// Used at the beginning of each [`Reedline::read_line()`] call.
fn queue_prompt(&mut self, screen_width: usize) -> Result<()> { fn queue_prompt(&mut self, screen_width: usize) -> Result<()> {
// print our prompt // print our prompt
let prompt_mode = self.prompt_mode(); let prompt_mode = self.prompt_edit_mode();
self.stdout self.stdout
.queue(MoveToColumn(0))? .queue(MoveToColumn(0))?
@ -654,7 +655,7 @@ impl Reedline {
/// the prompt /// the prompt
fn queue_prompt_indicator(&mut self) -> Result<()> { fn queue_prompt_indicator(&mut self) -> Result<()> {
// print our prompt // print our prompt
let prompt_mode = self.prompt_mode(); let prompt_mode = self.prompt_edit_mode();
self.stdout self.stdout
.queue(MoveToColumn(0))? .queue(MoveToColumn(0))?
.queue(SetForegroundColor(self.prompt.get_prompt_color()))? .queue(SetForegroundColor(self.prompt.get_prompt_color()))?
@ -724,19 +725,21 @@ impl Reedline {
.expect("couldn't get history_search reference"); .expect("couldn't get history_search reference");
let status = if search.result.is_none() && !search.search_string.is_empty() { let status = if search.result.is_none() && !search.search_string.is_empty() {
"failed " PromptHistorySearchStatus::Failing
} else { } else {
"" PromptHistorySearchStatus::Passing
}; };
let prompt_history_search = PromptHistorySearch::new(status, search.search_string.clone());
let history_indicator = self
.prompt
.render_prompt_history_search_indicator(prompt_history_search);
// print search prompt // print search prompt
self.stdout self.stdout
.queue(MoveToColumn(0))? .queue(MoveToColumn(0))?
.queue(SetForegroundColor(Color::Blue))? .queue(SetForegroundColor(Color::Blue))?
.queue(Print(format!( .queue(Print(history_indicator))?
"({}reverse-search)`{}':",
status, search.search_string
)))?
.queue(ResetColor)?; .queue(ResetColor)?;
match search.result { match search.result {

View File

@ -5,13 +5,39 @@ use std::env;
pub static DEFAULT_PROMPT_COLOR: Color = Color::Blue; pub static DEFAULT_PROMPT_COLOR: Color = Color::Blue;
pub static DEFAULT_PROMPT_INDICATOR: &str = ""; pub static DEFAULT_PROMPT_INDICATOR: &str = "";
pub static DEFAULT_VI_INSERT_PROMPT_INDICATOR: &str = ": "; pub static DEFAULT_VI_INSERT_PROMPT_INDICATOR: &str = ": ";
pub static DEFAULT_VI_VISUAL_PROMPT_INDICATOR: &str = "v ";
pub static DEFAULT_MULTILINE_INDICATOR: &str = "::: "; pub static DEFAULT_MULTILINE_INDICATOR: &str = "::: ";
/// The type of prompt indicator to display pub enum PromptHistorySearchStatus {
pub enum PromptMode { Passing,
Failing,
}
pub struct PromptHistorySearch {
status: PromptHistorySearchStatus,
term: String,
}
impl PromptHistorySearch {
pub fn new(status: PromptHistorySearchStatus, search_term: String) -> Self {
PromptHistorySearch {
status,
term: search_term,
}
}
}
pub enum PromptEditMode {
Default,
Emacs,
Vi(PromptViMode),
Custom(String),
}
pub enum PromptViMode {
Normal, Normal,
ViInsert, Insert,
Multiline, Visual,
} }
/// API to provide a custom prompt. /// API to provide a custom prompt.
@ -22,7 +48,12 @@ pub trait Prompt {
/// Provide content off the full prompt. May use a line above the entry buffer that fits into `screen_width`. /// Provide content off the full prompt. May use a line above the entry buffer that fits into `screen_width`.
fn render_prompt(&self, screen_width: usize) -> String; fn render_prompt(&self, screen_width: usize) -> String;
/// Render the default prompt indicator /// Render the default prompt indicator
fn render_prompt_indicator(&self, prompt_mode: PromptMode) -> String; fn render_prompt_indicator(&self, prompt_mode: PromptEditMode) -> String;
/// Render the default prompt indicator
fn render_prompt_multiline_indicator(&self) -> String;
/// Render the default prompt indicator
fn render_prompt_history_search_indicator(&self, history_search: PromptHistorySearch)
-> String;
/// Render the vi insert mode prompt indicator /// Render the vi insert mode prompt indicator
/// Get back the prompt color /// Get back the prompt color
fn get_prompt_color(&self) -> Color { fn get_prompt_color(&self) -> Color {
@ -35,13 +66,35 @@ impl Prompt for DefaultPrompt {
DefaultPrompt::render_prompt(self, screen_width) DefaultPrompt::render_prompt(self, screen_width)
} }
fn render_prompt_indicator(&self, prompt_mode: PromptMode) -> String { fn render_prompt_indicator(&self, edit_mode: PromptEditMode) -> String {
match prompt_mode { match edit_mode {
PromptMode::Normal => DEFAULT_PROMPT_INDICATOR.into(), PromptEditMode::Default => DEFAULT_PROMPT_INDICATOR.into(),
PromptMode::ViInsert => DEFAULT_VI_INSERT_PROMPT_INDICATOR.into(), PromptEditMode::Emacs => DEFAULT_PROMPT_INDICATOR.into(),
PromptMode::Multiline => DEFAULT_MULTILINE_INDICATOR.into(), PromptEditMode::Vi(vi_mode) => match vi_mode {
PromptViMode::Normal => DEFAULT_PROMPT_INDICATOR.into(),
PromptViMode::Insert => DEFAULT_VI_INSERT_PROMPT_INDICATOR.into(),
PromptViMode::Visual => DEFAULT_VI_VISUAL_PROMPT_INDICATOR.into(),
},
PromptEditMode::Custom(str) => self.default_wrapped_custom_string(str),
} }
} }
fn render_prompt_multiline_indicator(&self) -> String {
DEFAULT_MULTILINE_INDICATOR.into()
}
fn render_prompt_history_search_indicator(
&self,
history_search: PromptHistorySearch,
) -> String {
let prefix = match history_search.status {
PromptHistorySearchStatus::Passing => "",
PromptHistorySearchStatus::Failing => "failing ",
};
// NOTE: magic strings, givent there is logic on how these compose I am not sure if it
// is worth extracting in to static constant
format!("({}reverse-search: {})", prefix, history_search.term)
}
} }
impl Default for DefaultPrompt { impl Default for DefaultPrompt {
@ -90,6 +143,10 @@ impl DefaultPrompt {
prompt_str prompt_str
} }
fn default_wrapped_custom_string(&self, str: String) -> String {
format!("({})", str)
}
} }
fn get_working_dir() -> Result<String, std::io::Error> { fn get_working_dir() -> Result<String, std::io::Error> {