reedline/utils/
query.rs

1use crate::{
2    default_emacs_keybindings, default_vi_insert_keybindings, default_vi_normal_keybindings,
3    EditCommand, Keybindings, PromptEditMode, ReedlineEvent,
4};
5use crossterm::event::KeyCode;
6use std::fmt::{Display, Formatter};
7use strum::IntoEnumIterator;
8
9struct ReedLineCrossTermKeyCode(crossterm::event::KeyCode);
10impl ReedLineCrossTermKeyCode {
11    fn iterator() -> std::slice::Iter<'static, ReedLineCrossTermKeyCode> {
12        static KEYCODE: [ReedLineCrossTermKeyCode; 19] = [
13            ReedLineCrossTermKeyCode(KeyCode::Backspace),
14            ReedLineCrossTermKeyCode(KeyCode::Enter),
15            ReedLineCrossTermKeyCode(KeyCode::Left),
16            ReedLineCrossTermKeyCode(KeyCode::Right),
17            ReedLineCrossTermKeyCode(KeyCode::Up),
18            ReedLineCrossTermKeyCode(KeyCode::Down),
19            ReedLineCrossTermKeyCode(KeyCode::Home),
20            ReedLineCrossTermKeyCode(KeyCode::End),
21            ReedLineCrossTermKeyCode(KeyCode::PageUp),
22            ReedLineCrossTermKeyCode(KeyCode::PageDown),
23            ReedLineCrossTermKeyCode(KeyCode::Tab),
24            ReedLineCrossTermKeyCode(KeyCode::BackTab),
25            ReedLineCrossTermKeyCode(KeyCode::Delete),
26            ReedLineCrossTermKeyCode(KeyCode::Insert),
27            ReedLineCrossTermKeyCode(KeyCode::F(1)),
28            ReedLineCrossTermKeyCode(KeyCode::Char(' ')),
29            ReedLineCrossTermKeyCode(KeyCode::Char('a')),
30            ReedLineCrossTermKeyCode(KeyCode::Null),
31            ReedLineCrossTermKeyCode(KeyCode::Esc),
32        ];
33        KEYCODE.iter()
34    }
35}
36
37impl Display for ReedLineCrossTermKeyCode {
38    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
39        match self {
40            ReedLineCrossTermKeyCode(kc) => match kc {
41                KeyCode::Backspace => write!(f, "Backspace"),
42                KeyCode::Enter => write!(f, "Enter"),
43                KeyCode::Left => write!(f, "Left"),
44                KeyCode::Right => write!(f, "Right"),
45                KeyCode::Up => write!(f, "Up"),
46                KeyCode::Down => write!(f, "Down"),
47                KeyCode::Home => write!(f, "Home"),
48                KeyCode::End => write!(f, "End"),
49                KeyCode::PageUp => write!(f, "PageUp"),
50                KeyCode::PageDown => write!(f, "PageDown"),
51                KeyCode::Tab => write!(f, "Tab"),
52                KeyCode::BackTab => write!(f, "BackTab"),
53                KeyCode::Delete => write!(f, "Delete"),
54                KeyCode::Insert => write!(f, "Insert"),
55                KeyCode::F(_) => write!(f, "F<number>"),
56                KeyCode::Char(' ') => write!(f, "Space"),
57                KeyCode::Char(_) => write!(f, "Char_<letter>"),
58                KeyCode::Null => write!(f, "Null"),
59                KeyCode::Esc => write!(f, "Esc"),
60                KeyCode::CapsLock => write!(f, "CapsLock"),
61                KeyCode::ScrollLock => write!(f, "ScrollLock"),
62                KeyCode::NumLock => write!(f, "NumLock"),
63                KeyCode::PrintScreen => write!(f, "PrintScreen"),
64                KeyCode::Pause => write!(f, "Pause"),
65                KeyCode::Menu => write!(f, "Menu"),
66                KeyCode::KeypadBegin => write!(f, "KeypadBegin"),
67                KeyCode::Media(_) => write!(f, "Media<media>"),
68                KeyCode::Modifier(_) => write!(f, "Modifier<modifier>"),
69            },
70        }
71    }
72}
73
74/// Return a `Vec` of the Reedline Keybinding Modifiers
75pub fn get_reedline_keybinding_modifiers() -> Vec<String> {
76    vec![
77        "Alt".to_string(),
78        "Control".to_string(),
79        "Shift".to_string(),
80        "None".to_string(),
81        "Shift_Alt".to_string(),
82        "Alt_Shift".to_string(),
83        "Control_Shift".to_string(),
84        "Shift_Control".to_string(),
85        "Control_Alt".to_string(),
86        "Alt_Control".to_string(),
87        "Control_Alt_Shift".to_string(),
88        "Control_Shift_Alt".to_string(),
89    ]
90}
91
92/// Return a `Vec<String>` of the Reedline [`PromptEditMode`]s
93pub fn get_reedline_prompt_edit_modes() -> Vec<String> {
94    PromptEditMode::iter().map(|em| em.to_string()).collect()
95}
96
97/// Return a `Vec<String>` of the Reedline `KeyCode`s
98pub fn get_reedline_keycodes() -> Vec<String> {
99    ReedLineCrossTermKeyCode::iterator()
100        .map(|kc| format!("{kc}"))
101        .collect()
102}
103
104/// Return a `Vec<String>` of the Reedline [`ReedlineEvent`]s
105pub fn get_reedline_reedline_events() -> Vec<String> {
106    ReedlineEvent::iter().map(|rle| rle.to_string()).collect()
107}
108
109/// Return a `Vec<String>` of the Reedline [`EditCommand`]s
110pub fn get_reedline_edit_commands() -> Vec<String> {
111    EditCommand::iter().map(|edit| edit.to_string()).collect()
112}
113
114/// Get the default keybindings and return a `Vec<(String, String, String, String)>`
115/// where String 1 is `mode`, String 2 is `key_modifiers`, String 3 is `key_code`, and
116/// Sting 4 is `event`
117pub fn get_reedline_default_keybindings() -> Vec<(String, String, String, String)> {
118    let options = vec![
119        ("emacs", default_emacs_keybindings()),
120        ("vi_normal", default_vi_normal_keybindings()),
121        ("vi_insert", default_vi_insert_keybindings()),
122    ];
123
124    options
125        .into_iter()
126        .flat_map(|(mode, keybindings)| get_keybinding_strings(mode, &keybindings))
127        .collect()
128}
129
130fn get_keybinding_strings(
131    mode: &str,
132    keybindings: &Keybindings,
133) -> Vec<(String, String, String, String)> {
134    let mut data: Vec<(String, String, String, String)> = keybindings
135        .get_keybindings()
136        .iter()
137        .map(|(combination, event)| {
138            (
139                mode.to_string(),
140                format!("{:?}", combination.modifier),
141                format!("{:?}", combination.key_code),
142                format!("{event:?}"),
143            )
144        })
145        .collect();
146
147    data.sort();
148
149    data
150}