From ac2cf2cb3ea36388437aab17d31e1c5e984d9693 Mon Sep 17 00:00:00 2001 From: sigmaSd Date: Mon, 20 Jun 2022 23:47:25 +0100 Subject: fix(repl): accept tab when previous character is whitespace (#14898) --- cli/tools/repl/editor.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'cli/tools/repl') diff --git a/cli/tools/repl/editor.rs b/cli/tools/repl/editor.rs index 502134ebc..cc095a603 100644 --- a/cli/tools/repl/editor.rs +++ b/cli/tools/repl/editor.rs @@ -23,6 +23,7 @@ use rustyline::EventHandler; use rustyline::KeyCode; use rustyline::KeyEvent; use rustyline::Modifiers; +use rustyline::{ConditionalEventHandler, Event, EventContext, RepeatCount}; use rustyline_derive::{Helper, Hinter}; use std::borrow::Cow; use std::path::PathBuf; @@ -369,6 +370,10 @@ impl ReplEditor { KeyEvent(KeyCode::Char('s'), Modifiers::CTRL), EventHandler::Simple(Cmd::Newline), ); + editor.bind_sequence( + KeyEvent::from('\t'), + EventHandler::Conditional(Box::new(TabEventHandler)), + ); ReplEditor { inner: Arc::new(Mutex::new(editor)), @@ -391,3 +396,33 @@ impl ReplEditor { Ok(()) } } + +/// A custom tab key event handler +/// It uses a heuristic to determine if the user is requesting completion or if they want to insert an actual tab +/// The heuristic goes like this: +/// - If the last character before the cursor is whitespace, the the user wants to insert a tab +/// - Else the user is requesting completion +struct TabEventHandler; +impl ConditionalEventHandler for TabEventHandler { + fn handle( + &self, + evt: &Event, + n: RepeatCount, + _: bool, + ctx: &EventContext, + ) -> Option { + debug_assert_eq!(*evt, Event::from(KeyEvent::from('\t'))); + if ctx.line().is_empty() + || ctx.line()[..ctx.pos()] + .chars() + .rev() + .next() + .filter(|c| c.is_whitespace()) + .is_some() + { + Some(Cmd::Insert(n, "\t".into())) + } else { + None // default complete + } + } +} -- cgit v1.2.3