on master help sign in
Readline style insert mode (#1039)
46d9ae2Bob
book/src/keymap.md+23−7
@@ -243,11 +243,26 @@ Mappings in the style of [vim-unimpaired](https://github.com/tpope/vim-unimpaire
243
243
244## Insert Mode
244## Insert Mode
245
245
246−| Key | Description | Command |
246+| Key | Description | Command |
247−| ----- | ----------- | ------- |
247+| ----- | ----------- | ------- |
248−| `Escape` | Switch to normal mode | `normal_mode` |
248+| `Escape` | Switch to normal mode | `normal_mode` |
249−| `Ctrl-x` | Autocomplete | `completion` |
249+| `Ctrl-x` | Autocomplete | `completion` |
250+| `Ctrl-r` | Insert a register content | `insert_register` |
250−| `Ctrl-w` | Delete previous word | `delete_word_backward` |
251+| `Ctrl-w` | Delete previous word | `delete_word_backward` |
252+| `Alt-d` | Delete next word | `delete_word_forward` |
253+| `Alt-b`, `Alt-Left` | Backward a word | `move_prev_word_end` |
254+| `Ctrl-b`, `Left` | Backward a char | `move_char_left` |
255+| `Alt-f`, `Alt-Right` | Forward a word | `move_next_word_start` |
256+| `Ctrl-f`, `Right` | Forward a char | `move_char_right` |
257+| `Ctrl-e`, `End` | move to line end | `goto_line_end_newline` |
258+| `Ctrl-a`, `Home` | move to line start | `goto_line_start` |
259+| `Ctrl-w` | delete previous word | `delete_word_backwar` |
260+| `Ctrl-u` | delete to start of line | `kill_to_line_start` |
261+| `Ctrl-k` | delete to end of line | `kill_to_line_end` |
262+| `backspace`, `Ctrl-h` | delete previous char | `delete_char_backward` |
263+| `delete`, `Ctrl-d` | delete previous char | `delete_char_forward` |
264+| `Ctrl-p`, `Up` | move to previous line | `move_line_up` |
265+| `Ctrl-n`, `Down` | move to next line | `move_line_down` |
251
266
252## Select / extend mode
267## Select / extend mode
253
268
@@ -285,6 +300,7 @@ Keys to use within prompt, Remapping currently not supported.
285| `Ctrl-e`, `End` | Move prompt end |
300| `Ctrl-e`, `End` | Move prompt end |
286| `Ctrl-a`, `Home` | Move prompt start |
301| `Ctrl-a`, `Home` | Move prompt start |
287| `Ctrl-w` | Delete previous word |
302| `Ctrl-w` | Delete previous word |
303+| `Alt-d` | Delete next word |
288| `Ctrl-u` | Delete to start of line |
304| `Ctrl-u` | Delete to start of line |
289| `Ctrl-k` | Delete to end of line |
305| `Ctrl-k` | Delete to end of line |
290| `backspace`, `Ctrl-h` | Delete previous char |
306| `backspace`, `Ctrl-h` | Delete previous char |
@@ -292,7 +308,7 @@ Keys to use within prompt, Remapping currently not supported.
292| `Ctrl-s` | Insert a word under doc cursor, may be changed to Ctrl-r Ctrl-w later |
308| `Ctrl-s` | Insert a word under doc cursor, may be changed to Ctrl-r Ctrl-w later |
293| `Ctrl-p`, `Up` | Select previous history |
309| `Ctrl-p`, `Up` | Select previous history |
294| `Ctrl-n`, `Down` | Select next history |
310| `Ctrl-n`, `Down` | Select next history |
295−| `Tab` | Select next completion item |
311+| `Tab` | Select next completion item |
296−| `BackTab` | Select previous completion item |
312+| `BackTab` | Select previous completion item |
297| `Enter` | Open selected |
313| `Enter` | Open selected |
298
314
helix-term/src/commands.rs+65−2
@@ -187,6 +187,7 @@ impl Command {
187 copy_selection_on_prev_line, "Copy selection on previous line",
187 copy_selection_on_prev_line, "Copy selection on previous line",
188 move_next_word_start, "Move to beginning of next word",
188 move_next_word_start, "Move to beginning of next word",
189 move_prev_word_start, "Move to beginning of previous word",
189 move_prev_word_start, "Move to beginning of previous word",
190+ move_prev_word_end, "Move to end of previous word",
190 move_next_word_end, "Move to end of next word",
191 move_next_word_end, "Move to end of next word",
191 move_next_long_word_start, "Move to beginning of next long word",
192 move_next_long_word_start, "Move to beginning of next long word",
192 move_prev_long_word_start, "Move to beginning of previous long word",
193 move_prev_long_word_start, "Move to beginning of previous long word",
@@ -284,6 +285,9 @@ impl Command {
284 delete_char_backward, "Delete previous char",
285 delete_char_backward, "Delete previous char",
285 delete_char_forward, "Delete next char",
286 delete_char_forward, "Delete next char",
286 delete_word_backward, "Delete previous word",
287 delete_word_backward, "Delete previous word",
288+ delete_word_forward, "Delete next word",
289+ kill_to_line_start, "Delete content till the start of the line",
290+ kill_to_line_end, "Delete content till the end of the line",
287 undo, "Undo change",
291 undo, "Undo change",
288 redo, "Redo change",
292 redo, "Redo change",
289 earlier, "Move backward in history",
293 earlier, "Move backward in history",
@@ -330,6 +334,7 @@ impl Command {
330 wclose, "Close window",
334 wclose, "Close window",
331 wonly, "Current window only",
335 wonly, "Current window only",
332 select_register, "Select register",
336 select_register, "Select register",
337+ insert_register, "Insert register",
333 align_view_middle, "Align view middle",
338 align_view_middle, "Align view middle",
334 align_view_top, "Align view top",
339 align_view_top, "Align view top",
335 align_view_center, "Align view center",
340 align_view_center, "Align view center",
@@ -572,6 +577,29 @@ fn extend_to_line_start(cx: &mut Context) {
572 goto_line_start_impl(view, doc, Movement::Extend)
577 goto_line_start_impl(view, doc, Movement::Extend)
573}
578}
574
579
580+fn kill_to_line_start(cx: &mut Context) {
581+ let (view, doc) = current!(cx.editor);
582+ let text = doc.text().slice(..);
583+
584+ let selection = doc.selection(view.id).clone().transform(|range| {
585+ let line = range.cursor_line(text);
586+ range.put_cursor(text, text.line_to_char(line), true)
587+ });
588+ delete_selection_insert_mode(doc, view, &selection);
589+}
590+
591+fn kill_to_line_end(cx: &mut Context) {
592+ let (view, doc) = current!(cx.editor);
593+ let text = doc.text().slice(..);
594+
595+ let selection = doc.selection(view.id).clone().transform(|range| {
596+ let line = range.cursor_line(text);
597+ let pos = line_end_char_index(&text, line);
598+ range.put_cursor(text, pos, true)
599+ });
600+ delete_selection_insert_mode(doc, view, &selection);
601+}
602+
575fn goto_first_nonwhitespace(cx: &mut Context) {
603fn goto_first_nonwhitespace(cx: &mut Context) {
576 let (view, doc) = current!(cx.editor);
604 let (view, doc) = current!(cx.editor);
577 let text = doc.text().slice(..);
605 let text = doc.text().slice(..);
@@ -684,6 +712,10 @@ fn move_prev_word_start(cx: &mut Context) {
684 move_word_impl(cx, movement::move_prev_word_start)
712 move_word_impl(cx, movement::move_prev_word_start)
685}
713}
686
714
715+fn move_prev_word_end(cx: &mut Context) {
716+ move_word_impl(cx, movement::move_prev_word_end)
717+}
718+
687fn move_next_word_end(cx: &mut Context) {
719fn move_next_word_end(cx: &mut Context) {
688 move_word_impl(cx, movement::move_next_word_end)
720 move_word_impl(cx, movement::move_next_word_end)
689}
721}
@@ -1586,6 +1618,17 @@ fn delete_selection_impl(reg: &mut Register, doc: &mut Document, view_id: ViewId
1586 doc.apply(&transaction, view_id);
1618 doc.apply(&transaction, view_id);
1587}
1619}
1588
1620
1621+#[inline]
1622+fn delete_selection_insert_mode(doc: &mut Document, view: &View, selection: &Selection) {
1623+ let view_id = view.id;
1624+
1625+ // then delete
1626+ let transaction = Transaction::change_by_selection(doc.text(), selection, |range| {
1627+ (range.from(), range.to(), None)
1628+ });
1629+ doc.apply(&transaction, view_id);
1630+}
1631+
1589fn delete_selection(cx: &mut Context) {
1632fn delete_selection(cx: &mut Context) {
1590 let reg_name = cx.register.unwrap_or('"');
1633 let reg_name = cx.register.unwrap_or('"');
1591 let (view, doc) = current!(cx.editor);
1634 let (view, doc) = current!(cx.editor);
@@ -4010,8 +4053,19 @@ pub mod insert {
4010 .selection(view.id)
4053 .selection(view.id)
4011 .clone()
4054 .clone()
4012 .transform(|range| movement::move_prev_word_start(text, range, count));
4055 .transform(|range| movement::move_prev_word_start(text, range, count));
4013− doc.set_selection(view.id, selection);
4056+ delete_selection_insert_mode(doc, view, &selection);
4014− delete_selection(cx)
4057+ }
4058+
4059+ pub fn delete_word_forward(cx: &mut Context) {
4060+ let count = cx.count();
4061+ let (view, doc) = current!(cx.editor);
4062+ let text = doc.text().slice(..);
4063+
4064+ let selection = doc
4065+ .selection(view.id)
4066+ .clone()
4067+ .transform(|range| movement::move_next_word_start(text, range, count));
4068+ delete_selection_insert_mode(doc, view, &selection);
4015 }
4069 }
4016}
4070}
4017
4071
@@ -4973,6 +5027,15 @@ fn select_register(cx: &mut Context) {
4973 })
5027 })
4974}
5028}
4975
5029
5030+fn insert_register(cx: &mut Context) {
5031+ cx.on_next_key(move |cx, event| {
5032+ if let Some(ch) = event.char() {
5033+ cx.editor.selected_register = Some(ch);
5034+ paste_before(cx);
5035+ }
5036+ })
5037+}
5038+
4976fn align_view_top(cx: &mut Context) {
5039fn align_view_top(cx: &mut Context) {
4977 let (view, doc) = current!(cx.editor);
5040 let (view, doc) = current!(cx.editor);
4978 align_view(doc, view, Align::Top);
5041 align_view(doc, view, Align::Top);
helix-term/src/keymap.rs+17
@@ -731,21 +731,38 @@ impl Default for Keymaps {
731 "esc" => normal_mode,
731 "esc" => normal_mode,
732
732
733 "backspace" => delete_char_backward,
733 "backspace" => delete_char_backward,
734+ "C-h" => delete_char_backward,
734 "del" => delete_char_forward,
735 "del" => delete_char_forward,
736+ "C-d" => delete_char_forward,
735 "ret" => insert_newline,
737 "ret" => insert_newline,
736 "tab" => insert_tab,
738 "tab" => insert_tab,
737 "C-w" => delete_word_backward,
739 "C-w" => delete_word_backward,
740+ "A-d" => delete_word_forward,
738
741
739 "left" => move_char_left,
742 "left" => move_char_left,
743+ "C-b" => move_char_left,
740 "down" => move_line_down,
744 "down" => move_line_down,
745+ "C-n" => move_line_down,
741 "up" => move_line_up,
746 "up" => move_line_up,
747+ "C-p" => move_line_up,
742 "right" => move_char_right,
748 "right" => move_char_right,
749+ "C-f" => move_char_right,
750+ "A-b" => move_prev_word_end,
751+ "A-left" => move_prev_word_end,
752+ "A-f" => move_next_word_start,
753+ "A-right" => move_next_word_start,
743 "pageup" => page_up,
754 "pageup" => page_up,
744 "pagedown" => page_down,
755 "pagedown" => page_down,
745 "home" => goto_line_start,
756 "home" => goto_line_start,
757+ "C-a" => goto_line_start,
746 "end" => goto_line_end_newline,
758 "end" => goto_line_end_newline,
759+ "C-e" => goto_line_end_newline,
760+
761+ "C-k" => kill_to_line_end,
762+ "C-u" => kill_to_line_start,
747
763
748 "C-x" => completion,
764 "C-x" => completion,
765+ "C-r" => insert_register,
749 });
766 });
750 Keymaps(hashmap!(
767 Keymaps(hashmap!(
751 Mode::Normal => Keymap::new(normal),
768 Mode::Normal => Keymap::new(normal),
helix-term/src/ui/prompt.rs+9
@@ -231,6 +231,14 @@ impl Prompt {
231 self.completion = (self.completion_fn)(&self.line);
231 self.completion = (self.completion_fn)(&self.line);
232 }
232 }
233
233
234+ pub fn delete_word_forwards(&mut self) {
235+ let pos = self.eval_movement(Movement::ForwardWord(1));
236+ self.line.replace_range(self.cursor..pos, "");
237+
238+ self.exit_selection();
239+ self.completion = (self.completion_fn)(&self.line);
240+ }
241+
234 pub fn kill_to_start_of_line(&mut self) {
242 pub fn kill_to_start_of_line(&mut self) {
235 let pos = self.eval_movement(Movement::StartOfLine);
243 let pos = self.eval_movement(Movement::StartOfLine);
236 self.line.replace_range(pos..self.cursor, "");
244 self.line.replace_range(pos..self.cursor, "");
@@ -435,6 +443,7 @@ impl Component for Prompt {
435 ctrl!('e') | key!(End) => self.move_end(),
443 ctrl!('e') | key!(End) => self.move_end(),
436 ctrl!('a') | key!(Home) => self.move_start(),
444 ctrl!('a') | key!(Home) => self.move_start(),
437 ctrl!('w') => self.delete_word_backwards(),
445 ctrl!('w') => self.delete_word_backwards(),
446+ alt!('d') => self.delete_word_forwards(),
438 ctrl!('k') => self.kill_to_end_of_line(),
447 ctrl!('k') => self.kill_to_end_of_line(),
439 ctrl!('u') => self.kill_to_start_of_line(),
448 ctrl!('u') => self.kill_to_start_of_line(),
440 ctrl!('h') | key!(Backspace) => {
449 ctrl!('h') | key!(Backspace) => {