on master help sign in
support insert register in prompt (#2458)
6462542Bob
book/src/keymap.md+1
@@ -367,6 +367,7 @@ Keys to use within prompt, Remapping currently not supported.
367| `Ctrl-s` | Insert a word under doc cursor, may be changed to Ctrl-r Ctrl-w later |
367| `Ctrl-s` | Insert a word under doc cursor, may be changed to Ctrl-r Ctrl-w later |
368| `Ctrl-p`, `Up` | Select previous history |
368| `Ctrl-p`, `Up` | Select previous history |
369| `Ctrl-n`, `Down` | Select next history |
369| `Ctrl-n`, `Down` | Select next history |
370+| `Ctrl-r` | Insert the content of the register selected by following input char |
370| `Tab` | Select next completion item |
371| `Tab` | Select next completion item |
371| `BackTab` | Select previous completion item |
372| `BackTab` | Select previous completion item |
372| `Enter` | Open selected |
373| `Enter` | Open selected |
helix-term/src/ui/prompt.rs+39
@@ -16,6 +16,7 @@ use helix_view::{
16};
16};
17
17
18pub type Completion = (RangeFrom<usize>, Cow<'static, str>);
18pub type Completion = (RangeFrom<usize>, Cow<'static, str>);
19+type PromptCharHandler = Box<dyn Fn(&mut Prompt, char, &Context)>;
19
20
20pub struct Prompt {
21pub struct Prompt {
21 prompt: Cow<'static, str>,
22 prompt: Cow<'static, str>,
@@ -28,6 +29,7 @@ pub struct Prompt {
28 completion_fn: Box<dyn FnMut(&Editor, &str) -> Vec<Completion>>,
29 completion_fn: Box<dyn FnMut(&Editor, &str) -> Vec<Completion>>,
29 callback_fn: Box<dyn FnMut(&mut Context, &str, PromptEvent)>,
30 callback_fn: Box<dyn FnMut(&mut Context, &str, PromptEvent)>,
30 pub doc_fn: Box<dyn Fn(&str) -> Option<Cow<str>>>,
31 pub doc_fn: Box<dyn Fn(&str) -> Option<Cow<str>>>,
32+ next_char_handler: Option<PromptCharHandler>,
31}
33}
32
34
33#[derive(Clone, Copy, PartialEq)]
35#[derive(Clone, Copy, PartialEq)]
@@ -78,6 +80,7 @@ impl Prompt {
78 completion_fn: Box::new(completion_fn),
80 completion_fn: Box::new(completion_fn),
79 callback_fn: Box::new(callback_fn),
81 callback_fn: Box::new(callback_fn),
80 doc_fn: Box::new(|_| None),
82 doc_fn: Box::new(|_| None),
83+ next_char_handler: None,
81 }
84 }
82 }
85 }
83
86
@@ -191,6 +194,13 @@ impl Prompt {
191 }
194 }
192
195
193 pub fn insert_char(&mut self, c: char, cx: &Context) {
196 pub fn insert_char(&mut self, c: char, cx: &Context) {
197+ if let Some(handler) = &self.next_char_handler.take() {
198+ handler(self, c, cx);
199+
200+ self.next_char_handler = None;
201+ return;
202+ }
203+
194 self.line.insert(self.cursor, c);
204 self.line.insert(self.cursor, c);
195 let mut cursor = GraphemeCursor::new(self.cursor, self.line.len(), false);
205 let mut cursor = GraphemeCursor::new(self.cursor, self.line.len(), false);
196 if let Ok(Some(pos)) = cursor.next_boundary(&self.line, 0) {
206 if let Ok(Some(pos)) = cursor.next_boundary(&self.line, 0) {
@@ -538,6 +548,35 @@ impl Component for Prompt {
538 (self.callback_fn)(cx, &self.line, PromptEvent::Update)
548 (self.callback_fn)(cx, &self.line, PromptEvent::Update)
539 }
549 }
540 ctrl!('q') => self.exit_selection(),
550 ctrl!('q') => self.exit_selection(),
551+ ctrl!('r') => {
552+ self.completion = cx
553+ .editor
554+ .registers
555+ .inner()
556+ .iter()
557+ .map(|(ch, reg)| {
558+ let content = reg
559+ .read()
560+ .get(0)
561+ .and_then(|s| s.lines().next().to_owned())
562+ .unwrap_or_default();
563+ (0.., format!("{} {}", ch, &content).into())
564+ })
565+ .collect();
566+ self.next_char_handler = Some(Box::new(|prompt, c, context| {
567+ prompt.insert_str(
568+ context
569+ .editor
570+ .registers
571+ .read(c)
572+ .and_then(|r| r.first())
573+ .map_or("", |r| r.as_str()),
574+ );
575+ prompt.recalculate_completion(context.editor);
576+ }));
577+ (self.callback_fn)(cx, &self.line, PromptEvent::Update);
578+ return EventResult::Consumed(None);
579+ }
541 // any char event that's not mapped to any other combo
580 // any char event that's not mapped to any other combo
542 KeyEvent {
581 KeyEvent {
543 code: KeyCode::Char(c),
582 code: KeyCode::Char(c),