@@ -15,11 +15,13 @@ use helix_view::{
15 Document, DocumentId, Editor, ViewId,
15 Document, DocumentId, Editor, ViewId,
18use helix_lsp::{
19use helix_lsp::{
20 util::{lsp_pos_to_pos, lsp_range_to_range, pos_to_lsp_pos, range_to_lsp_range},
21 util::{lsp_pos_to_pos, lsp_range_to_range, pos_to_lsp_pos, range_to_lsp_range},
21 OffsetEncoding,
22 OffsetEncoding,
23use movement::Movement;
25use movement::Movement;
25use crate::{
27use crate::{
@@ -29,7 +31,7 @@ use crate::{
30use crate::application::{LspCallbackWrapper, LspCallbacks};
32use crate::application::{LspCallbackWrapper, LspCallbacks};
31use futures_util::FutureExt;
33use futures_util::FutureExt;
32−use std::future::Future;
34+use std::{fmt, future::Future, path::Display, str::FromStr};
35 borrow::Cow,
37 borrow::Cow,
@@ -133,11 +135,145 @@ fn align_view(doc: &Document, view: &mut View, align: Align) {
133 view.first_line = line.saturating_sub(relative);
135 view.first_line = line.saturating_sub(relative);
136−/// A command is a function that takes the current state and a count, and does a side-effect on the
138+/// A command is composed of a static name, and a function that takes the current state plus a count,
137−/// state (usually by creating and applying a transaction).
139+/// and does a side-effect on the state (usually by creating and applying a transaction).
140+#[derive(Copy, Clone)]
138−pub type Command = fn(cx: &mut Context);
141+pub struct Command(&'static str, fn(cx: &mut Context));
143+macro_rules! commands {
144+ ( $($name:ident),* ) => {
146+ #[allow(non_upper_case_globals)]
147+ pub const $name: Self = Self(stringify!($name), $name);
150+ pub const COMMAND_LIST: &'static [Self] = &[
157+ pub fn execute(&self, cx: &mut Context) {
161+ pub fn name(&self) -> &'static str {
172+ move_first_nonwhitespace,
173+ move_next_word_start,
174+ move_prev_word_start,
178+ extend_next_word_start,
179+ extend_prev_word_start,
180+ extend_next_word_end,
187+ extend_till_prev_char,
189+ extend_first_nonwhitespace,
204+ split_selection_on_newline,
230+ goto_type_definition,
231+ goto_implementation,
240+ delete_char_backward,
241+ delete_char_forward,
242+ delete_word_backward,
246+ replace_with_yanked,
254+ keep_primary_selection,
140−pub fn move_char_left(cx: &mut Context) {
276+fn move_char_left(cx: &mut Context) {
141 let count = cx.count();
277 let count = cx.count();
142 let (view, doc) = cx.current();
278 let (view, doc) = cx.current();
143 let text = doc.text().slice(..);
279 let text = doc.text().slice(..);
@@ -147,7 +283,7 @@ pub fn move_char_left(cx: &mut Context) {
147 doc.set_selection(view.id, selection);
283 doc.set_selection(view.id, selection);
150−pub fn move_char_right(cx: &mut Context) {
286+fn move_char_right(cx: &mut Context) {
151 let count = cx.count();
287 let count = cx.count();
152 let (view, doc) = cx.current();
288 let (view, doc) = cx.current();
153 let text = doc.text().slice(..);
289 let text = doc.text().slice(..);
@@ -157,7 +293,7 @@ pub fn move_char_right(cx: &mut Context) {
157 doc.set_selection(view.id, selection);
293 doc.set_selection(view.id, selection);
160−pub fn move_line_up(cx: &mut Context) {
296+fn move_line_up(cx: &mut Context) {
161 let count = cx.count();
297 let count = cx.count();
162 let (view, doc) = cx.current();
298 let (view, doc) = cx.current();
163 let text = doc.text().slice(..);
299 let text = doc.text().slice(..);
@@ -167,7 +303,7 @@ pub fn move_line_up(cx: &mut Context) {
167 doc.set_selection(view.id, selection);
303 doc.set_selection(view.id, selection);
170−pub fn move_line_down(cx: &mut Context) {
306+fn move_line_down(cx: &mut Context) {
171 let count = cx.count();
307 let count = cx.count();
172 let (view, doc) = cx.current();
308 let (view, doc) = cx.current();
173 let text = doc.text().slice(..);
309 let text = doc.text().slice(..);
@@ -177,7 +313,7 @@ pub fn move_line_down(cx: &mut Context) {
177 doc.set_selection(view.id, selection);
313 doc.set_selection(view.id, selection);
180−pub fn move_line_end(cx: &mut Context) {
316+fn move_line_end(cx: &mut Context) {
181 let (view, doc) = cx.current();
317 let (view, doc) = cx.current();
183 let selection = doc.selection(view.id).transform(|range| {
319 let selection = doc.selection(view.id).transform(|range| {
@@ -193,7 +329,7 @@ pub fn move_line_end(cx: &mut Context) {
193 doc.set_selection(view.id, selection);
329 doc.set_selection(view.id, selection);
196−pub fn move_line_start(cx: &mut Context) {
332+fn move_line_start(cx: &mut Context) {
197 let (view, doc) = cx.current();
333 let (view, doc) = cx.current();
199 let selection = doc.selection(view.id).transform(|range| {
335 let selection = doc.selection(view.id).transform(|range| {
@@ -208,7 +344,7 @@ pub fn move_line_start(cx: &mut Context) {
208 doc.set_selection(view.id, selection);
344 doc.set_selection(view.id, selection);
211−pub fn move_first_nonwhitespace(cx: &mut Context) {
347+fn move_first_nonwhitespace(cx: &mut Context) {
212 let (view, doc) = cx.current();
348 let (view, doc) = cx.current();
214 let selection = doc.selection(view.id).transform(|range| {
350 let selection = doc.selection(view.id).transform(|range| {
@@ -230,7 +366,7 @@ pub fn move_first_nonwhitespace(cx: &mut Context) {
230// Range::new(if Move { pos } if Extend { range.anchor }, pos)
366// Range::new(if Move { pos } if Extend { range.anchor }, pos)
231// since these all really do the same thing
367// since these all really do the same thing
233−pub fn move_next_word_start(cx: &mut Context) {
369+fn move_next_word_start(cx: &mut Context) {
234 let count = cx.count();
370 let count = cx.count();
235 let (view, doc) = cx.current();
371 let (view, doc) = cx.current();
236 let text = doc.text().slice(..);
372 let text = doc.text().slice(..);
@@ -242,7 +378,7 @@ pub fn move_next_word_start(cx: &mut Context) {
242 doc.set_selection(view.id, selection);
378 doc.set_selection(view.id, selection);
245−pub fn move_prev_word_start(cx: &mut Context) {
381+fn move_prev_word_start(cx: &mut Context) {
246 let count = cx.count();
382 let count = cx.count();
247 let (view, doc) = cx.current();
383 let (view, doc) = cx.current();
248 let text = doc.text().slice(..);
384 let text = doc.text().slice(..);
@@ -254,7 +390,7 @@ pub fn move_prev_word_start(cx: &mut Context) {
254 doc.set_selection(view.id, selection);
390 doc.set_selection(view.id, selection);
257−pub fn move_next_word_end(cx: &mut Context) {
393+fn move_next_word_end(cx: &mut Context) {
258 let count = cx.count();
394 let count = cx.count();
259 let (view, doc) = cx.current();
395 let (view, doc) = cx.current();
260 let text = doc.text().slice(..);
396 let text = doc.text().slice(..);
@@ -266,13 +402,13 @@ pub fn move_next_word_end(cx: &mut Context) {
266 doc.set_selection(view.id, selection);
402 doc.set_selection(view.id, selection);
269−pub fn move_file_start(cx: &mut Context) {
405+fn move_file_start(cx: &mut Context) {
270 push_jump(cx.editor);
406 push_jump(cx.editor);
271 let (view, doc) = cx.current();
407 let (view, doc) = cx.current();
272 doc.set_selection(view.id, Selection::point(0));
408 doc.set_selection(view.id, Selection::point(0));
275−pub fn move_file_end(cx: &mut Context) {
411+fn move_file_end(cx: &mut Context) {
276 push_jump(cx.editor);
412 push_jump(cx.editor);
277 let (view, doc) = cx.current();
413 let (view, doc) = cx.current();
278 let text = doc.text();
414 let text = doc.text();
@@ -280,7 +416,7 @@ pub fn move_file_end(cx: &mut Context) {
280 doc.set_selection(view.id, Selection::point(last_line));
416 doc.set_selection(view.id, Selection::point(last_line));
283−pub fn extend_next_word_start(cx: &mut Context) {
419+fn extend_next_word_start(cx: &mut Context) {
284 let count = cx.count();
420 let count = cx.count();
285 let (view, doc) = cx.current();
421 let (view, doc) = cx.current();
286 let text = doc.text().slice(..);
422 let text = doc.text().slice(..);
@@ -294,7 +430,7 @@ pub fn extend_next_word_start(cx: &mut Context) {
294 doc.set_selection(view.id, selection);
430 doc.set_selection(view.id, selection);
297−pub fn extend_prev_word_start(cx: &mut Context) {
433+fn extend_prev_word_start(cx: &mut Context) {
298 let count = cx.count();
434 let count = cx.count();
299 let (view, doc) = cx.current();
435 let (view, doc) = cx.current();
300 let text = doc.text().slice(..);
436 let text = doc.text().slice(..);
@@ -307,7 +443,7 @@ pub fn extend_prev_word_start(cx: &mut Context) {
307 doc.set_selection(view.id, selection);
443 doc.set_selection(view.id, selection);
310−pub fn extend_next_word_end(cx: &mut Context) {
446+fn extend_next_word_end(cx: &mut Context) {
311 let count = cx.count();
447 let count = cx.count();
312 let (view, doc) = cx.current();
448 let (view, doc) = cx.current();
313 let text = doc.text().slice(..);
449 let text = doc.text().slice(..);
@@ -365,7 +501,7 @@ where
368−pub fn find_till_char(cx: &mut Context) {
504+fn find_till_char(cx: &mut Context) {
369 find_char_impl(
505 find_char_impl(
371 search::find_nth_next,
507 search::find_nth_next,
@@ -374,7 +510,7 @@ pub fn find_till_char(cx: &mut Context) {
377−pub fn find_next_char(cx: &mut Context) {
513+fn find_next_char(cx: &mut Context) {
378 find_char_impl(
514 find_char_impl(
380 search::find_nth_next,
516 search::find_nth_next,
@@ -383,7 +519,7 @@ pub fn find_next_char(cx: &mut Context) {
386−pub fn extend_till_char(cx: &mut Context) {
522+fn extend_till_char(cx: &mut Context) {
387 find_char_impl(
523 find_char_impl(
389 search::find_nth_next,
525 search::find_nth_next,
@@ -392,7 +528,7 @@ pub fn extend_till_char(cx: &mut Context) {
395−pub fn extend_next_char(cx: &mut Context) {
531+fn extend_next_char(cx: &mut Context) {
396 find_char_impl(
532 find_char_impl(
398 search::find_nth_next,
534 search::find_nth_next,
@@ -401,7 +537,7 @@ pub fn extend_next_char(cx: &mut Context) {
404−pub fn till_prev_char(cx: &mut Context) {
540+fn till_prev_char(cx: &mut Context) {
405 find_char_impl(
541 find_char_impl(
407 search::find_nth_prev,
543 search::find_nth_prev,
@@ -410,7 +546,7 @@ pub fn till_prev_char(cx: &mut Context) {
413−pub fn find_prev_char(cx: &mut Context) {
549+fn find_prev_char(cx: &mut Context) {
414 find_char_impl(
550 find_char_impl(
416 search::find_nth_prev,
552 search::find_nth_prev,
@@ -419,7 +555,7 @@ pub fn find_prev_char(cx: &mut Context) {
422−pub fn extend_till_prev_char(cx: &mut Context) {
558+fn extend_till_prev_char(cx: &mut Context) {
423 find_char_impl(
559 find_char_impl(
425 search::find_nth_prev,
561 search::find_nth_prev,
@@ -428,7 +564,7 @@ pub fn extend_till_prev_char(cx: &mut Context) {
431−pub fn extend_prev_char(cx: &mut Context) {
567+fn extend_prev_char(cx: &mut Context) {
432 find_char_impl(
568 find_char_impl(
434 search::find_nth_prev,
570 search::find_nth_prev,
@@ -437,7 +573,7 @@ pub fn extend_prev_char(cx: &mut Context) {
440−pub fn extend_first_nonwhitespace(cx: &mut Context) {
576+fn extend_first_nonwhitespace(cx: &mut Context) {
441 let (view, doc) = cx.current();
577 let (view, doc) = cx.current();
443 let selection = doc.selection(view.id).transform(|range| {
579 let selection = doc.selection(view.id).transform(|range| {
@@ -455,7 +591,7 @@ pub fn extend_first_nonwhitespace(cx: &mut Context) {
455 doc.set_selection(view.id, selection);
591 doc.set_selection(view.id, selection);
458−pub fn replace(cx: &mut Context) {
594+fn replace(cx: &mut Context) {
459 // need to wait for next key
595 // need to wait for next key
460 cx.on_next_key(move |cx, event| {
596 cx.on_next_key(move |cx, event| {
461 let ch = match event {
597 let ch = match event {
@@ -535,31 +671,31 @@ fn scroll(cx: &mut Context, offset: usize, direction: Direction) {
535 doc.set_selection(view.id, Selection::point(pos));
671 doc.set_selection(view.id, Selection::point(pos));
538−pub fn page_up(cx: &mut Context) {
674+fn page_up(cx: &mut Context) {
539 let view = cx.view();
675 let view = cx.view();
540 let offset = view.area.height as usize;
676 let offset = view.area.height as usize;
541 scroll(cx, offset, Direction::Backward);
677 scroll(cx, offset, Direction::Backward);
544−pub fn page_down(cx: &mut Context) {
680+fn page_down(cx: &mut Context) {
545 let view = cx.view();
681 let view = cx.view();
546 let offset = view.area.height as usize;
682 let offset = view.area.height as usize;
547 scroll(cx, offset, Direction::Forward);
683 scroll(cx, offset, Direction::Forward);
550−pub fn half_page_up(cx: &mut Context) {
686+fn half_page_up(cx: &mut Context) {
551 let view = cx.view();
687 let view = cx.view();
552 let offset = view.area.height as usize / 2;
688 let offset = view.area.height as usize / 2;
553 scroll(cx, offset, Direction::Backward);
689 scroll(cx, offset, Direction::Backward);
556−pub fn half_page_down(cx: &mut Context) {
692+fn half_page_down(cx: &mut Context) {
557 let view = cx.view();
693 let view = cx.view();
558 let offset = view.area.height as usize / 2;
694 let offset = view.area.height as usize / 2;
559 scroll(cx, offset, Direction::Forward);
695 scroll(cx, offset, Direction::Forward);
562−pub fn extend_char_left(cx: &mut Context) {
698+fn extend_char_left(cx: &mut Context) {
563 let count = cx.count();
699 let count = cx.count();
564 let (view, doc) = cx.current();
700 let (view, doc) = cx.current();
565 let text = doc.text().slice(..);
701 let text = doc.text().slice(..);
@@ -569,7 +705,7 @@ pub fn extend_char_left(cx: &mut Context) {
569 doc.set_selection(view.id, selection);
705 doc.set_selection(view.id, selection);
572−pub fn extend_char_right(cx: &mut Context) {
708+fn extend_char_right(cx: &mut Context) {
573 let count = cx.count();
709 let count = cx.count();
574 let (view, doc) = cx.current();
710 let (view, doc) = cx.current();
575 let text = doc.text().slice(..);
711 let text = doc.text().slice(..);
@@ -579,7 +715,7 @@ pub fn extend_char_right(cx: &mut Context) {
579 doc.set_selection(view.id, selection);
715 doc.set_selection(view.id, selection);
582−pub fn extend_line_up(cx: &mut Context) {
718+fn extend_line_up(cx: &mut Context) {
583 let count = cx.count();
719 let count = cx.count();
584 let (view, doc) = cx.current();
720 let (view, doc) = cx.current();
585 let text = doc.text().slice(..);
721 let text = doc.text().slice(..);
@@ -589,7 +725,7 @@ pub fn extend_line_up(cx: &mut Context) {
589 doc.set_selection(view.id, selection);
725 doc.set_selection(view.id, selection);
592−pub fn extend_line_down(cx: &mut Context) {
728+fn extend_line_down(cx: &mut Context) {
593 let count = cx.count();
729 let count = cx.count();
594 let (view, doc) = cx.current();
730 let (view, doc) = cx.current();
595 let text = doc.text().slice(..);
731 let text = doc.text().slice(..);
@@ -599,7 +735,7 @@ pub fn extend_line_down(cx: &mut Context) {
599 doc.set_selection(view.id, selection);
735 doc.set_selection(view.id, selection);
602−pub fn extend_line_end(cx: &mut Context) {
738+fn extend_line_end(cx: &mut Context) {
603 let (view, doc) = cx.current();
739 let (view, doc) = cx.current();
605 let selection = doc.selection(view.id).transform(|range| {
741 let selection = doc.selection(view.id).transform(|range| {
@@ -615,7 +751,7 @@ pub fn extend_line_end(cx: &mut Context) {
615 doc.set_selection(view.id, selection);
751 doc.set_selection(view.id, selection);
618−pub fn extend_line_start(cx: &mut Context) {
754+fn extend_line_start(cx: &mut Context) {
619 let (view, doc) = cx.current();
755 let (view, doc) = cx.current();
621 let selection = doc.selection(view.id).transform(|range| {
757 let selection = doc.selection(view.id).transform(|range| {
@@ -630,14 +766,14 @@ pub fn extend_line_start(cx: &mut Context) {
630 doc.set_selection(view.id, selection);
766 doc.set_selection(view.id, selection);
633−pub fn select_all(cx: &mut Context) {
769+fn select_all(cx: &mut Context) {
634 let (view, doc) = cx.current();
770 let (view, doc) = cx.current();
636 let end = doc.text().len_chars().saturating_sub(1);
772 let end = doc.text().len_chars().saturating_sub(1);
637 doc.set_selection(view.id, Selection::single(0, end))
773 doc.set_selection(view.id, Selection::single(0, end))
640−pub fn select_regex(cx: &mut Context) {
776+fn select_regex(cx: &mut Context) {
641 let prompt = ui::regex_prompt(cx, "select:".to_string(), move |view, doc, _, regex| {
777 let prompt = ui::regex_prompt(cx, "select:".to_string(), move |view, doc, _, regex| {
642 let text = doc.text().slice(..);
778 let text = doc.text().slice(..);
643 if let Some(selection) = selection::select_on_matches(text, doc.selection(view.id), ®ex)
779 if let Some(selection) = selection::select_on_matches(text, doc.selection(view.id), ®ex)
@@ -649,7 +785,7 @@ pub fn select_regex(cx: &mut Context) {
649 cx.push_layer(Box::new(prompt));
785 cx.push_layer(Box::new(prompt));
652−pub fn split_selection(cx: &mut Context) {
788+fn split_selection(cx: &mut Context) {
653 let prompt = ui::regex_prompt(cx, "split:".to_string(), move |view, doc, _, regex| {
789 let prompt = ui::regex_prompt(cx, "split:".to_string(), move |view, doc, _, regex| {
654 let text = doc.text().slice(..);
790 let text = doc.text().slice(..);
655 let selection = selection::split_on_matches(text, doc.selection(view.id), ®ex);
791 let selection = selection::split_on_matches(text, doc.selection(view.id), ®ex);
@@ -659,7 +795,7 @@ pub fn split_selection(cx: &mut Context) {
659 cx.push_layer(Box::new(prompt));
795 cx.push_layer(Box::new(prompt));
662−pub fn split_selection_on_newline(cx: &mut Context) {
798+fn split_selection_on_newline(cx: &mut Context) {
663 let (view, doc) = cx.current();
799 let (view, doc) = cx.current();
664 let text = doc.text().slice(..);
800 let text = doc.text().slice(..);
665 // only compile the regex once
801 // only compile the regex once
@@ -711,7 +847,7 @@ fn search_impl(doc: &mut Document, view: &mut View, contents: &str, regex: &Rege
713// TODO: use one function for search vs extend
849// TODO: use one function for search vs extend
714−pub fn search(cx: &mut Context) {
850+fn search(cx: &mut Context) {
715 let (view, doc) = cx.current();
851 let (view, doc) = cx.current();
717 // TODO: could probably share with select_on_matches?
853 // TODO: could probably share with select_on_matches?
@@ -733,9 +869,8 @@ pub fn search(cx: &mut Context) {
734 cx.push_layer(Box::new(prompt));
870 cx.push_layer(Box::new(prompt));
736−// can't search next for ""compose"" for some reason
738−pub fn search_next_impl(cx: &mut Context, extend: bool) {
873+fn search_next_impl(cx: &mut Context, extend: bool) {
739 let (view, doc, registers) = cx.current_with_registers();
874 let (view, doc, registers) = cx.current_with_registers();
740 if let Some(query) = registers.read('\\') {
875 if let Some(query) = registers.read('\\') {
741 let query = query.first().unwrap();
876 let query = query.first().unwrap();
@@ -745,15 +880,15 @@ pub fn search_next_impl(cx: &mut Context, extend: bool) {
748−pub fn search_next(cx: &mut Context) {
883+fn search_next(cx: &mut Context) {
749 search_next_impl(cx, false);
884 search_next_impl(cx, false);
752−pub fn extend_search_next(cx: &mut Context) {
887+fn extend_search_next(cx: &mut Context) {
753 search_next_impl(cx, true);
888 search_next_impl(cx, true);
756−pub fn search_selection(cx: &mut Context) {
891+fn search_selection(cx: &mut Context) {
757 let (view, doc) = cx.current();
892 let (view, doc) = cx.current();
758 let contents = doc.text().slice(..);
893 let contents = doc.text().slice(..);
759 let query = doc.selection(view.id).primary().fragment(contents);
894 let query = doc.selection(view.id).primary().fragment(contents);
@@ -768,7 +903,7 @@ pub fn search_selection(cx: &mut Context) {
771−pub fn select_line(cx: &mut Context) {
906+fn select_line(cx: &mut Context) {
772 let count = cx.count();
907 let count = cx.count();
773 let (view, doc) = cx.current();
908 let (view, doc) = cx.current();
@@ -783,7 +918,7 @@ pub fn select_line(cx: &mut Context) {
784 doc.set_selection(view.id, Selection::single(start, end));
919 doc.set_selection(view.id, Selection::single(start, end));
786−pub fn extend_line(cx: &mut Context) {
921+fn extend_line(cx: &mut Context) {
787 let count = cx.count();
922 let count = cx.count();
788 let (view, doc) = cx.current();
923 let (view, doc) = cx.current();
@@ -825,7 +960,7 @@ fn delete_selection_impl(reg: &mut Register, doc: &mut Document, view_id: ViewId
825 doc.apply(&transaction, view_id);
960 doc.apply(&transaction, view_id);
828−pub fn delete_selection(cx: &mut Context) {
963+fn delete_selection(cx: &mut Context) {
829 let reg_name = cx.selected_register.name();
964 let reg_name = cx.selected_register.name();
830 let (view, doc, registers) = cx.current_with_registers();
965 let (view, doc, registers) = cx.current_with_registers();
831 let reg = registers.get_or_insert(reg_name);
966 let reg = registers.get_or_insert(reg_name);
@@ -837,7 +972,7 @@ pub fn delete_selection(cx: &mut Context) {
837 exit_select_mode(cx);
972 exit_select_mode(cx);
840−pub fn change_selection(cx: &mut Context) {
975+fn change_selection(cx: &mut Context) {
841 let reg_name = cx.selected_register.name();
976 let reg_name = cx.selected_register.name();
842 let (view, doc, registers) = cx.current_with_registers();
977 let (view, doc, registers) = cx.current_with_registers();
843 let reg = registers.get_or_insert(reg_name);
978 let reg = registers.get_or_insert(reg_name);
@@ -845,7 +980,7 @@ pub fn change_selection(cx: &mut Context) {
845 enter_insert_mode(doc);
980 enter_insert_mode(doc);
848−pub fn collapse_selection(cx: &mut Context) {
983+fn collapse_selection(cx: &mut Context) {
849 let (view, doc) = cx.current();
984 let (view, doc) = cx.current();
850 let selection = doc
985 let selection = doc
851 .selection(view.id)
986 .selection(view.id)
@@ -854,7 +989,7 @@ pub fn collapse_selection(cx: &mut Context) {
854 doc.set_selection(view.id, selection);
989 doc.set_selection(view.id, selection);
857−pub fn flip_selections(cx: &mut Context) {
992+fn flip_selections(cx: &mut Context) {
858 let (view, doc) = cx.current();
993 let (view, doc) = cx.current();
859 let selection = doc
994 let selection = doc
860 .selection(view.id)
995 .selection(view.id)
@@ -868,7 +1003,7 @@ fn enter_insert_mode(doc: &mut Document) {
870// inserts at the start of each selection
1005// inserts at the start of each selection
871−pub fn insert_mode(cx: &mut Context) {
1006+fn insert_mode(cx: &mut Context) {
872 let (view, doc) = cx.current();
1007 let (view, doc) = cx.current();
873 enter_insert_mode(doc);
1008 enter_insert_mode(doc);
@@ -879,7 +1014,7 @@ pub fn insert_mode(cx: &mut Context) {
881// inserts at the end of each selection
1016// inserts at the end of each selection
882−pub fn append_mode(cx: &mut Context) {
1017+fn append_mode(cx: &mut Context) {
883 let (view, doc) = cx.current();
1018 let (view, doc) = cx.current();
884 enter_insert_mode(doc);
1019 enter_insert_mode(doc);
885 doc.restore_cursor = true;
1020 doc.restore_cursor = true;
@@ -913,7 +1048,7 @@ mod cmd {
913 use ui::completers::{self, Completer};
1048 use ui::completers::{self, Completer};
915 #[derive(Clone)]
1050 #[derive(Clone)]
916− pub struct Command {
1051+ pub struct TypableCommand {
917 pub name: &'static str,
1052 pub name: &'static str,
918 pub alias: Option<&'static str>,
1053 pub alias: Option<&'static str>,
919 pub doc: &'static str,
1054 pub doc: &'static str,
@@ -1152,113 +1287,113 @@ mod cmd {
1152 quit_all_impl(editor, args, event, true)
1287 quit_all_impl(editor, args, event, true)
1155− pub const COMMAND_LIST: &[Command] = &[
1290+ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
1156− Command {
1291+ TypableCommand {
1157 name: "quit",
1292 name: "quit",
1158 alias: Some("q"),
1293 alias: Some("q"),
1159 doc: "Close the current view.",
1294 doc: "Close the current view.",
1160 fun: quit,
1295 fun: quit,
1161 completer: None,
1296 completer: None,
1163− Command {
1298+ TypableCommand {
1164 name: "quit!",
1299 name: "quit!",
1165 alias: Some("q!"),
1300 alias: Some("q!"),
1166 doc: "Close the current view.",
1301 doc: "Close the current view.",
1167 fun: force_quit,
1302 fun: force_quit,
1168 completer: None,
1303 completer: None,
1170− Command {
1305+ TypableCommand {
1171 name: "open",
1306 name: "open",
1172 alias: Some("o"),
1307 alias: Some("o"),
1173 doc: "Open a file from disk into the current view.",
1308 doc: "Open a file from disk into the current view.",
1174 fun: open,
1309 fun: open,
1175 completer: Some(completers::filename),
1310 completer: Some(completers::filename),
1177− Command {
1312+ TypableCommand {
1178 name: "write",
1313 name: "write",
1179 alias: Some("w"),
1314 alias: Some("w"),
1180 doc: "Write changes to disk. Accepts an optional path (:write some/path.txt)",
1315 doc: "Write changes to disk. Accepts an optional path (:write some/path.txt)",
1181 fun: write,
1316 fun: write,
1182 completer: Some(completers::filename),
1317 completer: Some(completers::filename),
1184− Command {
1319+ TypableCommand {
1185 name: "new",
1320 name: "new",
1186 alias: Some("n"),
1321 alias: Some("n"),
1187 doc: "Create a new scratch buffer.",
1322 doc: "Create a new scratch buffer.",
1188 fun: new_file,
1323 fun: new_file,
1189 completer: Some(completers::filename),
1324 completer: Some(completers::filename),
1191− Command {
1326+ TypableCommand {
1192 name: "format",
1327 name: "format",
1193 alias: Some("fmt"),
1328 alias: Some("fmt"),
1194 doc: "Format the file using a formatter.",
1329 doc: "Format the file using a formatter.",
1195 fun: format,
1330 fun: format,
1196 completer: None,
1331 completer: None,
1198− Command {
1333+ TypableCommand {
1199 name: "indent-style",
1334 name: "indent-style",
1200 alias: None,
1335 alias: None,
1201 doc: "Set the indentation style for editing. ('t' for tabs or 1-8 for number of spaces.)",
1336 doc: "Set the indentation style for editing. ('t' for tabs or 1-8 for number of spaces.)",
1202 fun: set_indent_style,
1337 fun: set_indent_style,
1203 completer: None,
1338 completer: None,
1205− Command {
1340+ TypableCommand {
1206 name: "earlier",
1341 name: "earlier",
1207 alias: Some("ear"),
1342 alias: Some("ear"),
1208 doc: "Jump back to an earlier point in edit history. Accepts a number of steps or a time span.",
1343 doc: "Jump back to an earlier point in edit history. Accepts a number of steps or a time span.",
1209 fun: earlier,
1344 fun: earlier,
1210 completer: None,
1345 completer: None,
1212− Command {
1347+ TypableCommand {
1213 name: "later",
1348 name: "later",
1214 alias: Some("lat"),
1349 alias: Some("lat"),
1215 doc: "Jump to a later point in edit history. Accepts a number of steps or a time span.",
1350 doc: "Jump to a later point in edit history. Accepts a number of steps or a time span.",
1216 fun: later,
1351 fun: later,
1217 completer: None,
1352 completer: None,
1219− Command {
1354+ TypableCommand {
1220 name: "write-quit",
1355 name: "write-quit",
1221 alias: Some("wq"),
1356 alias: Some("wq"),
1222 doc: "Writes changes to disk and closes the current view. Accepts an optional path (:wq some/path.txt)",
1357 doc: "Writes changes to disk and closes the current view. Accepts an optional path (:wq some/path.txt)",
1223 fun: write_quit,
1358 fun: write_quit,
1224 completer: Some(completers::filename),
1359 completer: Some(completers::filename),
1226− Command {
1361+ TypableCommand {
1227 name: "write-quit!",
1362 name: "write-quit!",
1228 alias: Some("wq!"),
1363 alias: Some("wq!"),
1229 doc: "Writes changes to disk and closes the current view forcefully. Accepts an optional path (:wq! some/path.txt)",
1364 doc: "Writes changes to disk and closes the current view forcefully. Accepts an optional path (:wq! some/path.txt)",
1230 fun: force_write_quit,
1365 fun: force_write_quit,
1231 completer: Some(completers::filename),
1366 completer: Some(completers::filename),
1233− Command {
1368+ TypableCommand {
1234 name: "write-all",
1369 name: "write-all",
1235 alias: Some("wa"),
1370 alias: Some("wa"),
1236 doc: "Writes changes from all views to disk.",
1371 doc: "Writes changes from all views to disk.",
1237 fun: write_all,
1372 fun: write_all,
1238 completer: None,
1373 completer: None,
1240− Command {
1375+ TypableCommand {
1241 name: "write-quit-all",
1376 name: "write-quit-all",
1242 alias: Some("wqa"),
1377 alias: Some("wqa"),
1243 doc: "Writes changes from all views to disk and close all views.",
1378 doc: "Writes changes from all views to disk and close all views.",
1244 fun: write_all_quit,
1379 fun: write_all_quit,
1245 completer: None,
1380 completer: None,
1247− Command {
1382+ TypableCommand {
1248 name: "write-quit-all!",
1383 name: "write-quit-all!",
1249 alias: Some("wqa!"),
1384 alias: Some("wqa!"),
1250 doc: "Writes changes from all views to disk and close all views forcefully (ignoring unsaved changes).",
1385 doc: "Writes changes from all views to disk and close all views forcefully (ignoring unsaved changes).",
1251 fun: force_write_all_quit,
1386 fun: force_write_all_quit,
1252 completer: None,
1387 completer: None,
1254− Command {
1389+ TypableCommand {
1255 name: "quit-all",
1390 name: "quit-all",
1256 alias: Some("qa"),
1391 alias: Some("qa"),
1257 doc: "Close all views.",
1392 doc: "Close all views.",
1258 fun: quit_all,
1393 fun: quit_all,
1259 completer: None,
1394 completer: None,
1261− Command {
1396+ TypableCommand {
1262 name: "quit-all!",
1397 name: "quit-all!",
1263 alias: Some("qa!"),
1398 alias: Some("qa!"),
1264 doc: "Close all views forcefully (ignoring unsaved changes).",
1399 doc: "Close all views forcefully (ignoring unsaved changes).",
@@ -1268,10 +1403,10 @@ mod cmd {
1271− pub static COMMANDS: Lazy<HashMap<&'static str, &'static Command>> = Lazy::new(|| {
1406+ pub static COMMANDS: Lazy<HashMap<&'static str, &'static TypableCommand>> = Lazy::new(|| {
1272 let mut map = HashMap::new();
1407 let mut map = HashMap::new();
1274− for cmd in COMMAND_LIST {
1409+ for cmd in TYPABLE_COMMAND_LIST {
1275 map.insert(cmd.name, cmd);
1410 map.insert(cmd.name, cmd);
1276 if let Some(alias) = cmd.alias {
1411 if let Some(alias) = cmd.alias {
1277 map.insert(alias, cmd);
1412 map.insert(alias, cmd);
@@ -1282,7 +1417,7 @@ mod cmd {
1285−pub fn command_mode(cx: &mut Context) {
1420+fn command_mode(cx: &mut Context) {
1286 // TODO: completion items should have a info section that would get displayed in
1421 // TODO: completion items should have a info section that would get displayed in
1287 // a popup above the prompt when items are tabbed over
1422 // a popup above the prompt when items are tabbed over
@@ -1297,7 +1432,7 @@ pub fn command_mode(cx: &mut Context) {
1297 if parts.len() <= 1 {
1432 if parts.len() <= 1 {
1298 use std::{borrow::Cow, ops::Range};
1433 use std::{borrow::Cow, ops::Range};
1299 let end = 0..;
1434 let end = 0..;
1300− cmd::COMMAND_LIST
1435+ cmd::TYPABLE_COMMAND_LIST
1302 .filter(|command| command.name.contains(input))
1437 .filter(|command| command.name.contains(input))
1303 .map(|command| (end.clone(), Cow::Borrowed(command.name)))
1438 .map(|command| (end.clone(), Cow::Borrowed(command.name)))
@@ -1305,7 +1440,7 @@ pub fn command_mode(cx: &mut Context) {
1305 } else {
1440 } else {
1306 let part = parts.last().unwrap();
1441 let part = parts.last().unwrap();
1308− if let Some(cmd::Command {
1443+ if let Some(cmd::TypableCommand {
1309 completer: Some(completer),
1444 completer: Some(completer),
1311 }) = cmd::COMMANDS.get(parts[0])
1446 }) = cmd::COMMANDS.get(parts[0])
@@ -1346,7 +1481,7 @@ pub fn command_mode(cx: &mut Context) {
1346 prompt.doc_fn = Box::new(|input: &str| {
1481 prompt.doc_fn = Box::new(|input: &str| {
1347 let part = input.split(' ').next().unwrap_or_default();
1482 let part = input.split(' ').next().unwrap_or_default();
1349− if let Some(cmd::Command { doc, .. }) = cmd::COMMANDS.get(part) {
1484+ if let Some(cmd::TypableCommand { doc, .. }) = cmd::COMMANDS.get(part) {
1350 return Some(doc);
1485 return Some(doc);
@@ -1356,13 +1491,13 @@ pub fn command_mode(cx: &mut Context) {
1356 cx.push_layer(Box::new(prompt));
1491 cx.push_layer(Box::new(prompt));
1359−pub fn file_picker(cx: &mut Context) {
1494+fn file_picker(cx: &mut Context) {
1360 let root = find_root(None).unwrap_or_else(|| PathBuf::from("./"));
1495 let root = find_root(None).unwrap_or_else(|| PathBuf::from("./"));
1361 let picker = ui::file_picker(root);
1496 let picker = ui::file_picker(root);
1362 cx.push_layer(Box::new(picker));
1497 cx.push_layer(Box::new(picker));
1365−pub fn buffer_picker(cx: &mut Context) {
1500+fn buffer_picker(cx: &mut Context) {
1366 use std::path::{Path, PathBuf};
1501 use std::path::{Path, PathBuf};
1367 let current = cx.editor.view().doc;
1502 let current = cx.editor.view().doc;
@@ -1393,7 +1528,7 @@ pub fn buffer_picker(cx: &mut Context) {
1393 cx.push_layer(Box::new(picker));
1528 cx.push_layer(Box::new(picker));
1396−pub fn symbol_picker(cx: &mut Context) {
1531+fn symbol_picker(cx: &mut Context) {
1397 fn nested_to_flat(
1532 fn nested_to_flat(
1398 list: &mut Vec<lsp::SymbolInformation>,
1533 list: &mut Vec<lsp::SymbolInformation>,
1399 file: &lsp::TextDocumentIdentifier,
1534 file: &lsp::TextDocumentIdentifier,
@@ -1464,14 +1599,14 @@ pub fn symbol_picker(cx: &mut Context) {
1466// I inserts at the first nonwhitespace character of each line with a selection
1601// I inserts at the first nonwhitespace character of each line with a selection
1467−pub fn prepend_to_line(cx: &mut Context) {
1602+fn prepend_to_line(cx: &mut Context) {
1468 move_first_nonwhitespace(cx);
1603 move_first_nonwhitespace(cx);
1469 let doc = cx.doc();
1604 let doc = cx.doc();
1470 enter_insert_mode(doc);
1605 enter_insert_mode(doc);
1473// A inserts at the end of each line with a selection
1608// A inserts at the end of each line with a selection
1474−pub fn append_to_line(cx: &mut Context) {
1609+fn append_to_line(cx: &mut Context) {
1475 let (view, doc) = cx.current();
1610 let (view, doc) = cx.current();
1476 enter_insert_mode(doc);
1611 enter_insert_mode(doc);
@@ -1550,16 +1685,16 @@ fn open(cx: &mut Context, open: Open) {
1552// o inserts a new line after each line with a selection
1687// o inserts a new line after each line with a selection
1553−pub fn open_below(cx: &mut Context) {
1688+fn open_below(cx: &mut Context) {
1554 open(cx, Open::Below)
1689 open(cx, Open::Below)
1557// O inserts a new line before each line with a selection
1692// O inserts a new line before each line with a selection
1558−pub fn open_above(cx: &mut Context) {
1693+fn open_above(cx: &mut Context) {
1559 open(cx, Open::Above)
1694 open(cx, Open::Above)
1562−pub fn normal_mode(cx: &mut Context) {
1697+fn normal_mode(cx: &mut Context) {
1563 let (view, doc) = cx.current();
1698 let (view, doc) = cx.current();
1565 doc.mode = Mode::Normal;
1700 doc.mode = Mode::Normal;
@@ -1597,7 +1732,7 @@ fn switch_to_last_accessed_file(cx: &mut Context) {
1600−pub fn goto_mode(cx: &mut Context) {
1735+fn goto_mode(cx: &mut Context) {
1601 if let Some(count) = cx.count {
1736 if let Some(count) = cx.count {
1602 push_jump(cx.editor);
1737 push_jump(cx.editor);
@@ -1658,11 +1793,11 @@ pub fn goto_mode(cx: &mut Context) {
1661−pub fn select_mode(cx: &mut Context) {
1796+fn select_mode(cx: &mut Context) {
1662 cx.doc().mode = Mode::Select;
1797 cx.doc().mode = Mode::Select;
1665−pub fn exit_select_mode(cx: &mut Context) {
1800+fn exit_select_mode(cx: &mut Context) {
1666 cx.doc().mode = Mode::Normal;
1801 cx.doc().mode = Mode::Normal;
@@ -1722,7 +1857,7 @@ fn goto_impl(
1725−pub fn goto_definition(cx: &mut Context) {
1860+fn goto_definition(cx: &mut Context) {
1726 let (view, doc) = cx.current();
1861 let (view, doc) = cx.current();
1727 let language_server = match doc.language_server() {
1862 let language_server = match doc.language_server() {
1728 Some(language_server) => language_server,
1863 Some(language_server) => language_server,
@@ -1759,7 +1894,7 @@ pub fn goto_definition(cx: &mut Context) {
1762−pub fn goto_type_definition(cx: &mut Context) {
1897+fn goto_type_definition(cx: &mut Context) {
1763 let (view, doc) = cx.current();
1898 let (view, doc) = cx.current();
1764 let language_server = match doc.language_server() {
1899 let language_server = match doc.language_server() {
1765 Some(language_server) => language_server,
1900 Some(language_server) => language_server,
@@ -1796,7 +1931,7 @@ pub fn goto_type_definition(cx: &mut Context) {
1799−pub fn goto_implementation(cx: &mut Context) {
1934+fn goto_implementation(cx: &mut Context) {
1800 let (view, doc) = cx.current();
1935 let (view, doc) = cx.current();
1801 let language_server = match doc.language_server() {
1936 let language_server = match doc.language_server() {
1802 Some(language_server) => language_server,
1937 Some(language_server) => language_server,
@@ -1833,7 +1968,7 @@ pub fn goto_implementation(cx: &mut Context) {
1836−pub fn goto_reference(cx: &mut Context) {
1971+fn goto_reference(cx: &mut Context) {
1837 let (view, doc) = cx.current();
1972 let (view, doc) = cx.current();
1838 let language_server = match doc.language_server() {
1973 let language_server = match doc.language_server() {
1839 Some(language_server) => language_server,
1974 Some(language_server) => language_server,
@@ -1871,7 +2006,7 @@ fn goto_pos(editor: &mut Editor, pos: usize) {
1871 align_view(doc, view, Align::Center);
2006 align_view(doc, view, Align::Center);
1874−pub fn goto_first_diag(cx: &mut Context) {
2009+fn goto_first_diag(cx: &mut Context) {
1875 let editor = &mut cx.editor;
2010 let editor = &mut cx.editor;
1876 let (view, doc) = editor.current();
2011 let (view, doc) = editor.current();
@@ -1885,7 +2020,7 @@ pub fn goto_first_diag(cx: &mut Context) {
1885 goto_pos(editor, diag);
2020 goto_pos(editor, diag);
1888−pub fn goto_last_diag(cx: &mut Context) {
2023+fn goto_last_diag(cx: &mut Context) {
1889 let editor = &mut cx.editor;
2024 let editor = &mut cx.editor;
1890 let (view, doc) = editor.current();
2025 let (view, doc) = editor.current();
@@ -1899,7 +2034,7 @@ pub fn goto_last_diag(cx: &mut Context) {
1899 goto_pos(editor, diag);
2034 goto_pos(editor, diag);
1902−pub fn goto_next_diag(cx: &mut Context) {
2037+fn goto_next_diag(cx: &mut Context) {
1903 let editor = &mut cx.editor;
2038 let editor = &mut cx.editor;
1904 let (view, doc) = editor.current();
2039 let (view, doc) = editor.current();
@@ -1920,7 +2055,7 @@ pub fn goto_next_diag(cx: &mut Context) {
1920 goto_pos(editor, diag);
2055 goto_pos(editor, diag);
1923−pub fn goto_prev_diag(cx: &mut Context) {
2058+fn goto_prev_diag(cx: &mut Context) {
1924 let editor = &mut cx.editor;
2059 let editor = &mut cx.editor;
1925 let (view, doc) = editor.current();
2060 let (view, doc) = editor.current();
@@ -1942,7 +2077,7 @@ pub fn goto_prev_diag(cx: &mut Context) {
1942 goto_pos(editor, diag);
2077 goto_pos(editor, diag);
1945−pub fn signature_help(cx: &mut Context) {
2080+fn signature_help(cx: &mut Context) {
1946 let (view, doc) = cx.current();
2081 let (view, doc) = cx.current();
1948 let language_server = match doc.language_server() {
2083 let language_server = match doc.language_server() {
@@ -2218,19 +2353,19 @@ pub mod insert {
2218// TODO: each command could simply return a Option<transaction>, then the higher level handles
2353// TODO: each command could simply return a Option<transaction>, then the higher level handles
2219// storing it?
2354// storing it?
2221−pub fn undo(cx: &mut Context) {
2356+fn undo(cx: &mut Context) {
2222 let view_id = cx.view().id;
2357 let view_id = cx.view().id;
2223 cx.doc().undo(view_id);
2358 cx.doc().undo(view_id);
2226−pub fn redo(cx: &mut Context) {
2361+fn redo(cx: &mut Context) {
2227 let view_id = cx.view().id;
2362 let view_id = cx.view().id;
2228 cx.doc().redo(view_id);
2363 cx.doc().redo(view_id);
2231// Yank / Paste
2366// Yank / Paste
2233−pub fn yank(cx: &mut Context) {
2368+fn yank(cx: &mut Context) {
2234 // TODO: should selections be made end inclusive?
2369 // TODO: should selections be made end inclusive?
2235 let (view, doc) = cx.current();
2370 let (view, doc) = cx.current();
2236 let values: Vec<String> = doc
2371 let values: Vec<String> = doc
@@ -2295,7 +2430,7 @@ fn paste_impl(
2295 Some(transaction)
2430 Some(transaction)
2298−pub fn replace_with_yanked(cx: &mut Context) {
2433+fn replace_with_yanked(cx: &mut Context) {
2299 let reg_name = cx.selected_register.name();
2434 let reg_name = cx.selected_register.name();
2300 let (view, doc, registers) = cx.current_with_registers();
2435 let (view, doc, registers) = cx.current_with_registers();
@@ -2324,7 +2459,7 @@ pub fn replace_with_yanked(cx: &mut Context) {
2324// replace => replace
2459// replace => replace
2325// default insert
2460// default insert
2327−pub fn paste_after(cx: &mut Context) {
2462+fn paste_after(cx: &mut Context) {
2328 let reg_name = cx.selected_register.name();
2463 let reg_name = cx.selected_register.name();
2329 let (view, doc, registers) = cx.current_with_registers();
2464 let (view, doc, registers) = cx.current_with_registers();
@@ -2337,7 +2472,7 @@ pub fn paste_after(cx: &mut Context) {
2340−pub fn paste_before(cx: &mut Context) {
2475+fn paste_before(cx: &mut Context) {
2341 let reg_name = cx.selected_register.name();
2476 let reg_name = cx.selected_register.name();
2342 let (view, doc, registers) = cx.current_with_registers();
2477 let (view, doc, registers) = cx.current_with_registers();
@@ -2367,7 +2502,7 @@ fn get_lines(doc: &Document, view_id: ViewId) -> Vec<usize> {
2370−pub fn indent(cx: &mut Context) {
2505+fn indent(cx: &mut Context) {
2371 let count = cx.count();
2506 let count = cx.count();
2372 let (view, doc) = cx.current();
2507 let (view, doc) = cx.current();
2373 let lines = get_lines(doc, view.id);
2508 let lines = get_lines(doc, view.id);
@@ -2386,7 +2521,7 @@ pub fn indent(cx: &mut Context) {
2386 doc.append_changes_to_history(view.id);
2521 doc.append_changes_to_history(view.id);
2389−pub fn unindent(cx: &mut Context) {
2524+fn unindent(cx: &mut Context) {
2390 let count = cx.count();
2525 let count = cx.count();
2391 let (view, doc) = cx.current();
2526 let (view, doc) = cx.current();
2392 let lines = get_lines(doc, view.id);
2527 let lines = get_lines(doc, view.id);
@@ -2426,7 +2561,7 @@ pub fn unindent(cx: &mut Context) {
2426 doc.append_changes_to_history(view.id);
2561 doc.append_changes_to_history(view.id);
2429−pub fn format_selections(cx: &mut Context) {
2564+fn format_selections(cx: &mut Context) {
2430 let (view, doc) = cx.current();
2565 let (view, doc) = cx.current();
2432 // via lsp if available
2567 // via lsp if available
@@ -2472,7 +2607,7 @@ pub fn format_selections(cx: &mut Context) {
2472 doc.append_changes_to_history(view.id);
2607 doc.append_changes_to_history(view.id);
2475−pub fn join_selections(cx: &mut Context) {
2610+fn join_selections(cx: &mut Context) {
2476 use movement::skip_while;
2611 use movement::skip_while;
2477 let (view, doc) = cx.current();
2612 let (view, doc) = cx.current();
2478 let text = doc.text();
2613 let text = doc.text();
@@ -2516,7 +2651,7 @@ pub fn join_selections(cx: &mut Context) {
2516 doc.append_changes_to_history(view.id);
2651 doc.append_changes_to_history(view.id);
2519−pub fn keep_selections(cx: &mut Context) {
2654+fn keep_selections(cx: &mut Context) {
2520 // keep selections matching regex
2655 // keep selections matching regex
2521 let prompt = ui::regex_prompt(cx, "keep:".to_string(), move |view, doc, _, regex| {
2656 let prompt = ui::regex_prompt(cx, "keep:".to_string(), move |view, doc, _, regex| {
2522 let text = doc.text().slice(..);
2657 let text = doc.text().slice(..);
@@ -2529,7 +2664,7 @@ pub fn keep_selections(cx: &mut Context) {
2529 cx.push_layer(Box::new(prompt));
2664 cx.push_layer(Box::new(prompt));
2532−pub fn keep_primary_selection(cx: &mut Context) {
2667+fn keep_primary_selection(cx: &mut Context) {
2533 let (view, doc) = cx.current();
2668 let (view, doc) = cx.current();
2535 let range = doc.selection(view.id).primary();
2670 let range = doc.selection(view.id).primary();
@@ -2539,14 +2674,14 @@ pub fn keep_primary_selection(cx: &mut Context) {
2542−pub fn save(cx: &mut Context) {
2677+fn save(cx: &mut Context) {
2543 // Spawns an async task to actually do the saving. This way we prevent blocking.
2678 // Spawns an async task to actually do the saving. This way we prevent blocking.
2545 // TODO: handle save errors somehow?
2680 // TODO: handle save errors somehow?
2546 tokio::spawn(cx.doc().save());
2681 tokio::spawn(cx.doc().save());
2549−pub fn completion(cx: &mut Context) {
2684+fn completion(cx: &mut Context) {
2550 // trigger on trigger char, or if user calls it
2685 // trigger on trigger char, or if user calls it
2551 // (or on word char typing??)
2686 // (or on word char typing??)
2552 // after it's triggered, if response marked is_incomplete, update on every subsequent keypress
2687 // after it's triggered, if response marked is_incomplete, update on every subsequent keypress
@@ -2636,7 +2771,7 @@ pub fn completion(cx: &mut Context) {
2639−pub fn hover(cx: &mut Context) {
2774+fn hover(cx: &mut Context) {
2640 let (view, doc) = cx.current();
2775 let (view, doc) = cx.current();
2642 let language_server = match doc.language_server() {
2777 let language_server = match doc.language_server() {
@@ -2686,7 +2821,7 @@ pub fn hover(cx: &mut Context) {
2688// comments
2823// comments
2689−pub fn toggle_comments(cx: &mut Context) {
2824+fn toggle_comments(cx: &mut Context) {
2690 let (view, doc) = cx.current();
2825 let (view, doc) = cx.current();
2691 let transaction = comment::toggle_line_comments(doc.text(), doc.selection(view.id));
2826 let transaction = comment::toggle_line_comments(doc.text(), doc.selection(view.id));
@@ -2696,7 +2831,7 @@ pub fn toggle_comments(cx: &mut Context) {
2697// tree sitter node selection
2832// tree sitter node selection
2699−pub fn expand_selection(cx: &mut Context) {
2834+fn expand_selection(cx: &mut Context) {
2700 let (view, doc) = cx.current();
2835 let (view, doc) = cx.current();
2702 if let Some(syntax) = doc.syntax() {
2837 if let Some(syntax) = doc.syntax() {
@@ -2706,7 +2841,7 @@ pub fn expand_selection(cx: &mut Context) {
2709−pub fn match_brackets(cx: &mut Context) {
2844+fn match_brackets(cx: &mut Context) {
2710 let (view, doc) = cx.current();
2845 let (view, doc) = cx.current();
2712 if let Some(syntax) = doc.syntax() {
2847 if let Some(syntax) = doc.syntax() {
@@ -2720,7 +2855,7 @@ pub fn match_brackets(cx: &mut Context) {
2723−pub fn jump_forward(cx: &mut Context) {
2858+fn jump_forward(cx: &mut Context) {
2724 let count = cx.count();
2859 let count = cx.count();
2725 let (view, doc) = cx.current();
2860 let (view, doc) = cx.current();
@@ -2734,7 +2869,7 @@ pub fn jump_forward(cx: &mut Context) {
2737−pub fn jump_backward(cx: &mut Context) {
2872+fn jump_backward(cx: &mut Context) {
2738 let count = cx.count();
2873 let count = cx.count();
2739 let (view, doc) = cx.current();
2874 let (view, doc) = cx.current();
@@ -2752,7 +2887,7 @@ pub fn jump_backward(cx: &mut Context) {
2755−pub fn window_mode(cx: &mut Context) {
2890+fn window_mode(cx: &mut Context) {
2756 cx.on_next_key(move |cx, event| {
2891 cx.on_next_key(move |cx, event| {
2757 if let KeyEvent {
2892 if let KeyEvent {
2758 code: KeyCode::Char(ch),
2893 code: KeyCode::Char(ch),
@@ -2770,12 +2905,14 @@ pub fn window_mode(cx: &mut Context) {
2773−pub fn rotate_view(cx: &mut Context) {
2908+fn rotate_view(cx: &mut Context) {
2774 cx.editor.focus_next()
2909 cx.editor.focus_next()
2777// split helper, clear it later
2912// split helper, clear it later
2778use helix_view::editor::Action;
2913use helix_view::editor::Action;
2915+use self::cmd::TypableCommand;
2779fn split(cx: &mut Context, action: Action) {
2916fn split(cx: &mut Context, action: Action) {
2780 use helix_view::editor::Action;
2917 use helix_view::editor::Action;
2781 let (view, doc) = cx.current();
2918 let (view, doc) = cx.current();
@@ -2791,21 +2928,21 @@ fn split(cx: &mut Context, action: Action) {
2791 doc.set_selection(view.id, selection);
2928 doc.set_selection(view.id, selection);
2794−pub fn hsplit(cx: &mut Context) {
2931+fn hsplit(cx: &mut Context) {
2795 split(cx, Action::HorizontalSplit);
2932 split(cx, Action::HorizontalSplit);
2798−pub fn vsplit(cx: &mut Context) {
2935+fn vsplit(cx: &mut Context) {
2799 split(cx, Action::VerticalSplit);
2936 split(cx, Action::VerticalSplit);
2802−pub fn wclose(cx: &mut Context) {
2939+fn wclose(cx: &mut Context) {
2803 let view_id = cx.view().id;
2940 let view_id = cx.view().id;
2804 // close current split
2941 // close current split
2805 cx.editor.close(view_id, /* close_buffer */ false);
2942 cx.editor.close(view_id, /* close_buffer */ false);
2808−pub fn select_register(cx: &mut Context) {
2945+fn select_register(cx: &mut Context) {
2809 cx.on_next_key(move |cx, event| {
2946 cx.on_next_key(move |cx, event| {
2810 if let KeyEvent {
2947 if let KeyEvent {
2811 code: KeyCode::Char(ch),
2948 code: KeyCode::Char(ch),
@@ -2817,7 +2954,7 @@ pub fn select_register(cx: &mut Context) {
2820−pub fn space_mode(cx: &mut Context) {
2957+fn space_mode(cx: &mut Context) {
2821 cx.on_next_key(move |cx, event| {
2958 cx.on_next_key(move |cx, event| {
2822 if let KeyEvent {
2959 if let KeyEvent {
2823 code: KeyCode::Char(ch),
2960 code: KeyCode::Char(ch),
@@ -2839,7 +2976,7 @@ pub fn space_mode(cx: &mut Context) {
2842−pub fn view_mode(cx: &mut Context) {
2979+fn view_mode(cx: &mut Context) {
2843 cx.on_next_key(move |cx, event| {
2980 cx.on_next_key(move |cx, event| {
2844 if let KeyEvent {
2981 if let KeyEvent {
2845 code: KeyCode::Char(ch),
2982 code: KeyCode::Char(ch),
@@ -2882,7 +3019,7 @@ pub fn view_mode(cx: &mut Context) {
2885−pub fn left_bracket_mode(cx: &mut Context) {
3022+fn left_bracket_mode(cx: &mut Context) {
2886 cx.on_next_key(move |cx, event| {
3023 cx.on_next_key(move |cx, event| {
2887 if let KeyEvent {
3024 if let KeyEvent {
2888 code: KeyCode::Char(ch),
3025 code: KeyCode::Char(ch),
@@ -2898,7 +3035,7 @@ pub fn left_bracket_mode(cx: &mut Context) {
2901−pub fn right_bracket_mode(cx: &mut Context) {
3038+fn right_bracket_mode(cx: &mut Context) {
2902 cx.on_next_key(move |cx, event| {
3039 cx.on_next_key(move |cx, event| {
2903 if let KeyEvent {
3040 if let KeyEvent {
2904 code: KeyCode::Char(ch),
3041 code: KeyCode::Char(ch),
@@ -2913,3 +3050,29 @@ pub fn right_bracket_mode(cx: &mut Context) {
3054+impl fmt::Display for Command {
3055+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3056+ let Command(name, _) = self;
3061+impl std::str::FromStr for Command {
3062+ type Err = anyhow::Error;
3064+ fn from_str(s: &str) -> Result<Self, Self::Err> {
3065+ Command::COMMAND_LIST
3068+ .find(|cmd| cmd.0 == s)
3069+ .ok_or_else(|| anyhow!("No command named '{}'", s))
3073+impl fmt::Debug for Command {
3074+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3075+ let Command(name, _) = self;
3076+ f.debug_tuple("Command").field(name).finish()