indigo_core/mode/
insert.rs1#![allow(clippy::enum_glob_use)]
2
3use crate::{
4 editor::Editor,
5 key::{KeyCode, KeyModifiers},
6 keymap::{Keymap, KeymapResult, keymap},
7 mode::{Mode, normal},
8};
9use std::sync::LazyLock;
10
11#[cfg(feature = "arbitrary")]
12use arbitrary::Arbitrary;
13
14#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
15#[derive(Debug)]
16pub enum Action {
17 EnterNormalMode,
18 DeleteBefore,
19 DeleteAfter,
20 InsertChar(char),
21}
22
23pub static KEYMAP: LazyLock<Keymap<Vec<Action>>> = LazyLock::new(|| {
24 use Action::*;
25 keymap! { Vec<Action>;
26 "<esc>" => vec![EnterNormalMode], "<tab>" => vec![InsertChar('\t')], "<ret>" => vec![InsertChar('\n')], "<bs>" => vec![DeleteBefore], "<del>" => vec![DeleteAfter], keys => {
32 if let [key] = keys
33 && let KeyCode::Char(c) = key.code
34 && key.modifiers.difference(KeyModifiers::SHIFT).is_empty()
35 {
36 KeymapResult::Fallback(vec![InsertChar(char::from(c))])
37 } else {
38 KeymapResult::Unmapped
39 }
40 } }
42});
43
44pub fn handle_actions(editor: &mut Editor, actions: &[Action]) {
45 for action in actions {
46 handle_action(editor, action);
47 }
48}
49
50pub fn handle_action(editor: &mut Editor, action: &Action) {
51 match action {
52 Action::EnterNormalMode => normal::enter(editor),
53 Action::DeleteBefore => delete_before(editor),
54 Action::DeleteAfter => delete_after(editor),
55 Action::InsertChar(c) => insert_char(editor, *c),
56 }
57}
58
59pub fn handle_keys(editor: &mut Editor) -> bool {
60 match KEYMAP.get_keys(&editor.pending_keys) {
61 KeymapResult::Mapped(actions) => {
62 editor.pending_keys.clear();
63 handle_actions(editor, actions);
64 true
65 }
66 KeymapResult::Fallback(actions) => {
67 editor.pending_keys.clear();
68 handle_actions(editor, &actions);
69 true
70 }
71 KeymapResult::Unmapped => {
72 editor.pending_keys.clear();
73 false
74 }
75 KeymapResult::Pending => true,
76 }
77}
78
79pub fn enter(editor: &mut Editor) {
80 if editor.focused_buffer().text.readonly {
81 editor.message = Some(Err(String::from("Buffer is readonly")));
82 editor.count = None;
83 return;
84 }
85 let mut window = editor.focused_window_mut();
86 window
87 .selection_move()
88 .for_each_move(|mut range| range.collapse());
89 window.scroll_to_selection();
90 editor.mode = Mode::Insert;
91 editor.count = None;
92}
93
94fn delete_before(editor: &mut Editor) {
95 let mut window = editor.focused_window_mut();
96 window.selection_edit().delete_before();
97 window.scroll_to_selection();
98 editor.count = None;
99}
100
101fn delete_after(editor: &mut Editor) {
102 let mut window = editor.focused_window_mut();
103 window.selection_edit().delete_after();
104 window.scroll_to_selection();
105 editor.count = None;
106}
107
108fn insert_char(editor: &mut Editor, char: char) {
109 let mut window = editor.focused_window_mut();
110 window.selection_edit().insert_char(char);
111 window.scroll_to_selection();
112 editor.count = None;
113}
114
115pub fn paste(editor: &mut Editor, text: &str) {
116 let mut window = editor.focused_window_mut();
117 window.selection_edit().insert(text);
118 window.scroll_to_selection();
119 editor.count = None;
120}