Skip to main content

indigo_core/mode/
replace.rs

1#![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    Replace(u8),
18}
19
20pub static KEYMAP: LazyLock<Keymap<Vec<Action>>> = LazyLock::new(|| {
21    use Action::*;
22    keymap! { Vec<Action>;
23        "<esc>" => vec![], /// Cancel
24        "<ret>" => vec![Replace(b'\n')], /// Replace with newline
25        "<tab>" => vec![Replace(b'\t')], /// Replace with tab
26        keys => {
27            if let [key] = keys
28                && let KeyCode::Char(c) = key.code
29                && key.modifiers.difference(KeyModifiers::SHIFT).is_empty()
30            {
31                KeymapResult::Fallback(vec![Replace(c)])
32            } else {
33                KeymapResult::Unmapped
34            }
35        } /// Replace with character
36    }
37});
38
39pub fn handle_actions(editor: &mut Editor, actions: &[Action]) {
40    for action in actions {
41        handle_action(editor, action);
42    }
43}
44
45pub fn handle_action(editor: &mut Editor, action: &Action) {
46    match action {
47        Action::Replace(byte) => replace(editor, *byte),
48    }
49}
50
51pub fn handle_keys(editor: &mut Editor) -> bool {
52    match KEYMAP.get_keys(&editor.pending_keys) {
53        KeymapResult::Mapped(actions) => {
54            editor.pending_keys.clear();
55            handle_actions(editor, actions);
56            normal::enter(editor);
57        }
58        KeymapResult::Fallback(actions) => {
59            editor.pending_keys.clear();
60            handle_actions(editor, &actions);
61            normal::enter(editor);
62        }
63        KeymapResult::Unmapped => {
64            editor.pending_keys.clear();
65            normal::enter(editor);
66        }
67        KeymapResult::Pending => {}
68    }
69
70    true
71}
72
73pub fn enter(editor: &mut Editor) {
74    editor.mode = Mode::Replace;
75}
76
77fn replace(editor: &mut Editor, byte: u8) {
78    if editor.focused_buffer().text.readonly {
79        editor.message = Some(Err(String::from("Buffer is readonly")));
80        editor.count = None;
81        return;
82    }
83    let mut window = editor.focused_window_mut();
84    window.selection_edit().replace_each(byte);
85    window.scroll_to_selection();
86    editor.count = None;
87}