minime/editor/
keybindings.rs1use crate::{editor::Editor, renderer::Renderer, Result};
2
3use crossterm::event::{read, Event, KeyCode, KeyEvent, KeyModifiers};
4
5pub trait Keybinding {
7 fn read(&self, editor: &mut Editor<impl Renderer>) -> Result<bool>;
9}
10
11pub struct NormalKeybinding;
13
14impl Keybinding for NormalKeybinding {
15 fn read(&self, editor: &mut Editor<impl Renderer>) -> Result<bool> {
16 let key_event = read()?;
17 match key_event {
18 Event::Key(k) => Self::process_key_event(editor, k),
19 _ => Ok(true),
20 }
21 }
22}
23
24impl NormalKeybinding {
25 fn process_key_event(editor: &mut Editor<impl Renderer>, event: KeyEvent) -> Result<bool> {
26 let code = event.code;
27 let ln_count = editor.line_count();
28 let shifted = event.modifiers.contains(KeyModifiers::SHIFT);
30 let alt = event.modifiers.contains(KeyModifiers::ALT);
31 let control = event.modifiers.contains(KeyModifiers::CONTROL);
32
33 match code {
34 KeyCode::Down => editor.move_down(shifted),
39 KeyCode::Up => editor.move_up(shifted),
40 KeyCode::Left => editor.move_left(shifted),
41 KeyCode::Right => editor.move_right(shifted),
42
43 KeyCode::Home => {
44 let leading_spaces = editor
45 .curr_ln_chars()
46 .take_while(|c| c.is_whitespace())
47 .count();
48 if editor.focus.col == leading_spaces {
49 editor.move_to_col(0, shifted);
50 } else {
51 editor.move_to_col(leading_spaces, shifted);
52 }
53 }
54 KeyCode::End => editor.move_to_line_end(shifted),
55
56 KeyCode::Backspace => editor.backspace(),
57 KeyCode::Char('h') if control => editor.backspace(),
58 KeyCode::Delete => editor.delete(),
59
60 #[cfg(feature = "unstable")]
61 KeyCode::Char('c') if control => {
62 if let Ok(mut clipboard) = arboard::Clipboard::new() {
63 if let Some(txt) = editor.curr_sel() {
64 clipboard.set_text(txt.to_string()).unwrap();
65 } else {
66 clipboard.set_text(editor.curr_ln().to_string()).unwrap();
67 }
68 }
69 }
70 #[cfg(feature = "unstable")]
71 KeyCode::Char('x') if control => {
72 if let Ok(mut clipboard) = arboard::Clipboard::new() {
73 if let Some(txt) = editor.curr_sel() {
74 clipboard.set_text(txt.to_string()).unwrap();
75 editor.delete();
76 } else {
77 clipboard.set_text(editor.remove_line(editor.focus.ln)).unwrap();
78 }
79 }
80 }
81 #[cfg(feature = "unstable")]
82 KeyCode::Char('v') if control => {
83 if let Ok(mut clipboard) = arboard::Clipboard::new() {
84 if let Ok(txt) = clipboard.get_text() {
85 editor.insert_str(&txt);
86 }
87 }
88 }
89
90 KeyCode::Tab => {
91 editor.clamp();
92 let soft = 4 - editor.focus.col % 4;
93 for _ in 0..soft {
94 editor.insert_char(0, ' ');
95 }
96 editor.focus.col += soft;
97 }
98 KeyCode::BackTab => {
99 editor.clamp();
100
101 let leading_spaces = editor
102 .curr_ln_chars()
103 .take(4)
104 .take_while(|c| c.is_whitespace())
105 .count();
106
107 editor.delete_ln_range(0, leading_spaces);
108 }
109 KeyCode::Esc => return Ok(false),
110 KeyCode::Enter => {
111 if !alt && editor.curr_ln_len() == 0 && editor.focus.ln + 1 == ln_count {
112 return Ok(false);
113 } else {
114 editor.type_char('\n');
115 }
116 }
117 KeyCode::Char(c) => editor.type_char(c),
118 _ => { }
119 }
120 Ok(true)
121 }
122}
123
124#[doc(hidden)]
125pub struct DebugKeybinding;
126
127impl Keybinding for DebugKeybinding {
128 fn read(&self, editor: &mut Editor<impl Renderer>) -> Result<bool> {
129 let key_event = read()?;
130 match key_event {
131 Event::Key(k) => Self::process_key_event(editor, k),
132 _ => Ok(true),
133 }
134 }
135}
136
137impl DebugKeybinding {
138 fn process_key_event(editor: &mut Editor<impl Renderer>, event: KeyEvent) -> Result<bool> {
139 let code = event.code;
140 match code {
141 KeyCode::Esc => return Ok(false),
142 _ => editor.insert_str(&format!("{:#?}", event)),
143 }
144 Ok(true)
145 }
146}