Skip to content

Commit

Permalink
Misc (#538)
Browse files Browse the repository at this point in the history
* \0 is Ctrl-@ not Ctrl-space
* Fix Ctrl-d in emacs mode
* Bind Ctrl-] to character-search in emacs mode
And Ctrl-Alt-] to character-search-backward
* Bind Ctrl-X backspace to backward-kill-line in emacs mode
  • Loading branch information
gwenn authored Jun 20, 2021
1 parent 059ce10 commit 8725a40
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 117 deletions.
22 changes: 9 additions & 13 deletions src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,15 @@ pub fn execute<H: Helper>(
s.edit_overwrite_char(c)?;
}
Cmd::EndOfFile => {
if input_state.is_emacs_mode() && !s.line.is_empty() {
s.edit_delete(1)?
} else {
if s.has_hint() || !s.is_default_prompt() {
// Force a refresh without hints to leave the previous
// line as the user typed it after a newline.
s.refresh_line_with_msg(None)?;
}
if s.line.is_empty() {
return Err(error::ReadlineError::Eof);
} else if !input_state.is_emacs_mode() {
return Ok(Submit);
}
if s.has_hint() || !s.is_default_prompt() {
// Force a refresh without hints to leave the previous
// line as the user typed it after a newline.
s.refresh_line_with_msg(None)?;
}
if s.line.is_empty() {
return Err(error::ReadlineError::Eof);
} else if !input_state.is_emacs_mode() {
return Ok(Submit);
}
}
Cmd::Move(Movement::EndOfLine) => {
Expand Down
8 changes: 0 additions & 8 deletions src/edit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -482,14 +482,6 @@ impl<'out, 'prompt, H: Helper> State<'out, 'prompt, H> {
self.refresh_line()
}

pub fn edit_delete(&mut self, n: RepeatCount) -> Result<()> {
if self.line.delete(n).is_some() {
self.refresh_line()
} else {
Ok(())
}
}

/// Exchange the char before cursor with the character at cursor.
pub fn edit_transpose_chars(&mut self) -> Result<()> {
self.changes.borrow_mut().begin();
Expand Down
188 changes: 99 additions & 89 deletions src/keymap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ pub enum Anchor {
Before,
}

/// Vi character search
/// character search
#[derive(Debug, Clone, PartialEq, Copy)]
pub enum CharSearch {
/// Forward search
Expand Down Expand Up @@ -283,7 +283,7 @@ pub enum Movement {
BackwardWord(RepeatCount, Word), // Backward until start of word
/// forward-word, vi-end-word, vi-next-word
ForwardWord(RepeatCount, At, Word), // Forward until start/end of word
/// vi-char-search
/// character-search, character-search-backward, vi-char-search
ViCharSearch(RepeatCount, CharSearch),
/// vi-first-print
ViFirstPrint,
Expand Down Expand Up @@ -560,29 +560,23 @@ impl InputState {
}
}
E(K::Char('A'), M::CTRL) => Cmd::Move(Movement::BeginningOfLine),
E(K::Char('B'), M::CTRL) => {
if positive {
Cmd::Move(Movement::BackwardChar(n))
} else {
Cmd::Move(Movement::ForwardChar(n))
}
}
E(K::Char('B'), M::CTRL) => Cmd::Move(if positive {
Movement::BackwardChar(n)
} else {
Movement::ForwardChar(n)
}),
E(K::Char('E'), M::CTRL) => Cmd::Move(Movement::EndOfLine),
E(K::Char('F'), M::CTRL) => {
if positive {
Cmd::Move(Movement::ForwardChar(n))
} else {
Cmd::Move(Movement::BackwardChar(n))
}
}
E(K::Char('F'), M::CTRL) => Cmd::Move(if positive {
Movement::ForwardChar(n)
} else {
Movement::BackwardChar(n)
}),
E(K::Char('G'), M::CTRL) | E::ESC | E(K::Char('G'), M::CTRL_ALT) => Cmd::Abort,
E(K::Char('H'), M::CTRL) | E::BACKSPACE => {
if positive {
Cmd::Kill(Movement::BackwardChar(n))
} else {
Cmd::Kill(Movement::ForwardChar(n))
}
}
E(K::Char('H'), M::CTRL) | E::BACKSPACE => Cmd::Kill(if positive {
Movement::BackwardChar(n)
} else {
Movement::ForwardChar(n)
}),
E(K::BackTab, M::NONE) => Cmd::CompleteBackward,
E(K::Tab, M::NONE) => {
if positive {
Expand All @@ -593,13 +587,11 @@ impl InputState {
}
// Don't complete hints when the cursor is not at the end of a line
E(K::Right, M::NONE) if wrt.has_hint() && wrt.is_cursor_at_end() => Cmd::CompleteHint,
E(K::Char('K'), M::CTRL) => {
if positive {
Cmd::Kill(Movement::EndOfLine)
} else {
Cmd::Kill(Movement::BeginningOfLine)
}
}
E(K::Char('K'), M::CTRL) => Cmd::Kill(if positive {
Movement::EndOfLine
} else {
Movement::BeginningOfLine
}),
E(K::Char('L'), M::CTRL) => Cmd::ClearScreen,
E(K::Char('N'), M::CTRL) => Cmd::NextHistory,
E(K::Char('P'), M::CTRL) => Cmd::PreviousHistory,
Expand All @@ -615,47 +607,65 @@ impl InputState {
match snd_key {
E(K::Char('G'), M::CTRL) | E::ESC => Cmd::Abort,
E(K::Char('U'), M::CTRL) => Cmd::Undo(n),
E(K::Backspace, M::NONE) => Cmd::Kill(if positive {
Movement::BeginningOfLine
} else {
Movement::EndOfLine
}),
_ => Cmd::Unknown,
}
}
}
E(K::Backspace, M::ALT) => {
if positive {
Cmd::Kill(Movement::BackwardWord(n, Word::Emacs))
} else {
Cmd::Kill(Movement::ForwardWord(n, At::AfterEnd, Word::Emacs))
// character-search, character-search-backward
E(K::Char(']'), m @ M::CTRL) | E(K::Char(']'), m @ M::CTRL_ALT) => {
let ch = rdr.next_key(false)?;
match ch {
E(K::Char(ch), M::NONE) => Cmd::Move(Movement::ViCharSearch(
n,
if positive {
if m.contains(M::ALT) {
CharSearch::Backward(ch)
} else {
CharSearch::ForwardBefore(ch)
}
} else if m.contains(M::ALT) {
CharSearch::ForwardBefore(ch)
} else {
CharSearch::Backward(ch)
},
)),
_ => Cmd::Unknown,
}
}
E(K::Backspace, M::ALT) => Cmd::Kill(if positive {
Movement::BackwardWord(n, Word::Emacs)
} else {
Movement::ForwardWord(n, At::AfterEnd, Word::Emacs)
}),
E(K::Char('<'), M::ALT) => Cmd::BeginningOfHistory,
E(K::Char('>'), M::ALT) => Cmd::EndOfHistory,
E(K::Char('B'), M::ALT)
| E(K::Char('b'), M::ALT)
| E(K::Left, M::CTRL)
| E(K::Left, M::ALT) => {
if positive {
Cmd::Move(Movement::BackwardWord(n, Word::Emacs))
} else {
Cmd::Move(Movement::ForwardWord(n, At::AfterEnd, Word::Emacs))
}
}
| E(K::Left, M::ALT) => Cmd::Move(if positive {
Movement::BackwardWord(n, Word::Emacs)
} else {
Movement::ForwardWord(n, At::AfterEnd, Word::Emacs)
}),
E(K::Char('C'), M::ALT) | E(K::Char('c'), M::ALT) => Cmd::CapitalizeWord,
E(K::Char('D'), M::ALT) | E(K::Char('d'), M::ALT) => {
if positive {
Cmd::Kill(Movement::ForwardWord(n, At::AfterEnd, Word::Emacs))
} else {
Cmd::Kill(Movement::BackwardWord(n, Word::Emacs))
}
}
E(K::Char('D'), M::ALT) | E(K::Char('d'), M::ALT) => Cmd::Kill(if positive {
Movement::ForwardWord(n, At::AfterEnd, Word::Emacs)
} else {
Movement::BackwardWord(n, Word::Emacs)
}),
E(K::Char('F'), M::ALT)
| E(K::Char('f'), M::ALT)
| E(K::Right, M::CTRL)
| E(K::Right, M::ALT) => {
if positive {
Cmd::Move(Movement::ForwardWord(n, At::AfterEnd, Word::Emacs))
} else {
Cmd::Move(Movement::BackwardWord(n, Word::Emacs))
}
}
| E(K::Right, M::ALT) => Cmd::Move(if positive {
Movement::ForwardWord(n, At::AfterEnd, Word::Emacs)
} else {
Movement::BackwardWord(n, Word::Emacs)
}),
E(K::Char('L'), M::ALT) | E(K::Char('l'), M::ALT) => Cmd::DowncaseWord,
E(K::Char('T'), M::ALT) | E(K::Char('t'), M::ALT) => Cmd::TransposeWords(n),
// TODO ESC-R (r): Undo all changes made to this line.
Expand Down Expand Up @@ -1022,30 +1032,34 @@ impl InputState {
) -> Result<Cmd> {
Ok(match key {
E(K::Home, M::NONE) => Cmd::Move(Movement::BeginningOfLine),
E(K::Left, M::NONE) => {
if positive {
Cmd::Move(Movement::BackwardChar(n))
} else {
Cmd::Move(Movement::ForwardChar(n))
}
}
E(K::Left, M::NONE) => Cmd::Move(if positive {
Movement::BackwardChar(n)
} else {
Movement::ForwardChar(n)
}),
E(K::Char('C'), M::CTRL) => Cmd::Interrupt,
E(K::Char('D'), M::CTRL) => Cmd::EndOfFile,
E(K::Delete, M::NONE) => {
if positive {
Cmd::Kill(Movement::ForwardChar(n))
E(K::Char('D'), M::CTRL) => {
if self.is_emacs_mode() && !wrt.line().is_empty() {
Cmd::Kill(if positive {
Movement::ForwardChar(n)
} else {
Movement::BackwardChar(n)
})
} else {
Cmd::Kill(Movement::BackwardChar(n))
Cmd::EndOfFile
}
}
E(K::Delete, M::NONE) => Cmd::Kill(if positive {
Movement::ForwardChar(n)
} else {
Movement::BackwardChar(n)
}),
E(K::End, M::NONE) => Cmd::Move(Movement::EndOfLine),
E(K::Right, M::NONE) => {
if positive {
Cmd::Move(Movement::ForwardChar(n))
} else {
Cmd::Move(Movement::BackwardChar(n))
}
}
E(K::Right, M::NONE) => Cmd::Move(if positive {
Movement::ForwardChar(n)
} else {
Movement::BackwardChar(n)
}),
E(K::Char('J'), M::CTRL) | E::ENTER => Cmd::AcceptOrInsertLine {
accept_in_the_middle: true,
},
Expand All @@ -1055,26 +1069,22 @@ impl InputState {
// most terminals override Ctrl+S to suspend execution
E(K::Char('S'), M::CTRL) => Cmd::ForwardSearchHistory,
E(K::Char('T'), M::CTRL) => Cmd::TransposeChars,
E(K::Char('U'), M::CTRL) => {
if positive {
Cmd::Kill(Movement::BeginningOfLine)
} else {
Cmd::Kill(Movement::EndOfLine)
}
}
E(K::Char('U'), M::CTRL) => Cmd::Kill(if positive {
Movement::BeginningOfLine
} else {
Movement::EndOfLine
}),
// most terminals override Ctrl+Q to resume execution
E(K::Char('Q'), M::CTRL) => Cmd::QuotedInsert,
#[cfg(not(windows))]
E(K::Char('V'), M::CTRL) => Cmd::QuotedInsert,
#[cfg(windows)]
E(K::Char('V'), M::CTRL) => Cmd::PasteFromClipboard,
E(K::Char('W'), M::CTRL) => {
if positive {
Cmd::Kill(Movement::BackwardWord(n, Word::Big))
} else {
Cmd::Kill(Movement::ForwardWord(n, At::AfterEnd, Word::Big))
}
}
E(K::Char('W'), M::CTRL) => Cmd::Kill(if positive {
Movement::BackwardWord(n, Word::Big)
} else {
Movement::ForwardWord(n, At::AfterEnd, Word::Big)
}),
E(K::Char('Y'), M::CTRL) => {
if positive {
Cmd::Yank(n, Anchor::Before)
Expand Down
10 changes: 5 additions & 5 deletions src/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ impl KeyEvent {
}
#[allow(clippy::match_same_arms)]
match c {
'\x00' => E(K::Char(' '), mods | M::CTRL),
'\x00' => E(K::Char('@'), mods | M::CTRL), // '\0'
'\x01' => E(K::Char('A'), mods | M::CTRL),
'\x02' => E(K::Char('B'), mods | M::CTRL),
'\x03' => E(K::Char('C'), mods | M::CTRL),
'\x04' => E(K::Char('D'), mods | M::CTRL),
'\x05' => E(K::Char('E'), mods | M::CTRL),
'\x06' => E(K::Char('F'), mods | M::CTRL),
'\x07' => E(K::Char('G'), mods | M::CTRL),
'\x08' => E(K::Backspace, mods), // '\b'
'\x07' => E(K::Char('G'), mods | M::CTRL), // '\a'
'\x08' => E(K::Backspace, mods), // '\b'
'\x09' => {
// '\t'
if mods.contains(M::SHIFT) {
Expand All @@ -60,12 +60,12 @@ impl KeyEvent {
'\x18' => E(K::Char('X'), mods | M::CTRL),
'\x19' => E(K::Char('Y'), mods | M::CTRL),
'\x1a' => E(K::Char('Z'), mods | M::CTRL),
'\x1b' => E(K::Esc, mods), // Ctrl-[
'\x1b' => E(K::Esc, mods), // Ctrl-[, '\e'
'\x1c' => E(K::Char('\\'), mods | M::CTRL),
'\x1d' => E(K::Char(']'), mods | M::CTRL),
'\x1e' => E(K::Char('^'), mods | M::CTRL),
'\x1f' => E(K::Char('_'), mods | M::CTRL),
'\x7f' => E(K::Backspace, mods), // Rubout
'\x7f' => E(K::Backspace, mods), // Rubout, Ctrl-?
'\u{9b}' => E(K::Esc, mods | M::SHIFT),
_ => E(K::Null, mods),
}
Expand Down
3 changes: 1 addition & 2 deletions src/tty/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,16 +272,15 @@ impl ConsoleRenderer {
for c in s.graphemes(true) {
if c == "\n" {
col = 0;
self.buffer.push_str(c);
} else {
let cw = width(c, &mut esc_seq);
col += cw;
if col > self.cols {
self.buffer.push('\n');
col = cw;
}
self.buffer.push_str(c);
}
self.buffer.push_str(c);
}
if col == self.cols {
self.buffer.push('\n');
Expand Down

0 comments on commit 8725a40

Please sign in to comment.