1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use std::hash::Hash;

use crossterm::event::{KeyCode, ModifierKeyCode};

#[derive(Debug, Clone)]
pub struct HelpText {
    button: Vec<KeyCode>,
    title: String,
}

impl Eq for HelpText {}

impl PartialEq for HelpText {
    fn eq(&self, other: &Self) -> bool {
        self.title == other.title
    }
}

/// char('s') -> solve, char('s') -> show_solution  is not possible.
/// Hence hashing only button values so that multiple actions cannot point to single key
impl Hash for HelpText {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        self.button.hash(state);
    }
}

impl HelpText {
    pub fn get_keys(&self) -> std::slice::Iter<KeyCode> {
        self.button.iter()
    }
}

impl HelpText {
    pub fn new(title: String, button: Vec<KeyCode>) -> Self {
        Self { button, title }
    }
    fn get_symbol_by_keycode(k: &KeyCode) -> String {
        match k {
            KeyCode::Backspace => "⌫ ".to_string(),
            KeyCode::Enter => "⏎".to_string(),
            KeyCode::Left => "←".to_string(),
            KeyCode::Right => "→".to_string(),
            KeyCode::Up => "↑".to_string(),
            KeyCode::Down => "↓".to_string(),
            KeyCode::Home => "⤒".to_string(),
            KeyCode::End => "⤓".to_string(),
            KeyCode::PageUp => "⇞".to_string(),
            KeyCode::PageDown => "⇟".to_string(),
            KeyCode::Tab => "⇥".to_string(),
            KeyCode::BackTab => "⇤".to_string(),
            KeyCode::Delete => "⌦ ".to_string(),
            KeyCode::Insert => "⎀".to_string(),
            KeyCode::F(n) => format!("F{}", n),
            KeyCode::Char(c) => c.to_string(),
            KeyCode::Null => "∅".to_string(),
            KeyCode::Esc => "⎋".to_string(),
            KeyCode::CapsLock => "⇪".to_string(),
            KeyCode::ScrollLock => "⤓".to_string(),
            KeyCode::NumLock => "⇭".to_string(),
            KeyCode::PrintScreen => "⎙".to_string(),
            KeyCode::Pause => "⏸".to_string(),
            KeyCode::Menu => "☰".to_string(),
            KeyCode::KeypadBegin => "⎆".to_string(),
            KeyCode::Media(_) => "☊".to_string(),
            KeyCode::Modifier(modifier) => match modifier {
                ModifierKeyCode::LeftShift => "⇧".to_string(),
                ModifierKeyCode::LeftControl => "⌃".to_string(),
                ModifierKeyCode::LeftAlt => "⌥".to_string(),
                ModifierKeyCode::LeftSuper => "⌘".to_string(),
                ModifierKeyCode::LeftHyper => "⎇".to_string(),
                ModifierKeyCode::LeftMeta => "⌘".to_string(),
                ModifierKeyCode::RightShift => "⇧".to_string(),
                ModifierKeyCode::RightControl => "⌃".to_string(),
                ModifierKeyCode::RightAlt => "⌥".to_string(),
                ModifierKeyCode::RightSuper => "⌘".to_string(),
                ModifierKeyCode::RightHyper => "⎇".to_string(),
                ModifierKeyCode::RightMeta => "⌘".to_string(),
                ModifierKeyCode::IsoLevel3Shift => "ISO Level3 Shift".to_string(),
                ModifierKeyCode::IsoLevel5Shift => "ISO Level5 Shift".to_string(),
            },
        }
    }
}

impl From<&HelpText> for String {
    fn from(value: &HelpText) -> Self {
        let symbols = value
            .button
            .iter()
            .map(HelpText::get_symbol_by_keycode)
            .collect::<String>();
        format!("{}[{}]", value.title, symbols,)
    }
}

pub(crate) enum CommonHelpText {
    ScrollUp,
    ScrollDown,
    SwitchPane,
    Edit,
    ReadContent,
    Submit,
    Run,
    Close,
    Select,
    Search,
}

impl From<CommonHelpText> for HelpText {
    fn from(value: CommonHelpText) -> Self {
        let (k, t) = match value {
            CommonHelpText::ScrollUp => (vec![KeyCode::Up], "Up"),
            CommonHelpText::ScrollDown => (vec![KeyCode::Down], "Down"),
            CommonHelpText::SwitchPane => (vec![KeyCode::Left, KeyCode::Right], "Switch Pane"),
            CommonHelpText::Edit => (vec![KeyCode::Char('E'), KeyCode::Char('e')], "Edit"),
            CommonHelpText::ReadContent => (vec![KeyCode::Enter], "Read Content"),
            CommonHelpText::Close => (vec![KeyCode::Esc], "Close"),
            CommonHelpText::Select => (vec![KeyCode::Enter], "Select"),
            CommonHelpText::Submit => (vec![KeyCode::Char('s')], "Submit"),
            CommonHelpText::Run => (vec![KeyCode::Char('R'), KeyCode::Char('r')], "Run"),
            CommonHelpText::Search => (vec![KeyCode::Char('/')], "Search"),
        };
        HelpText {
            button: k,
            title: t.to_string(),
        }
    }
}