rustyline
rustyline copied to clipboard
How do you express a vi keybinding with numeric argument?
In nushell, we've been experimenting with adding configurable keybindings. We wanted to set up some configuration, and then call into rustyline using the bind_sequence
commands, like this:
// add key bindings to move over a whole word with Ctrl+ArrowLeft and Ctrl+ArrowRight
rl.bind_sequence(
KeyPress::ControlLeft,
Cmd::Move(Movement::BackwardWord(1, Word::Vi)),
);
rl.bind_sequence(
KeyPress::ControlRight,
Cmd::Move(Movement::ForwardWord(1, At::AfterEnd, Word::Vi)),
);
An issue I'm running into: how would the user define their own vi bindings? I don't see a way to express a bind_sequence
where there is a numeric parameter. When you call bind_sequence
it looks like you have to pick a statically known number of repeats, rather than letting rustyline get the number from the user.
See https://github.com/kkawakam/rustyline/blob/master/src/keymap.rs#L449. And https://github.com/kkawakam/rustyline/blob/master/src/keymap.rs#L595. If the command is repeatable, the static/default number should be replaced by the dynamic/user number.
@gwenn - is this right mental model:
The repeat number is the one used when there is no numeric argument given in vi mode. If there is a numeric argument, it overwrites the numeric argument set by the keybinding
Yes.
@gwenn I'm working with @jonathandturner on keybindings in nushell and I'm having trouble figuring out how I can remap some of these Vi keybindings that you have in keymap.rs where instead of calling a Cmd::something
function, you have a code block.
It may also be helpful to understand that we're trying to use a yml file to express keybindings so that end users can change them if they wish. Here's an example of our yaml for one command.
- key:
Char: e
binding:
Move:
ForwardWord:
repeat: 1
at: BeforeEnd
word: Vi
And this is the corresponding function in your code that we created this yaml from.
KeyPress::Char('e') => Cmd::Move(Movement::ForwardWord(n, At::BeforeEnd, Word::Vi)),
With that in mind. I'd appreciate any advice you could give for functions like this. Since they don't call a direct function, but more of a code block, I'm not sure how we can expose them to the user to change. Any ideas?
KeyPress::Char('a') => {
// vi-append-mode
self.input_mode = InputMode::Insert;
wrt.doing_insert();
Cmd::Move(Movement::ForwardChar(n))
}
KeyPress::Char('c') => {
self.input_mode = InputMode::Insert;
match self.vi_cmd_motion(rdr, wrt, key, n)? {
Some(mvt) => Cmd::Replace(mvt, None),
None => Cmd::Unknown,
}
}
See https://github.com/kkawakam/rustyline/issues/306
And https://github.com/kkawakam/rustyline/pull/293#issuecomment-557862724
=> We need to refactor / introduce an indirection between KeyPress
and action(s).