summaryrefslogtreecommitdiff
path: root/cli/tools
diff options
context:
space:
mode:
Diffstat (limited to 'cli/tools')
-rw-r--r--cli/tools/repl/editor.rs35
1 files changed, 35 insertions, 0 deletions
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<Cmd> {
+ 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
+ }
+ }
+}