1use crate::input::keybindings::{Action, KeyContext};
4use crate::types::context_keys;
5use rust_i18n::t;
6
7#[derive(Debug, Clone, PartialEq)]
9pub enum CommandSource {
10 Builtin,
12 Plugin(String),
14}
15
16#[derive(Debug, Clone)]
18pub struct Command {
19 pub name: String,
21 pub description: String,
23 pub action: Action,
25 pub contexts: Vec<KeyContext>,
27 pub custom_contexts: Vec<String>,
30 pub source: CommandSource,
32}
33
34impl Command {
35 pub fn get_localized_name(&self) -> String {
37 if self.name.starts_with('%') {
38 if let CommandSource::Plugin(ref plugin_name) = self.source {
39 return crate::i18n::translate_plugin_string(
40 plugin_name,
41 &self.name[1..],
42 &std::collections::HashMap::new(),
43 );
44 }
45 }
46 self.name.clone()
47 }
48
49 pub fn get_localized_description(&self) -> String {
51 if self.description.starts_with('%') {
52 if let CommandSource::Plugin(ref plugin_name) = self.source {
53 return crate::i18n::translate_plugin_string(
54 plugin_name,
55 &self.description[1..],
56 &std::collections::HashMap::new(),
57 );
58 }
59 }
60 self.description.clone()
61 }
62}
63
64#[derive(Debug, Clone, PartialEq)]
66pub struct Suggestion {
67 pub text: String,
69 pub description: Option<String>,
71 pub value: Option<String>,
73 pub disabled: bool,
75 pub keybinding: Option<String>,
77 pub source: Option<CommandSource>,
79}
80
81impl Suggestion {
82 pub fn new(text: String) -> Self {
84 Self {
85 text,
86 description: None,
87 value: None,
88 disabled: false,
89 keybinding: None,
90 source: None,
91 }
92 }
93
94 pub fn disabled(text: String) -> Self {
96 Self {
97 text,
98 description: None,
99 value: None,
100 disabled: true,
101 keybinding: None,
102 source: None,
103 }
104 }
105
106 pub fn with_description(mut self, description: String) -> Self {
107 self.description = Some(description);
108 self
109 }
110
111 pub fn with_value(mut self, value: String) -> Self {
112 self.value = Some(value);
113 self
114 }
115
116 pub fn with_keybinding(mut self, keybinding: Option<String>) -> Self {
117 self.keybinding = keybinding;
118 self
119 }
120
121 pub fn with_source(mut self, source: Option<CommandSource>) -> Self {
122 self.source = source;
123 self
124 }
125
126 pub fn set_disabled(mut self, disabled: bool) -> Self {
127 self.disabled = disabled;
128 self
129 }
130
131 pub fn get_value(&self) -> &str {
132 self.value.as_ref().unwrap_or(&self.text)
133 }
134}
135
136struct CommandDef {
138 name_key: &'static str,
139 desc_key: &'static str,
140 action: fn() -> Action,
141 contexts: &'static [KeyContext],
142 custom_contexts: &'static [&'static str],
143}
144
145use KeyContext::{FileExplorer, Normal, Terminal};
146
147static COMMAND_DEFS: &[CommandDef] = &[
150 CommandDef {
152 name_key: "cmd.open_file",
153 desc_key: "cmd.open_file_desc",
154 action: || Action::Open,
155 contexts: &[],
156 custom_contexts: &[],
157 },
158 CommandDef {
159 name_key: "cmd.switch_project",
160 desc_key: "cmd.switch_project_desc",
161 action: || Action::SwitchProject,
162 contexts: &[],
163 custom_contexts: &[],
164 },
165 CommandDef {
166 name_key: "cmd.save_file",
167 desc_key: "cmd.save_file_desc",
168 action: || Action::Save,
169 contexts: &[Normal],
170 custom_contexts: &[],
171 },
172 CommandDef {
173 name_key: "cmd.save_file_as",
174 desc_key: "cmd.save_file_as_desc",
175 action: || Action::SaveAs,
176 contexts: &[Normal],
177 custom_contexts: &[],
178 },
179 CommandDef {
180 name_key: "cmd.new_file",
181 desc_key: "cmd.new_file_desc",
182 action: || Action::New,
183 contexts: &[],
184 custom_contexts: &[],
185 },
186 CommandDef {
187 name_key: "cmd.close_buffer",
188 desc_key: "cmd.close_buffer_desc",
189 action: || Action::Close,
190 contexts: &[Normal, Terminal],
191 custom_contexts: &[],
192 },
193 CommandDef {
194 name_key: "cmd.close_tab",
195 desc_key: "cmd.close_tab_desc",
196 action: || Action::CloseTab,
197 contexts: &[Normal, Terminal],
198 custom_contexts: &[],
199 },
200 CommandDef {
201 name_key: "cmd.revert_file",
202 desc_key: "cmd.revert_file_desc",
203 action: || Action::Revert,
204 contexts: &[Normal],
205 custom_contexts: &[],
206 },
207 CommandDef {
208 name_key: "cmd.toggle_auto_revert",
209 desc_key: "cmd.toggle_auto_revert_desc",
210 action: || Action::ToggleAutoRevert,
211 contexts: &[],
212 custom_contexts: &[],
213 },
214 CommandDef {
215 name_key: "cmd.format_buffer",
216 desc_key: "cmd.format_buffer_desc",
217 action: || Action::FormatBuffer,
218 contexts: &[Normal],
219 custom_contexts: &[],
220 },
221 CommandDef {
222 name_key: "cmd.trim_trailing_whitespace",
223 desc_key: "cmd.trim_trailing_whitespace_desc",
224 action: || Action::TrimTrailingWhitespace,
225 contexts: &[Normal],
226 custom_contexts: &[],
227 },
228 CommandDef {
229 name_key: "cmd.ensure_final_newline",
230 desc_key: "cmd.ensure_final_newline_desc",
231 action: || Action::EnsureFinalNewline,
232 contexts: &[Normal],
233 custom_contexts: &[],
234 },
235 CommandDef {
236 name_key: "cmd.quit",
237 desc_key: "cmd.quit_desc",
238 action: || Action::Quit,
239 contexts: &[],
240 custom_contexts: &[],
241 },
242 CommandDef {
243 name_key: "cmd.detach",
244 desc_key: "cmd.detach_desc",
245 action: || Action::Detach,
246 contexts: &[],
247 custom_contexts: &[context_keys::SESSION_MODE],
248 },
249 CommandDef {
251 name_key: "cmd.undo",
252 desc_key: "cmd.undo_desc",
253 action: || Action::Undo,
254 contexts: &[Normal],
255 custom_contexts: &[],
256 },
257 CommandDef {
258 name_key: "cmd.redo",
259 desc_key: "cmd.redo_desc",
260 action: || Action::Redo,
261 contexts: &[Normal],
262 custom_contexts: &[],
263 },
264 CommandDef {
265 name_key: "cmd.copy",
266 desc_key: "cmd.copy_desc",
267 action: || Action::Copy,
268 contexts: &[Normal],
269 custom_contexts: &[],
270 },
271 CommandDef {
272 name_key: "cmd.copy_with_formatting",
273 desc_key: "cmd.copy_with_formatting_desc",
274 action: || Action::CopyWithTheme(String::new()),
275 contexts: &[Normal],
276 custom_contexts: &[],
277 },
278 CommandDef {
279 name_key: "cmd.cut",
280 desc_key: "cmd.cut_desc",
281 action: || Action::Cut,
282 contexts: &[Normal],
283 custom_contexts: &[],
284 },
285 CommandDef {
286 name_key: "cmd.paste",
287 desc_key: "cmd.paste_desc",
288 action: || Action::Paste,
289 contexts: &[Normal],
290 custom_contexts: &[],
291 },
292 CommandDef {
293 name_key: "cmd.delete_line",
294 desc_key: "cmd.delete_line_desc",
295 action: || Action::DeleteLine,
296 contexts: &[Normal],
297 custom_contexts: &[],
298 },
299 CommandDef {
300 name_key: "cmd.delete_word_backward",
301 desc_key: "cmd.delete_word_backward_desc",
302 action: || Action::DeleteWordBackward,
303 contexts: &[Normal],
304 custom_contexts: &[],
305 },
306 CommandDef {
307 name_key: "cmd.delete_word_forward",
308 desc_key: "cmd.delete_word_forward_desc",
309 action: || Action::DeleteWordForward,
310 contexts: &[Normal],
311 custom_contexts: &[],
312 },
313 CommandDef {
314 name_key: "cmd.delete_to_end_of_line",
315 desc_key: "cmd.delete_to_end_of_line_desc",
316 action: || Action::DeleteToLineEnd,
317 contexts: &[Normal],
318 custom_contexts: &[],
319 },
320 CommandDef {
321 name_key: "cmd.transpose_characters",
322 desc_key: "cmd.transpose_characters_desc",
323 action: || Action::TransposeChars,
324 contexts: &[Normal],
325 custom_contexts: &[],
326 },
327 CommandDef {
328 name_key: "cmd.transform_uppercase",
329 desc_key: "cmd.transform_uppercase_desc",
330 action: || Action::ToUpperCase,
331 contexts: &[Normal],
332 custom_contexts: &[],
333 },
334 CommandDef {
335 name_key: "cmd.transform_lowercase",
336 desc_key: "cmd.transform_lowercase_desc",
337 action: || Action::ToLowerCase,
338 contexts: &[Normal],
339 custom_contexts: &[],
340 },
341 CommandDef {
342 name_key: "cmd.sort_lines",
343 desc_key: "cmd.sort_lines_desc",
344 action: || Action::SortLines,
345 contexts: &[Normal],
346 custom_contexts: &[],
347 },
348 CommandDef {
349 name_key: "cmd.open_line",
350 desc_key: "cmd.open_line_desc",
351 action: || Action::OpenLine,
352 contexts: &[Normal],
353 custom_contexts: &[],
354 },
355 CommandDef {
356 name_key: "cmd.duplicate_line",
357 desc_key: "cmd.duplicate_line_desc",
358 action: || Action::DuplicateLine,
359 contexts: &[Normal],
360 custom_contexts: &[],
361 },
362 CommandDef {
363 name_key: "cmd.recenter",
364 desc_key: "cmd.recenter_desc",
365 action: || Action::Recenter,
366 contexts: &[Normal],
367 custom_contexts: &[],
368 },
369 CommandDef {
370 name_key: "cmd.set_mark",
371 desc_key: "cmd.set_mark_desc",
372 action: || Action::SetMark,
373 contexts: &[Normal],
374 custom_contexts: &[],
375 },
376 CommandDef {
378 name_key: "cmd.select_all",
379 desc_key: "cmd.select_all_desc",
380 action: || Action::SelectAll,
381 contexts: &[Normal],
382 custom_contexts: &[],
383 },
384 CommandDef {
385 name_key: "cmd.select_word",
386 desc_key: "cmd.select_word_desc",
387 action: || Action::SelectWord,
388 contexts: &[Normal],
389 custom_contexts: &[],
390 },
391 CommandDef {
392 name_key: "cmd.select_line",
393 desc_key: "cmd.select_line_desc",
394 action: || Action::SelectLine,
395 contexts: &[Normal],
396 custom_contexts: &[],
397 },
398 CommandDef {
399 name_key: "cmd.expand_selection",
400 desc_key: "cmd.expand_selection_desc",
401 action: || Action::ExpandSelection,
402 contexts: &[Normal],
403 custom_contexts: &[],
404 },
405 CommandDef {
407 name_key: "cmd.add_cursor_above",
408 desc_key: "cmd.add_cursor_above_desc",
409 action: || Action::AddCursorAbove,
410 contexts: &[Normal],
411 custom_contexts: &[],
412 },
413 CommandDef {
414 name_key: "cmd.add_cursor_below",
415 desc_key: "cmd.add_cursor_below_desc",
416 action: || Action::AddCursorBelow,
417 contexts: &[Normal],
418 custom_contexts: &[],
419 },
420 CommandDef {
421 name_key: "cmd.add_cursor_next_match",
422 desc_key: "cmd.add_cursor_next_match_desc",
423 action: || Action::AddCursorNextMatch,
424 contexts: &[Normal],
425 custom_contexts: &[],
426 },
427 CommandDef {
428 name_key: "cmd.remove_secondary_cursors",
429 desc_key: "cmd.remove_secondary_cursors_desc",
430 action: || Action::RemoveSecondaryCursors,
431 contexts: &[Normal],
432 custom_contexts: &[],
433 },
434 CommandDef {
436 name_key: "cmd.next_buffer",
437 desc_key: "cmd.next_buffer_desc",
438 action: || Action::NextBuffer,
439 contexts: &[Normal, Terminal],
440 custom_contexts: &[],
441 },
442 CommandDef {
443 name_key: "cmd.previous_buffer",
444 desc_key: "cmd.previous_buffer_desc",
445 action: || Action::PrevBuffer,
446 contexts: &[Normal, Terminal],
447 custom_contexts: &[],
448 },
449 CommandDef {
450 name_key: "cmd.switch_to_previous_tab",
451 desc_key: "cmd.switch_to_previous_tab_desc",
452 action: || Action::SwitchToPreviousTab,
453 contexts: &[Normal, Terminal],
454 custom_contexts: &[],
455 },
456 CommandDef {
457 name_key: "cmd.switch_to_tab_by_name",
458 desc_key: "cmd.switch_to_tab_by_name_desc",
459 action: || Action::SwitchToTabByName,
460 contexts: &[Normal, Terminal],
461 custom_contexts: &[],
462 },
463 CommandDef {
465 name_key: "cmd.split_horizontal",
466 desc_key: "cmd.split_horizontal_desc",
467 action: || Action::SplitHorizontal,
468 contexts: &[Normal, Terminal],
469 custom_contexts: &[],
470 },
471 CommandDef {
472 name_key: "cmd.split_vertical",
473 desc_key: "cmd.split_vertical_desc",
474 action: || Action::SplitVertical,
475 contexts: &[Normal, Terminal],
476 custom_contexts: &[],
477 },
478 CommandDef {
479 name_key: "cmd.close_split",
480 desc_key: "cmd.close_split_desc",
481 action: || Action::CloseSplit,
482 contexts: &[Normal, Terminal],
483 custom_contexts: &[],
484 },
485 CommandDef {
486 name_key: "cmd.next_split",
487 desc_key: "cmd.next_split_desc",
488 action: || Action::NextSplit,
489 contexts: &[Normal, Terminal],
490 custom_contexts: &[],
491 },
492 CommandDef {
493 name_key: "cmd.previous_split",
494 desc_key: "cmd.previous_split_desc",
495 action: || Action::PrevSplit,
496 contexts: &[Normal, Terminal],
497 custom_contexts: &[],
498 },
499 CommandDef {
500 name_key: "cmd.increase_split_size",
501 desc_key: "cmd.increase_split_size_desc",
502 action: || Action::IncreaseSplitSize,
503 contexts: &[Normal, Terminal],
504 custom_contexts: &[],
505 },
506 CommandDef {
507 name_key: "cmd.decrease_split_size",
508 desc_key: "cmd.decrease_split_size_desc",
509 action: || Action::DecreaseSplitSize,
510 contexts: &[Normal, Terminal],
511 custom_contexts: &[],
512 },
513 CommandDef {
514 name_key: "cmd.toggle_maximize_split",
515 desc_key: "cmd.toggle_maximize_split_desc",
516 action: || Action::ToggleMaximizeSplit,
517 contexts: &[Normal, Terminal],
518 custom_contexts: &[],
519 },
520 CommandDef {
522 name_key: "cmd.toggle_line_numbers",
523 desc_key: "cmd.toggle_line_numbers_desc",
524 action: || Action::ToggleLineNumbers,
525 contexts: &[Normal],
526 custom_contexts: &[],
527 },
528 CommandDef {
529 name_key: "cmd.toggle_scroll_sync",
530 desc_key: "cmd.toggle_scroll_sync_desc",
531 action: || Action::ToggleScrollSync,
532 contexts: &[Normal],
533 custom_contexts: &[],
534 },
535 CommandDef {
536 name_key: "cmd.toggle_fold",
537 desc_key: "cmd.toggle_fold_desc",
538 action: || Action::ToggleFold,
539 contexts: &[Normal],
540 custom_contexts: &[],
541 },
542 CommandDef {
543 name_key: "cmd.debug_toggle_highlight",
544 desc_key: "cmd.debug_toggle_highlight_desc",
545 action: || Action::ToggleDebugHighlights,
546 contexts: &[Normal],
547 custom_contexts: &[],
548 },
549 CommandDef {
551 name_key: "cmd.add_ruler",
552 desc_key: "cmd.add_ruler_desc",
553 action: || Action::AddRuler,
554 contexts: &[Normal],
555 custom_contexts: &[],
556 },
557 CommandDef {
558 name_key: "cmd.remove_ruler",
559 desc_key: "cmd.remove_ruler_desc",
560 action: || Action::RemoveRuler,
561 contexts: &[Normal],
562 custom_contexts: &[],
563 },
564 CommandDef {
566 name_key: "cmd.set_tab_size",
567 desc_key: "cmd.set_tab_size_desc",
568 action: || Action::SetTabSize,
569 contexts: &[Normal],
570 custom_contexts: &[],
571 },
572 CommandDef {
573 name_key: "cmd.set_line_ending",
574 desc_key: "cmd.set_line_ending_desc",
575 action: || Action::SetLineEnding,
576 contexts: &[Normal],
577 custom_contexts: &[],
578 },
579 CommandDef {
580 name_key: "cmd.set_encoding",
581 desc_key: "cmd.set_encoding_desc",
582 action: || Action::SetEncoding,
583 contexts: &[Normal],
584 custom_contexts: &[],
585 },
586 CommandDef {
587 name_key: "cmd.reload_with_encoding",
588 desc_key: "cmd.reload_with_encoding_desc",
589 action: || Action::ReloadWithEncoding,
590 contexts: &[Normal],
591 custom_contexts: &[],
592 },
593 CommandDef {
594 name_key: "cmd.set_language",
595 desc_key: "cmd.set_language_desc",
596 action: || Action::SetLanguage,
597 contexts: &[Normal],
598 custom_contexts: &[],
599 },
600 CommandDef {
601 name_key: "cmd.toggle_indentation",
602 desc_key: "cmd.toggle_indentation_desc",
603 action: || Action::ToggleIndentationStyle,
604 contexts: &[Normal],
605 custom_contexts: &[],
606 },
607 CommandDef {
608 name_key: "cmd.toggle_tab_indicators",
609 desc_key: "cmd.toggle_tab_indicators_desc",
610 action: || Action::ToggleTabIndicators,
611 contexts: &[Normal],
612 custom_contexts: &[],
613 },
614 CommandDef {
615 name_key: "cmd.toggle_whitespace_indicators",
616 desc_key: "cmd.toggle_whitespace_indicators_desc",
617 action: || Action::ToggleWhitespaceIndicators,
618 contexts: &[Normal],
619 custom_contexts: &[],
620 },
621 CommandDef {
622 name_key: "cmd.reset_buffer_settings",
623 desc_key: "cmd.reset_buffer_settings_desc",
624 action: || Action::ResetBufferSettings,
625 contexts: &[Normal],
626 custom_contexts: &[],
627 },
628 CommandDef {
629 name_key: "cmd.scroll_up",
630 desc_key: "cmd.scroll_up_desc",
631 action: || Action::ScrollUp,
632 contexts: &[Normal],
633 custom_contexts: &[],
634 },
635 CommandDef {
636 name_key: "cmd.scroll_down",
637 desc_key: "cmd.scroll_down_desc",
638 action: || Action::ScrollDown,
639 contexts: &[Normal],
640 custom_contexts: &[],
641 },
642 CommandDef {
643 name_key: "cmd.scroll_tabs_left",
644 desc_key: "cmd.scroll_tabs_left_desc",
645 action: || Action::ScrollTabsLeft,
646 contexts: &[Normal, Terminal],
647 custom_contexts: &[],
648 },
649 CommandDef {
650 name_key: "cmd.scroll_tabs_right",
651 desc_key: "cmd.scroll_tabs_right_desc",
652 action: || Action::ScrollTabsRight,
653 contexts: &[Normal, Terminal],
654 custom_contexts: &[],
655 },
656 CommandDef {
657 name_key: "cmd.toggle_mouse_support",
658 desc_key: "cmd.toggle_mouse_support_desc",
659 action: || Action::ToggleMouseCapture,
660 contexts: &[Normal, Terminal],
661 custom_contexts: &[],
662 },
663 CommandDef {
665 name_key: "cmd.toggle_file_explorer",
666 desc_key: "cmd.toggle_file_explorer_desc",
667 action: || Action::ToggleFileExplorer,
668 contexts: &[Normal, FileExplorer, Terminal],
669 custom_contexts: &[],
670 },
671 CommandDef {
672 name_key: "cmd.toggle_menu_bar",
673 desc_key: "cmd.toggle_menu_bar_desc",
674 action: || Action::ToggleMenuBar,
675 contexts: &[Normal, FileExplorer, Terminal],
676 custom_contexts: &[],
677 },
678 CommandDef {
679 name_key: "cmd.toggle_tab_bar",
680 desc_key: "cmd.toggle_tab_bar_desc",
681 action: || Action::ToggleTabBar,
682 contexts: &[Normal, FileExplorer, Terminal],
683 custom_contexts: &[],
684 },
685 CommandDef {
686 name_key: "cmd.toggle_status_bar",
687 desc_key: "cmd.toggle_status_bar_desc",
688 action: || Action::ToggleStatusBar,
689 contexts: &[Normal, FileExplorer, Terminal],
690 custom_contexts: &[],
691 },
692 CommandDef {
693 name_key: "cmd.toggle_prompt_line",
694 desc_key: "cmd.toggle_prompt_line_desc",
695 action: || Action::TogglePromptLine,
696 contexts: &[Normal, FileExplorer, Terminal],
697 custom_contexts: &[],
698 },
699 CommandDef {
700 name_key: "cmd.toggle_vertical_scrollbar",
701 desc_key: "cmd.toggle_vertical_scrollbar_desc",
702 action: || Action::ToggleVerticalScrollbar,
703 contexts: &[Normal, FileExplorer, Terminal],
704 custom_contexts: &[],
705 },
706 CommandDef {
707 name_key: "cmd.toggle_horizontal_scrollbar",
708 desc_key: "cmd.toggle_horizontal_scrollbar_desc",
709 action: || Action::ToggleHorizontalScrollbar,
710 contexts: &[Normal, FileExplorer, Terminal],
711 custom_contexts: &[],
712 },
713 CommandDef {
714 name_key: "cmd.focus_file_explorer",
715 desc_key: "cmd.focus_file_explorer_desc",
716 action: || Action::FocusFileExplorer,
717 contexts: &[Normal, Terminal],
718 custom_contexts: &[],
719 },
720 CommandDef {
721 name_key: "cmd.focus_editor",
722 desc_key: "cmd.focus_editor_desc",
723 action: || Action::FocusEditor,
724 contexts: &[FileExplorer],
725 custom_contexts: &[],
726 },
727 CommandDef {
728 name_key: "cmd.explorer_refresh",
729 desc_key: "cmd.explorer_refresh_desc",
730 action: || Action::FileExplorerRefresh,
731 contexts: &[FileExplorer],
732 custom_contexts: &[],
733 },
734 CommandDef {
735 name_key: "cmd.explorer_new_file",
736 desc_key: "cmd.explorer_new_file_desc",
737 action: || Action::FileExplorerNewFile,
738 contexts: &[FileExplorer],
739 custom_contexts: &[],
740 },
741 CommandDef {
742 name_key: "cmd.explorer_new_directory",
743 desc_key: "cmd.explorer_new_directory_desc",
744 action: || Action::FileExplorerNewDirectory,
745 contexts: &[FileExplorer],
746 custom_contexts: &[],
747 },
748 CommandDef {
749 name_key: "cmd.explorer_delete",
750 desc_key: "cmd.explorer_delete_desc",
751 action: || Action::FileExplorerDelete,
752 contexts: &[FileExplorer],
753 custom_contexts: &[],
754 },
755 CommandDef {
756 name_key: "cmd.explorer_rename",
757 desc_key: "cmd.explorer_rename_desc",
758 action: || Action::FileExplorerRename,
759 contexts: &[FileExplorer],
760 custom_contexts: &[],
761 },
762 CommandDef {
763 name_key: "cmd.toggle_hidden_files",
764 desc_key: "cmd.toggle_hidden_files_desc",
765 action: || Action::FileExplorerToggleHidden,
766 contexts: &[FileExplorer],
767 custom_contexts: &[],
768 },
769 CommandDef {
770 name_key: "cmd.toggle_gitignored_files",
771 desc_key: "cmd.toggle_gitignored_files_desc",
772 action: || Action::FileExplorerToggleGitignored,
773 contexts: &[FileExplorer],
774 custom_contexts: &[],
775 },
776 CommandDef {
778 name_key: "cmd.toggle_line_wrap",
779 desc_key: "cmd.toggle_line_wrap_desc",
780 action: || Action::ToggleLineWrap,
781 contexts: &[Normal],
782 custom_contexts: &[],
783 },
784 CommandDef {
785 name_key: "cmd.toggle_current_line_highlight",
786 desc_key: "cmd.toggle_current_line_highlight_desc",
787 action: || Action::ToggleCurrentLineHighlight,
788 contexts: &[Normal],
789 custom_contexts: &[],
790 },
791 CommandDef {
792 name_key: "cmd.toggle_page_view",
793 desc_key: "cmd.toggle_page_view_desc",
794 action: || Action::TogglePageView,
795 contexts: &[Normal],
796 custom_contexts: &[],
797 },
798 CommandDef {
799 name_key: "cmd.set_page_width",
800 desc_key: "cmd.set_page_width_desc",
801 action: || Action::SetPageWidth,
802 contexts: &[Normal],
803 custom_contexts: &[],
804 },
805 CommandDef {
806 name_key: "cmd.toggle_read_only",
807 desc_key: "cmd.toggle_read_only_desc",
808 action: || Action::ToggleReadOnly,
809 contexts: &[Normal],
810 custom_contexts: &[],
811 },
812 CommandDef {
813 name_key: "cmd.set_background",
814 desc_key: "cmd.set_background_desc",
815 action: || Action::SetBackground,
816 contexts: &[Normal],
817 custom_contexts: &[],
818 },
819 CommandDef {
820 name_key: "cmd.set_background_blend",
821 desc_key: "cmd.set_background_blend_desc",
822 action: || Action::SetBackgroundBlend,
823 contexts: &[Normal],
824 custom_contexts: &[],
825 },
826 CommandDef {
828 name_key: "cmd.search",
829 desc_key: "cmd.search_desc",
830 action: || Action::Search,
831 contexts: &[Normal],
832 custom_contexts: &[],
833 },
834 CommandDef {
835 name_key: "cmd.find_in_selection",
836 desc_key: "cmd.find_in_selection_desc",
837 action: || Action::FindInSelection,
838 contexts: &[Normal],
839 custom_contexts: &[],
840 },
841 CommandDef {
842 name_key: "cmd.find_next",
843 desc_key: "cmd.find_next_desc",
844 action: || Action::FindNext,
845 contexts: &[Normal],
846 custom_contexts: &[],
847 },
848 CommandDef {
849 name_key: "cmd.find_previous",
850 desc_key: "cmd.find_previous_desc",
851 action: || Action::FindPrevious,
852 contexts: &[Normal],
853 custom_contexts: &[],
854 },
855 CommandDef {
856 name_key: "cmd.find_selection_next",
857 desc_key: "cmd.find_selection_next_desc",
858 action: || Action::FindSelectionNext,
859 contexts: &[Normal],
860 custom_contexts: &[],
861 },
862 CommandDef {
863 name_key: "cmd.find_selection_previous",
864 desc_key: "cmd.find_selection_previous_desc",
865 action: || Action::FindSelectionPrevious,
866 contexts: &[Normal],
867 custom_contexts: &[],
868 },
869 CommandDef {
870 name_key: "cmd.replace",
871 desc_key: "cmd.replace_desc",
872 action: || Action::Replace,
873 contexts: &[Normal],
874 custom_contexts: &[],
875 },
876 CommandDef {
877 name_key: "cmd.query_replace",
878 desc_key: "cmd.query_replace_desc",
879 action: || Action::QueryReplace,
880 contexts: &[Normal],
881 custom_contexts: &[],
882 },
883 CommandDef {
885 name_key: "cmd.goto_line",
886 desc_key: "cmd.goto_line_desc",
887 action: || Action::GotoLine,
888 contexts: &[Normal],
889 custom_contexts: &[],
890 },
891 CommandDef {
892 name_key: "cmd.scan_line_index",
893 desc_key: "cmd.scan_line_index_desc",
894 action: || Action::ScanLineIndex,
895 contexts: &[Normal],
896 custom_contexts: &[],
897 },
898 CommandDef {
899 name_key: "cmd.smart_home",
900 desc_key: "cmd.smart_home_desc",
901 action: || Action::SmartHome,
902 contexts: &[Normal],
903 custom_contexts: &[],
904 },
905 CommandDef {
906 name_key: "cmd.show_completions",
907 desc_key: "cmd.show_completions_desc",
908 action: || Action::LspCompletion,
909 contexts: &[Normal],
910 custom_contexts: &[],
911 },
912 CommandDef {
913 name_key: "cmd.goto_definition",
914 desc_key: "cmd.goto_definition_desc",
915 action: || Action::LspGotoDefinition,
916 contexts: &[Normal],
917 custom_contexts: &[],
918 },
919 CommandDef {
920 name_key: "cmd.show_hover_info",
921 desc_key: "cmd.show_hover_info_desc",
922 action: || Action::LspHover,
923 contexts: &[Normal],
924 custom_contexts: &[],
925 },
926 CommandDef {
927 name_key: "cmd.find_references",
928 desc_key: "cmd.find_references_desc",
929 action: || Action::LspReferences,
930 contexts: &[Normal],
931 custom_contexts: &[],
932 },
933 CommandDef {
934 name_key: "cmd.show_signature_help",
935 desc_key: "cmd.show_signature_help_desc",
936 action: || Action::LspSignatureHelp,
937 contexts: &[Normal],
938 custom_contexts: &[],
939 },
940 CommandDef {
941 name_key: "cmd.code_actions",
942 desc_key: "cmd.code_actions_desc",
943 action: || Action::LspCodeActions,
944 contexts: &[Normal],
945 custom_contexts: &[],
946 },
947 CommandDef {
948 name_key: "cmd.start_restart_lsp",
949 desc_key: "cmd.start_restart_lsp_desc",
950 action: || Action::LspRestart,
951 contexts: &[Normal],
952 custom_contexts: &[],
953 },
954 CommandDef {
955 name_key: "cmd.stop_lsp",
956 desc_key: "cmd.stop_lsp_desc",
957 action: || Action::LspStop,
958 contexts: &[Normal],
959 custom_contexts: &[],
960 },
961 CommandDef {
962 name_key: "cmd.toggle_lsp_for_buffer",
963 desc_key: "cmd.toggle_lsp_for_buffer_desc",
964 action: || Action::LspToggleForBuffer,
965 contexts: &[Normal],
966 custom_contexts: &[],
967 },
968 CommandDef {
969 name_key: "cmd.toggle_mouse_hover",
970 desc_key: "cmd.toggle_mouse_hover_desc",
971 action: || Action::ToggleMouseHover,
972 contexts: &[],
973 custom_contexts: &[],
974 },
975 CommandDef {
976 name_key: "cmd.navigate_back",
977 desc_key: "cmd.navigate_back_desc",
978 action: || Action::NavigateBack,
979 contexts: &[Normal],
980 custom_contexts: &[],
981 },
982 CommandDef {
983 name_key: "cmd.navigate_forward",
984 desc_key: "cmd.navigate_forward_desc",
985 action: || Action::NavigateForward,
986 contexts: &[Normal],
987 custom_contexts: &[],
988 },
989 CommandDef {
991 name_key: "cmd.toggle_comment",
992 desc_key: "cmd.toggle_comment_desc",
993 action: || Action::ToggleComment,
994 contexts: &[Normal],
995 custom_contexts: &[],
996 },
997 CommandDef {
998 name_key: "cmd.dedent_selection",
999 desc_key: "cmd.dedent_selection_desc",
1000 action: || Action::DedentSelection,
1001 contexts: &[Normal],
1002 custom_contexts: &[],
1003 },
1004 CommandDef {
1005 name_key: "cmd.goto_matching_bracket",
1006 desc_key: "cmd.goto_matching_bracket_desc",
1007 action: || Action::GoToMatchingBracket,
1008 contexts: &[Normal],
1009 custom_contexts: &[],
1010 },
1011 CommandDef {
1013 name_key: "cmd.jump_to_next_error",
1014 desc_key: "cmd.jump_to_next_error_desc",
1015 action: || Action::JumpToNextError,
1016 contexts: &[Normal],
1017 custom_contexts: &[],
1018 },
1019 CommandDef {
1020 name_key: "cmd.jump_to_previous_error",
1021 desc_key: "cmd.jump_to_previous_error_desc",
1022 action: || Action::JumpToPreviousError,
1023 contexts: &[Normal],
1024 custom_contexts: &[],
1025 },
1026 CommandDef {
1028 name_key: "cmd.rename_symbol",
1029 desc_key: "cmd.rename_symbol_desc",
1030 action: || Action::LspRename,
1031 contexts: &[Normal],
1032 custom_contexts: &[],
1033 },
1034 CommandDef {
1036 name_key: "cmd.list_bookmarks",
1037 desc_key: "cmd.list_bookmarks_desc",
1038 action: || Action::ListBookmarks,
1039 contexts: &[Normal],
1040 custom_contexts: &[],
1041 },
1042 CommandDef {
1043 name_key: "cmd.list_macros",
1044 desc_key: "cmd.list_macros_desc",
1045 action: || Action::ListMacros,
1046 contexts: &[Normal],
1047 custom_contexts: &[],
1048 },
1049 CommandDef {
1050 name_key: "cmd.record_macro",
1051 desc_key: "cmd.record_macro_desc",
1052 action: || Action::PromptRecordMacro,
1053 contexts: &[Normal],
1054 custom_contexts: &[],
1055 },
1056 CommandDef {
1057 name_key: "cmd.stop_recording_macro",
1058 desc_key: "cmd.stop_recording_macro_desc",
1059 action: || Action::StopMacroRecording,
1060 contexts: &[Normal],
1061 custom_contexts: &[],
1062 },
1063 CommandDef {
1064 name_key: "cmd.play_macro",
1065 desc_key: "cmd.play_macro_desc",
1066 action: || Action::PromptPlayMacro,
1067 contexts: &[Normal],
1068 custom_contexts: &[],
1069 },
1070 CommandDef {
1071 name_key: "cmd.play_last_macro",
1072 desc_key: "cmd.play_last_macro_desc",
1073 action: || Action::PlayLastMacro,
1074 contexts: &[Normal],
1075 custom_contexts: &[],
1076 },
1077 CommandDef {
1078 name_key: "cmd.set_bookmark",
1079 desc_key: "cmd.set_bookmark_desc",
1080 action: || Action::PromptSetBookmark,
1081 contexts: &[Normal],
1082 custom_contexts: &[],
1083 },
1084 CommandDef {
1085 name_key: "cmd.jump_to_bookmark",
1086 desc_key: "cmd.jump_to_bookmark_desc",
1087 action: || Action::PromptJumpToBookmark,
1088 contexts: &[Normal],
1089 custom_contexts: &[],
1090 },
1091 CommandDef {
1093 name_key: "cmd.show_manual",
1094 desc_key: "cmd.show_manual_desc",
1095 action: || Action::ShowHelp,
1096 contexts: &[],
1097 custom_contexts: &[],
1098 },
1099 CommandDef {
1100 name_key: "cmd.show_keyboard_shortcuts",
1101 desc_key: "cmd.show_keyboard_shortcuts_desc",
1102 action: || Action::ShowKeyboardShortcuts,
1103 contexts: &[],
1104 custom_contexts: &[],
1105 },
1106 CommandDef {
1107 name_key: "cmd.show_warnings",
1108 desc_key: "cmd.show_warnings_desc",
1109 action: || Action::ShowWarnings,
1110 contexts: &[],
1111 custom_contexts: &[],
1112 },
1113 CommandDef {
1114 name_key: "cmd.show_lsp_status",
1115 desc_key: "cmd.show_lsp_status_desc",
1116 action: || Action::ShowLspStatus,
1117 contexts: &[],
1118 custom_contexts: &[],
1119 },
1120 CommandDef {
1121 name_key: "cmd.clear_warnings",
1122 desc_key: "cmd.clear_warnings_desc",
1123 action: || Action::ClearWarnings,
1124 contexts: &[],
1125 custom_contexts: &[],
1126 },
1127 CommandDef {
1129 name_key: "cmd.dump_config",
1130 desc_key: "cmd.dump_config_desc",
1131 action: || Action::DumpConfig,
1132 contexts: &[],
1133 custom_contexts: &[],
1134 },
1135 CommandDef {
1136 name_key: "cmd.toggle_inlay_hints",
1137 desc_key: "cmd.toggle_inlay_hints_desc",
1138 action: || Action::ToggleInlayHints,
1139 contexts: &[Normal],
1140 custom_contexts: &[],
1141 },
1142 CommandDef {
1144 name_key: "cmd.select_theme",
1145 desc_key: "cmd.select_theme_desc",
1146 action: || Action::SelectTheme,
1147 contexts: &[],
1148 custom_contexts: &[],
1149 },
1150 CommandDef {
1152 name_key: "cmd.inspect_theme_at_cursor",
1153 desc_key: "cmd.inspect_theme_at_cursor_desc",
1154 action: || Action::InspectThemeAtCursor,
1155 contexts: &[Normal],
1156 custom_contexts: &[],
1157 },
1158 CommandDef {
1160 name_key: "cmd.select_keybinding_map",
1161 desc_key: "cmd.select_keybinding_map_desc",
1162 action: || Action::SelectKeybindingMap,
1163 contexts: &[],
1164 custom_contexts: &[],
1165 },
1166 CommandDef {
1168 name_key: "cmd.select_cursor_style",
1169 desc_key: "cmd.select_cursor_style_desc",
1170 action: || Action::SelectCursorStyle,
1171 contexts: &[],
1172 custom_contexts: &[],
1173 },
1174 CommandDef {
1176 name_key: "cmd.select_locale",
1177 desc_key: "cmd.select_locale_desc",
1178 action: || Action::SelectLocale,
1179 contexts: &[],
1180 custom_contexts: &[],
1181 },
1182 CommandDef {
1184 name_key: "cmd.open_settings",
1185 desc_key: "cmd.open_settings_desc",
1186 action: || Action::OpenSettings,
1187 contexts: &[],
1188 custom_contexts: &[],
1189 },
1190 CommandDef {
1192 name_key: "cmd.open_keybinding_editor",
1193 desc_key: "cmd.open_keybinding_editor_desc",
1194 action: || Action::OpenKeybindingEditor,
1195 contexts: &[],
1196 custom_contexts: &[],
1197 },
1198 CommandDef {
1200 name_key: "cmd.calibrate_input",
1201 desc_key: "cmd.calibrate_input_desc",
1202 action: || Action::CalibrateInput,
1203 contexts: &[],
1204 custom_contexts: &[],
1205 },
1206 CommandDef {
1208 name_key: "cmd.open_terminal",
1209 desc_key: "cmd.open_terminal_desc",
1210 action: || Action::OpenTerminal,
1211 contexts: &[],
1212 custom_contexts: &[],
1213 },
1214 CommandDef {
1215 name_key: "cmd.focus_terminal",
1216 desc_key: "cmd.focus_terminal_desc",
1217 action: || Action::FocusTerminal,
1218 contexts: &[Normal],
1219 custom_contexts: &[],
1220 },
1221 CommandDef {
1222 name_key: "cmd.exit_terminal_mode",
1223 desc_key: "cmd.exit_terminal_mode_desc",
1224 action: || Action::TerminalEscape,
1225 contexts: &[Terminal],
1226 custom_contexts: &[],
1227 },
1228 CommandDef {
1229 name_key: "cmd.toggle_keyboard_capture",
1230 desc_key: "cmd.toggle_keyboard_capture_desc",
1231 action: || Action::ToggleKeyboardCapture,
1232 contexts: &[Terminal],
1233 custom_contexts: &[],
1234 },
1235 CommandDef {
1237 name_key: "cmd.shell_command",
1238 desc_key: "cmd.shell_command_desc",
1239 action: || Action::ShellCommand,
1240 contexts: &[Normal],
1241 custom_contexts: &[],
1242 },
1243 CommandDef {
1244 name_key: "cmd.shell_command_replace",
1245 desc_key: "cmd.shell_command_replace_desc",
1246 action: || Action::ShellCommandReplace,
1247 contexts: &[Normal],
1248 custom_contexts: &[],
1249 },
1250 CommandDef {
1252 name_key: "cmd.event_debug",
1253 desc_key: "cmd.event_debug_desc",
1254 action: || Action::EventDebug,
1255 contexts: &[],
1256 custom_contexts: &[],
1257 },
1258 CommandDef {
1260 name_key: "cmd.load_plugin_from_buffer",
1261 desc_key: "cmd.load_plugin_from_buffer_desc",
1262 action: || Action::LoadPluginFromBuffer,
1263 contexts: &[Normal],
1264 custom_contexts: &[],
1265 },
1266];
1267
1268pub fn get_all_commands() -> Vec<Command> {
1270 COMMAND_DEFS
1271 .iter()
1272 .map(|def| Command {
1273 name: t!(def.name_key).to_string(),
1274 description: t!(def.desc_key).to_string(),
1275 action: (def.action)(),
1276 contexts: def.contexts.to_vec(),
1277 custom_contexts: def.custom_contexts.iter().map(|s| s.to_string()).collect(),
1278 source: CommandSource::Builtin,
1279 })
1280 .collect()
1281}
1282
1283pub fn filter_commands(
1285 query: &str,
1286 current_context: KeyContext,
1287 keybinding_resolver: &crate::input::keybindings::KeybindingResolver,
1288) -> Vec<Suggestion> {
1289 let query_lower = query.to_lowercase();
1290 let commands = get_all_commands();
1291
1292 let is_available = |cmd: &Command| -> bool {
1294 cmd.contexts.is_empty() || cmd.contexts.contains(¤t_context)
1296 };
1297
1298 let matches_query = |cmd: &Command| -> bool {
1300 if query.is_empty() {
1301 return true;
1302 }
1303
1304 let name_lower = cmd.name.to_lowercase();
1305 let mut query_chars = query_lower.chars();
1306 let mut current_char = query_chars.next();
1307
1308 for name_char in name_lower.chars() {
1309 if let Some(qc) = current_char {
1310 if qc == name_char {
1311 current_char = query_chars.next();
1312 }
1313 } else {
1314 break;
1315 }
1316 }
1317
1318 current_char.is_none() };
1320
1321 let current_context_ref = ¤t_context;
1323 let mut suggestions: Vec<Suggestion> = commands
1324 .into_iter()
1325 .filter(|cmd| matches_query(cmd))
1326 .map(|cmd| {
1327 let available = is_available(&cmd);
1328 let keybinding = keybinding_resolver
1329 .get_keybinding_for_action(&cmd.action, current_context_ref.clone());
1330 Suggestion::new(cmd.name.clone())
1331 .with_description(cmd.description)
1332 .set_disabled(!available)
1333 .with_keybinding(keybinding)
1334 })
1335 .collect();
1336
1337 suggestions.sort_by_key(|s| s.disabled);
1339
1340 suggestions
1341}