mirror of
https://github.com/nushell/reedline.git
synced 2024-08-17 11:50:42 +03:00
Add Submit
and SubmitOrNewline
editor events (#490)
* `Submit` is used to return data unconditionally. This is useful for example if you want compiler to show you where the unclosed paren that doesn't pass validation actually is. * `SubmitOrNewline` is similar to `Enter` but inserts a new line if the cursor is not at the end of the buffer. It's useful to insert newlines in the middle of the text when editing. This also removes unconditional `KeyCode::Enter` to `ReedlineEvent::Enter` event mapping and sets it in the keybindings normally (so you can rebind to `Submit` or `SubmitOrNewline`)
This commit is contained in:
parent
835d2e9f25
commit
f949f560f7
@ -22,6 +22,9 @@ pub fn default_emacs_keybindings() -> Keybindings {
|
||||
add_common_navigation_bindings(&mut kb);
|
||||
add_common_edit_bindings(&mut kb);
|
||||
|
||||
// This could be in common, but in Vi it also changes the mode
|
||||
kb.add_binding(KM::NONE, KC::Enter, ReedlineEvent::Enter);
|
||||
|
||||
// *** CTRL ***
|
||||
// Moves
|
||||
kb.add_binding(
|
||||
@ -141,7 +144,6 @@ impl EditMode for Emacs {
|
||||
.unwrap_or(ReedlineEvent::None)
|
||||
}
|
||||
}
|
||||
(KeyModifiers::NONE, KeyCode::Enter) => ReedlineEvent::Enter,
|
||||
_ => self
|
||||
.keybindings
|
||||
.find_binding(modifiers, code)
|
||||
|
@ -629,7 +629,10 @@ impl Reedline {
|
||||
self.painter.clear_scrollback()?;
|
||||
Ok(EventStatus::Handled)
|
||||
}
|
||||
ReedlineEvent::Enter | ReedlineEvent::HistoryHintComplete => {
|
||||
ReedlineEvent::Enter
|
||||
| ReedlineEvent::HistoryHintComplete
|
||||
| ReedlineEvent::Submit
|
||||
| ReedlineEvent::SubmitOrNewline => {
|
||||
if let Some(string) = self.history_cursor.string_at_cursor() {
|
||||
self.editor
|
||||
.set_buffer(string, UndoBehavior::CreateUndoPoint);
|
||||
@ -848,7 +851,9 @@ impl Reedline {
|
||||
self.painter.clear_scrollback()?;
|
||||
Ok(EventStatus::Handled)
|
||||
}
|
||||
ReedlineEvent::Enter => {
|
||||
ReedlineEvent::Enter | ReedlineEvent::Submit | ReedlineEvent::SubmitOrNewline
|
||||
if self.menus.iter().any(|menu| menu.is_active()) =>
|
||||
{
|
||||
for menu in self.menus.iter_mut() {
|
||||
if menu.is_active() {
|
||||
menu.replace_in_buffer(&mut self.editor);
|
||||
@ -857,7 +862,9 @@ impl Reedline {
|
||||
return Ok(EventStatus::Handled);
|
||||
}
|
||||
}
|
||||
|
||||
unreachable!()
|
||||
}
|
||||
ReedlineEvent::Enter => {
|
||||
#[cfg(feature = "bashisms")]
|
||||
if let Some(event) = self.parse_bang_command() {
|
||||
return self.handle_editor_event(prompt, event);
|
||||
@ -865,22 +872,34 @@ impl Reedline {
|
||||
|
||||
let buffer = self.editor.get_buffer().to_string();
|
||||
match self.validator.as_mut().map(|v| v.validate(&buffer)) {
|
||||
None | Some(ValidationResult::Complete) => {
|
||||
self.hide_hints = true;
|
||||
// Additional repaint to show the content without hints etc.
|
||||
self.repaint(prompt)?;
|
||||
let buf = self.editor.get_buffer();
|
||||
if !buf.is_empty() {
|
||||
let mut entry = HistoryItem::from_command_line(buf);
|
||||
entry.session_id = self.history_session_id;
|
||||
let entry = self.history.save(entry).expect("todo: error handling");
|
||||
self.history_last_run_id = entry.id;
|
||||
}
|
||||
self.run_edit_commands(&[EditCommand::Clear]);
|
||||
self.editor.reset_undo_stack();
|
||||
None | Some(ValidationResult::Complete) => Ok(self.submit_buffer(prompt)?),
|
||||
Some(ValidationResult::Incomplete) => {
|
||||
self.run_edit_commands(&[EditCommand::InsertNewline]);
|
||||
|
||||
Ok(EventStatus::Exits(Signal::Success(buffer)))
|
||||
Ok(EventStatus::Handled)
|
||||
}
|
||||
}
|
||||
}
|
||||
ReedlineEvent::Submit => {
|
||||
#[cfg(feature = "bashisms")]
|
||||
if let Some(event) = self.parse_bang_command() {
|
||||
return self.handle_editor_event(prompt, event);
|
||||
}
|
||||
Ok(self.submit_buffer(prompt)?)
|
||||
}
|
||||
ReedlineEvent::SubmitOrNewline => {
|
||||
#[cfg(feature = "bashisms")]
|
||||
if let Some(event) = self.parse_bang_command() {
|
||||
return self.handle_editor_event(prompt, event);
|
||||
}
|
||||
let cursor_position_in_buffer = self.editor.insertion_point();
|
||||
let buffer = self.editor.get_buffer().to_string();
|
||||
if cursor_position_in_buffer < buffer.len() {
|
||||
self.run_edit_commands(&[EditCommand::InsertNewline]);
|
||||
return Ok(EventStatus::Handled);
|
||||
}
|
||||
match self.validator.as_mut().map(|v| v.validate(&buffer)) {
|
||||
None | Some(ValidationResult::Complete) => Ok(self.submit_buffer(prompt)?),
|
||||
Some(ValidationResult::Incomplete) => {
|
||||
self.run_edit_commands(&[EditCommand::InsertNewline]);
|
||||
|
||||
@ -1449,6 +1468,23 @@ impl Reedline {
|
||||
}
|
||||
Ok(messages)
|
||||
}
|
||||
|
||||
fn submit_buffer(&mut self, prompt: &dyn Prompt) -> io::Result<EventStatus> {
|
||||
let buffer = self.editor.get_buffer().to_string();
|
||||
self.hide_hints = true;
|
||||
// Additional repaint to show the content without hints etc.
|
||||
self.repaint(prompt)?;
|
||||
if !buffer.is_empty() {
|
||||
let mut entry = HistoryItem::from_command_line(&buffer);
|
||||
entry.session_id = self.history_session_id;
|
||||
let entry = self.history.save(entry).expect("todo: error handling");
|
||||
self.history_last_run_id = entry.id;
|
||||
}
|
||||
self.run_edit_commands(&[EditCommand::Clear]);
|
||||
self.editor.reset_undo_stack();
|
||||
|
||||
Ok(EventStatus::Exits(Signal::Success(buffer)))
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -422,6 +422,12 @@ pub enum ReedlineEvent {
|
||||
/// Handle enter event
|
||||
Enter,
|
||||
|
||||
/// Handle unconditional submit event
|
||||
Submit,
|
||||
|
||||
/// Submit at the end of the *complete* text, otherwise newline
|
||||
SubmitOrNewline,
|
||||
|
||||
/// Esc event
|
||||
Esc,
|
||||
|
||||
@ -510,6 +516,8 @@ impl Display for ReedlineEvent {
|
||||
ReedlineEvent::ClearScreen => write!(f, "ClearScreen"),
|
||||
ReedlineEvent::ClearScrollback => write!(f, "ClearScrollback"),
|
||||
ReedlineEvent::Enter => write!(f, "Enter"),
|
||||
ReedlineEvent::Submit => write!(f, "Submit"),
|
||||
ReedlineEvent::SubmitOrNewline => write!(f, "SubmitOrNewline"),
|
||||
ReedlineEvent::Esc => write!(f, "Esc"),
|
||||
ReedlineEvent::Mouse => write!(f, "Mouse"),
|
||||
ReedlineEvent::Resize(_, _) => write!(f, "Resize <int> <int>"),
|
||||
|
Loading…
Reference in New Issue
Block a user