Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes to allow Windows backspace keybindings #422

Closed
wants to merge 12 commits into from
7 changes: 5 additions & 2 deletions examples/example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use rustyline::error::ReadlineError;
use rustyline::highlight::{Highlighter, MatchingBracketHighlighter};
use rustyline::hint::{Hinter, HistoryHinter};
use rustyline::validate::{self, MatchingBracketValidator, Validator};
use rustyline::{Cmd, CompletionType, Config, Context, EditMode, Editor, KeyPress};
use rustyline::{Cmd, CompletionType, Config, Context, EditMode, Editor, KeyPress, Movement, Word};
use rustyline_derive::Helper;

#[derive(Helper)]
Expand Down Expand Up @@ -83,7 +83,7 @@ fn main() -> rustyline::Result<()> {
let config = Config::builder()
.history_ignore_space(true)
.completion_type(CompletionType::List)
.edit_mode(EditMode::Emacs)
.edit_mode(EditMode::Vi)
fdncred marked this conversation as resolved.
Show resolved Hide resolved
.output_stream(OutputStreamType::Stdout)
.build();
let h = MyHelper {
Expand All @@ -97,6 +97,9 @@ fn main() -> rustyline::Result<()> {
rl.set_helper(Some(h));
rl.bind_sequence(KeyPress::Meta('N'), Cmd::HistorySearchForward);
rl.bind_sequence(KeyPress::Meta('P'), Cmd::HistorySearchBackward);
rl.bind_sequence(KeyPress::ControlBackspace, Cmd::Kill(Movement::BackwardWord(1, Word::Vi)));
rl.bind_sequence(KeyPress::MetaBackspace, Cmd::Kill(Movement::BackwardChar(1)));
rl.bind_sequence(KeyPress::ShiftBackspace, Cmd::Kill(Movement::BackwardChar(1)));
fdncred marked this conversation as resolved.
Show resolved Hide resolved
if rl.load_history("history.txt").is_err() {
println!("No previous history.");
}
Expand Down
6 changes: 6 additions & 0 deletions src/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ pub enum KeyPress {
ControlRight,
/// Ctrl-↑
ControlUp,
/// Control Backspace
fdncred marked this conversation as resolved.
Show resolved Hide resolved
ControlBackspace,
/// Ctrl-char
Ctrl(char),
/// ⌦
Expand All @@ -46,6 +48,8 @@ pub enum KeyPress {
Left,
/// Escape-char or Alt-char
Meta(char),
/// Alt Backspace
MetaBackspace,
/// `KeyPress::Char('\0')`
Null,
/// ⇟
Expand All @@ -54,6 +58,8 @@ pub enum KeyPress {
PageUp,
/// → arrow key
Right,
/// Shift Backspace
ShiftBackspace,
/// Shift-↓
ShiftDown,
/// Shift-←
Expand Down
19 changes: 17 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ use std::path::Path;
use std::result;
use std::sync::{Arc, Mutex, RwLock};

use log::debug;
use log::{warn, debug};
use unicode_width::UnicodeWidthStr;

use crate::tty::{RawMode, Renderer, Term, Terminal};
Expand Down Expand Up @@ -888,7 +888,22 @@ impl<H: Helper> Editor<H> {
/// Bind a sequence to a command.
pub fn bind_sequence(&mut self, key_seq: KeyPress, cmd: Cmd) -> Option<Cmd> {
if let Ok(mut bindings) = self.custom_bindings.write() {
bindings.insert(key_seq, cmd)
let key = if let KeyPress::Char(ref c) = key_seq {
if c.is_control() {
keys::char_to_key_press(*c)
} else {
key_seq
}
} else if let KeyPress::Ctrl(ref c) = key_seq {
if c.is_control() {
keys::char_to_key_press(*c);
fdncred marked this conversation as resolved.
Show resolved Hide resolved
warn!(target: "rustyline", "KeyPress::Ctrl({:?}) may not work on unix", c)
fdncred marked this conversation as resolved.
Show resolved Hide resolved
}
key_seq
} else {
key_seq
};
bindings.insert(key, cmd)
} else {
None
}
Expand Down
21 changes: 20 additions & 1 deletion src/tty/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,17 @@ impl RawReader for ConsoleRawReader {
KeyPress::Down
});
}
winuser::VK_BACK => {
return Ok(if ctrl {
KeyPress::ControlBackspace
} else if shift {
KeyPress::ShiftBackspace
} else if meta {
KeyPress::MetaBackspace
} else {
KeyPress::Backspace
});
}
fdncred marked this conversation as resolved.
Show resolved Hide resolved
winuser::VK_DELETE => return Ok(KeyPress::Delete),
winuser::VK_HOME => return Ok(KeyPress::Home),
winuser::VK_END => return Ok(KeyPress::End),
Expand Down Expand Up @@ -220,13 +231,21 @@ impl RawReader for ConsoleRawReader {
};
let c = rc?;
if meta {
return Ok(KeyPress::Meta(c));
let mut key = keys::char_to_key_press(c);
fdncred marked this conversation as resolved.
Show resolved Hide resolved
if key == KeyPress::Backspace && meta {
fdncred marked this conversation as resolved.
Show resolved Hide resolved
key = KeyPress::MetaBackspace;
} else {
key = KeyPress::Meta(c);
}
return Ok(key);
} else {
let mut key = keys::char_to_key_press(c);
if key == KeyPress::Tab && shift {
key = KeyPress::BackTab;
} else if key == KeyPress::Char(' ') && ctrl {
key = KeyPress::Ctrl(' ');
} else if key == KeyPress::Backspace && ctrl {
key = KeyPress::ControlBackspace;
fdncred marked this conversation as resolved.
Show resolved Hide resolved
}
return Ok(key);
}
Expand Down