Closed segeljakt closed 1 year ago
I almost sure that you can already do it using a ConditionalEventHandler
without changing the Validator API.
See ConditionalEventHandler
And EventContext.
Oh, nice. Thanks
Tell me if you have any trouble but the idea is to return either AcceptLine
or Newline
(or None) depending on the input / cursor / ...
Alright I managed to get it working 👍
pub(crate) struct BraceValidator;
impl ConditionalEventHandler for BraceValidator {
fn handle(
&self,
evt: &rustyline::Event,
n: rustyline::RepeatCount,
positive: bool,
ctx: &rustyline::EventContext,
) -> Option<rustyline::Cmd> {
if ctx.line().ends_with('}') && ctx.pos() == ctx.line().len() {
return Some(rustyline::Cmd::AcceptLine);
} else {
return None;
}
}
}
fn main() {
let mut rl = Editor::<Repl, FileHistory>::new()?;
rl.bind_sequence(
KeyEvent::new('\r', Modifiers::NONE),
EventHandler::Conditional(Box::new(BraceValidator)),
);
}
Is KeyEvent::new('\r', Modifiers::NONE)
the right event to use?
Good question !
It works on macOS but I'm not sure how other platforms handle it. Maybe it's the same
In fact, there is a simpler solution than the ConditionalEventHandler
:
https://docs.rs/rustyline/latest/rustyline/enum.Cmd.html#variant.AcceptOrInsertLine
=> accept_in_the_middle
should be false.
(Sorry I forgot...)
And you want to overwrite these bindings:
https://github.com/kkawakam/rustyline/blob/aecbf41252b22c4e19785342073c5695a56c4d2b/src/keymap.rs#L1050-L1052
And you should be able to use https://docs.rs/rustyline/latest/rustyline/enum.KeyCode.html#variant.Enter instead of '\r'
...
Sorry for the messy API.
Your solution works really nice, thanks 👍
If I give this input to my rustyline REPL (
|
is cursor):I have currently implemented that
<Enter>
evaluates the statement. I did this validating that the current line ends with}
, and if so, yieldsValidationResult::Valid
and otherwiseValidationResult::Incomplete
. However, if my cursor is here:I would like
<Enter>
to insert a newline:This requires me to know the position of the cursor, but since
validate
only takes an input this is not possible:Would it be feasible to extend
Validator
with this functionality?