Tab backwards (#255)

* reduce string print

* menu input struct

* back tab

* spelling correction
This commit is contained in:
Fernando Herrera 2022-01-16 08:25:13 +00:00 committed by GitHub
parent c0fbcf0ed1
commit 32338dc18a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 73 additions and 37 deletions

View File

@ -216,8 +216,6 @@ impl ContextMenu {
/// Calculates how many rows the Menu will use
pub fn get_rows(&self, line_buffer: &LineBuffer) -> u16 {
// TODO. Consider case where the lines may wrap the screen. This happens
// when the working details don't get updated
let rows = self.get_values(line_buffer).len() as f64 / self.working_details.columns as f64;
rows.ceil() as u16
}
@ -255,12 +253,22 @@ impl ContextMenu {
}
}
/// Move menu cursor element
pub fn move_right(&mut self) {
let new_col = self.col_pos + 1;
self.col_pos = if new_col >= self.working_details.columns {
0
} else {
new_col
}
}
/// Move menu cursor to the next element
pub fn move_next(&mut self, line_buffer: &LineBuffer) {
let mut new_col = self.col_pos + 1;
let mut new_row = self.row_pos;
if self.col_pos + 1 >= self.working_details.columns {
if new_col >= self.working_details.columns {
new_row += 1;
new_col = 0;
}
@ -279,13 +287,29 @@ impl ContextMenu {
}
}
/// Move menu cursor element
pub fn move_right(&mut self) {
let new_col = self.col_pos + 1;
self.col_pos = if new_col >= self.working_details.columns {
0
/// Move menu cursor to the previous element
pub fn move_previous(&mut self, line_buffer: &LineBuffer) {
let new_col = self.col_pos.checked_sub(1);
let (new_col, new_row) = match new_col {
Some(col) => (col, self.row_pos),
None => match self.row_pos.checked_sub(1) {
Some(row) => (self.get_cols().saturating_sub(1), row),
None => (
self.get_cols().saturating_sub(1),
self.get_rows(line_buffer).saturating_sub(1),
),
},
};
let position = new_row * self.get_cols() + new_col;
if position >= self.get_values(line_buffer).len() as u16 {
self.col_pos =
(self.get_values(line_buffer).len() as u16 % self.get_cols()).saturating_sub(1);
self.row_pos = self.get_rows(line_buffer).saturating_sub(1);
} else {
new_col
self.col_pos = new_col;
self.row_pos = new_row;
}
}

View File

@ -114,6 +114,7 @@ pub fn default_emacs_keybindings() -> Keybindings {
kb.add_binding(KM::NONE, KC::Backspace, edit_bind(EC::Backspace));
kb.add_binding(KM::NONE, KC::Tab, ReedlineEvent::ContextMenu);
kb.add_binding(KM::SHIFT, KC::BackTab, ReedlineEvent::PreviousElement);
kb.add_binding(KM::NONE, KC::Esc, ReedlineEvent::Esc);
kb

View File

@ -27,8 +27,12 @@ pub fn default_vi_insert_keybindings() -> Keybindings {
kb.add_binding(KM::NONE, KC::Delete, edit_bind(EC::Delete));
kb.add_binding(KM::NONE, KC::End, edit_bind(EC::MoveToLineEnd));
kb.add_binding(KM::NONE, KC::Home, edit_bind(EC::MoveToLineStart));
kb.add_binding(KM::CONTROL, KC::Char('c'), ReedlineEvent::CtrlC);
kb.add_binding(KM::CONTROL, KC::Char('r'), ReedlineEvent::SearchHistory);
kb.add_binding(KM::NONE, KC::Tab, ReedlineEvent::ContextMenu);
kb.add_binding(KM::SHIFT, KC::BackTab, ReedlineEvent::PreviousElement);
kb
}

View File

@ -355,7 +355,7 @@ impl Reedline {
Ok(())
}
/// Helper implemting the logic for [`Reedline::read_line()`] to be wrapped
/// Helper implementing the logic for [`Reedline::read_line()`] to be wrapped
/// in a `raw_mode` context.
fn read_line_helper(&mut self, prompt: &dyn Prompt) -> Result<Signal> {
self.painter.init_terminal_size()?;
@ -518,22 +518,13 @@ impl Reedline {
self.repaint(prompt)?;
Ok(None)
}
ReedlineEvent::Paste(_) => {
// No history search if a paste event is handled
Ok(None)
}
ReedlineEvent::Multiple(_) => {
// VI multiplier operations currently not supported in the history search
Ok(None)
}
ReedlineEvent::None => {
// Default no operation
Ok(None)
}
ReedlineEvent::ContextMenu | ReedlineEvent::Esc => {
// No context menu action when pressing Tab in history mode
Ok(None)
}
ReedlineEvent::ContextMenu
| ReedlineEvent::Paste(_)
| ReedlineEvent::Multiple(_)
| ReedlineEvent::None
| ReedlineEvent::Esc
| ReedlineEvent::NextElement
| ReedlineEvent::PreviousElement => Ok(None),
}
}
@ -551,23 +542,35 @@ impl Reedline {
Ok(None)
} else {
self.context_menu.activate();
self.context_menu
.update_working_details(line_buffer, self.painter.terminal_cols());
// If there is only one value in the menu, it can select be selected immediately
if self.context_menu.get_num_values(line_buffer) == 1 {
self.handle_event(prompt, ReedlineEvent::Enter)
self.handle_editor_event(prompt, ReedlineEvent::Enter)
} else {
self.buffer_paint(prompt)?;
Ok(None)
}
}
}
ReedlineEvent::NextElement => {
if self.context_menu.is_active() {
let line_buffer = self.editor.line_buffer();
self.context_menu.move_next(line_buffer);
self.buffer_paint(prompt)?;
}
Ok(None)
}
ReedlineEvent::PreviousElement => {
if self.context_menu.is_active() {
let line_buffer = self.editor.line_buffer();
self.context_menu.move_previous(line_buffer);
self.buffer_paint(prompt)?;
}
Ok(None)
}
ReedlineEvent::Complete => {
let line_buffer = self.editor.line_buffer();
self.tab_handler.handle(line_buffer);
self.buffer_paint(prompt)?;
Ok(None)
}
@ -631,12 +634,6 @@ impl Reedline {
}
}
ReedlineEvent::Edit(commands) => {
if self.context_menu.is_active() {
let line_buffer = self.editor.line_buffer();
self.context_menu
.update_working_details(line_buffer, self.painter.terminal_cols());
}
self.run_edit_commands(&commands);
self.repaint(prompt)?;
Ok(None)
@ -1021,6 +1018,10 @@ impl Reedline {
let hint = hint.replace("\n", "\r\n");
let context_menu = if self.context_menu.is_active() {
let line_buffer = self.editor.line_buffer();
self.context_menu
.update_working_details(line_buffer, self.painter.terminal_cols());
Some(&self.context_menu)
} else {
None

View File

@ -285,4 +285,10 @@ pub enum ReedlineEvent {
/// In vi mode multiple reedline events can be chained while parsing the
/// command or movement characters
Multiple(Vec<ReedlineEvent>),
/// Next element in the menu
NextElement,
/// Previous element in the menu
PreviousElement,
}