mirror of
https://github.com/nushell/reedline.git
synced 2024-11-09 13:09:10 +03:00
Tab backwards (#255)
* reduce string print * menu input struct * back tab * spelling correction
This commit is contained in:
parent
c0fbcf0ed1
commit
32338dc18a
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user