1use tui_textarea::Input as TextAreaInput;
2
3#[derive(Clone, Debug)]
4pub enum Input {
5 Key(KeyEvent),
6 Paste(String),
7 Resize(u16, u16),
8}
9
10#[derive(Clone, Debug)]
11pub struct KeyEvent {
12 pub code: KeyCode,
13 pub modifiers: KeyModifiers,
14 pub kind: KeyEventKind,
15}
16
17#[derive(Clone, Copy, Debug, PartialEq, Eq)]
18pub enum KeyCode {
19 Char(char),
20 F(u8),
21 Backspace,
22 Enter,
23 Left,
24 Right,
25 Up,
26 Down,
27 Tab,
28 Delete,
29 Home,
30 End,
31 PageUp,
32 PageDown,
33 Esc,
34 Null,
35}
36
37#[derive(Clone, Copy, Debug, PartialEq, Eq)]
38pub enum KeyEventKind {
39 Press,
40 Release,
41 Repeat,
42}
43
44#[derive(Clone, Copy, Debug, PartialEq, Eq)]
45pub struct KeyModifiers {
46 pub ctrl: bool,
47 pub alt: bool,
48 pub shift: bool,
49}
50
51impl KeyModifiers {
52 pub const NONE: Self = Self {
53 ctrl: false,
54 alt: false,
55 shift: false,
56 };
57
58 pub const CONTROL: Self = Self {
59 ctrl: true,
60 alt: false,
61 shift: false,
62 };
63
64 pub fn new(ctrl: bool, alt: bool, shift: bool) -> Self {
65 Self { ctrl, alt, shift }
66 }
67}
68
69impl Default for KeyModifiers {
70 fn default() -> Self {
71 Self::NONE
72 }
73}
74
75#[cfg(not(target_arch = "wasm32"))]
76mod native {
77 use super::*;
78 use ratatui::crossterm::event as ct;
79
80 impl From<ct::Event> for Input {
81 fn from(event: ct::Event) -> Self {
82 match event {
83 ct::Event::Key(key) => Input::Key(key.into()),
84 ct::Event::Paste(paste) => Input::Paste(paste),
85 ct::Event::Resize(w, h) => Input::Resize(w, h),
86 _ => Input::Resize(0, 0),
87 }
88 }
89 }
90
91 impl From<ct::KeyEvent> for KeyEvent {
92 fn from(key: ct::KeyEvent) -> Self {
93 let modifiers = KeyModifiers::new(
94 key.modifiers.contains(ct::KeyModifiers::CONTROL),
95 key.modifiers.contains(ct::KeyModifiers::ALT),
96 key.modifiers.contains(ct::KeyModifiers::SHIFT),
97 );
98
99 let code = match key.code {
100 ct::KeyCode::Char(c) => KeyCode::Char(c),
101 ct::KeyCode::F(n) => KeyCode::F(n),
102 ct::KeyCode::Backspace => KeyCode::Backspace,
103 ct::KeyCode::Enter => KeyCode::Enter,
104 ct::KeyCode::Left => KeyCode::Left,
105 ct::KeyCode::Right => KeyCode::Right,
106 ct::KeyCode::Up => KeyCode::Up,
107 ct::KeyCode::Down => KeyCode::Down,
108 ct::KeyCode::Tab => KeyCode::Tab,
109 ct::KeyCode::Delete => KeyCode::Delete,
110 ct::KeyCode::Home => KeyCode::Home,
111 ct::KeyCode::End => KeyCode::End,
112 ct::KeyCode::PageUp => KeyCode::PageUp,
113 ct::KeyCode::PageDown => KeyCode::PageDown,
114 ct::KeyCode::Esc => KeyCode::Esc,
115 _ => KeyCode::Null,
116 };
117
118 let kind = match key.kind {
119 ct::KeyEventKind::Press => KeyEventKind::Press,
120 ct::KeyEventKind::Release => KeyEventKind::Release,
121 ct::KeyEventKind::Repeat => KeyEventKind::Repeat,
122 };
123
124 KeyEvent {
125 code,
126 modifiers,
127 kind,
128 }
129 }
130 }
131}
132
133#[cfg(target_arch = "wasm32")]
134mod wasm {
135 use super::*;
136 use ratzilla::event as rz;
137
138 impl From<rz::KeyEvent> for KeyEvent {
139 fn from(event: rz::KeyEvent) -> Self {
140 let code = match event.code {
141 rz::KeyCode::Char(c) => KeyCode::Char(c),
142 rz::KeyCode::F(n) => KeyCode::F(n),
143 rz::KeyCode::Backspace => KeyCode::Backspace,
144 rz::KeyCode::Enter => KeyCode::Enter,
145 rz::KeyCode::Left => KeyCode::Left,
146 rz::KeyCode::Right => KeyCode::Right,
147 rz::KeyCode::Up => KeyCode::Up,
148 rz::KeyCode::Down => KeyCode::Down,
149 rz::KeyCode::Tab => KeyCode::Tab,
150 rz::KeyCode::Delete => KeyCode::Delete,
151 rz::KeyCode::Home => KeyCode::Home,
152 rz::KeyCode::End => KeyCode::End,
153 rz::KeyCode::PageUp => KeyCode::PageUp,
154 rz::KeyCode::PageDown => KeyCode::PageDown,
155 rz::KeyCode::Esc => KeyCode::Esc,
156 rz::KeyCode::Unidentified => KeyCode::Null,
157 };
158
159 KeyEvent {
160 code,
161 modifiers: KeyModifiers::new(event.ctrl, event.alt, event.shift),
162 kind: KeyEventKind::Press,
163 }
164 }
165 }
166}
167
168pub fn to_textarea_input(input: &Input) -> Option<TextAreaInput> {
169 match input {
170 Input::Key(key) => Some(key_to_textarea_input(key)),
171 _ => None,
172 }
173}
174
175pub fn key_to_textarea_input(key: &KeyEvent) -> TextAreaInput {
176 use tui_textarea::Key;
177
178 let key_code = match key.code {
179 KeyCode::Char(c) => Key::Char(c),
180 KeyCode::F(n) => Key::F(n),
181 KeyCode::Backspace => Key::Backspace,
182 KeyCode::Enter => Key::Enter,
183 KeyCode::Left => Key::Left,
184 KeyCode::Right => Key::Right,
185 KeyCode::Up => Key::Up,
186 KeyCode::Down => Key::Down,
187 KeyCode::Tab => Key::Tab,
188 KeyCode::Delete => Key::Delete,
189 KeyCode::Home => Key::Home,
190 KeyCode::End => Key::End,
191 KeyCode::PageUp => Key::PageUp,
192 KeyCode::PageDown => Key::PageDown,
193 KeyCode::Esc => Key::Esc,
194 KeyCode::Null => Key::Null,
195 };
196
197 TextAreaInput {
198 key: key_code,
199 ctrl: key.modifiers.ctrl,
200 alt: key.modifiers.alt,
201 shift: key.modifiers.shift,
202 }
203}