|
| 1 | +use std::collections::HashMap; |
| 2 | + |
1 | 3 | use serde::Deserialize; |
2 | 4 |
|
3 | | -use crate::shortcut::{KeyBind, KeyBinds, Shortcut, shortcut}; |
| 5 | +use crate::config::Error; |
| 6 | +use crate::shortcut::{ |
| 7 | + Command, Commands, KeyBind, KeyBinds, Shortcut, shortcut, |
| 8 | +}; |
4 | 9 |
|
5 | 10 | #[derive(Debug, Clone, Deserialize)] |
6 | 11 | #[serde(default)] |
@@ -81,55 +86,76 @@ impl Default for Keyboard { |
81 | 86 | } |
82 | 87 |
|
83 | 88 | impl Keyboard { |
84 | | - pub fn shortcuts(&self) -> Vec<Shortcut> { |
85 | | - use crate::shortcut::Command::*; |
| 89 | + fn keybind_pairs(&self) -> Vec<(&KeyBinds, Command)> { |
| 90 | + use Command::*; |
| 91 | + vec![ |
| 92 | + (&self.move_up, MoveUp), |
| 93 | + (&self.move_down, MoveDown), |
| 94 | + (&self.move_left, MoveLeft), |
| 95 | + (&self.move_right, MoveRight), |
| 96 | + (&self.new_horizontal_buffer, NewHorizontalBuffer), |
| 97 | + (&self.new_vertical_buffer, NewVerticalBuffer), |
| 98 | + (&self.close_buffer, CloseBuffer), |
| 99 | + (&self.maximize_buffer, MaximizeBuffer), |
| 100 | + (&self.restore_buffer, RestoreBuffer), |
| 101 | + (&self.cycle_next_buffer, CycleNextBuffer), |
| 102 | + (&self.cycle_previous_buffer, CyclePreviousBuffer), |
| 103 | + (&self.leave_buffer, LeaveBuffer), |
| 104 | + (&self.toggle_nick_list, ToggleNicklist), |
| 105 | + (&self.toggle_topic, ToggleTopic), |
| 106 | + (&self.toggle_sidebar, ToggleSidebar), |
| 107 | + (&self.toggle_fullscreen, ToggleFullscreen), |
| 108 | + (&self.command_bar, CommandBar), |
| 109 | + (&self.reload_configuration, ReloadConfiguration), |
| 110 | + (&self.file_transfers, FileTransfers), |
| 111 | + (&self.logs, Logs), |
| 112 | + (&self.theme_editor, ThemeEditor), |
| 113 | + (&self.scroll_up_page, ScrollUpPage), |
| 114 | + (&self.scroll_down_page, ScrollDownPage), |
| 115 | + (&self.scroll_to_top, ScrollToTop), |
| 116 | + (&self.scroll_to_bottom, ScrollToBottom), |
| 117 | + (&self.highlights, Highlights), |
| 118 | + (&self.cycle_next_unread_buffer, CycleNextUnreadBuffer), |
| 119 | + ( |
| 120 | + &self.cycle_previous_unread_buffer, |
| 121 | + CyclePreviousUnreadBuffer, |
| 122 | + ), |
| 123 | + (&self.mark_as_read, MarkAsRead), |
| 124 | + (&self.quit_application, QuitApplication), |
| 125 | + (&self.open_config_file, OpenConfigFile), |
| 126 | + ] |
| 127 | + } |
86 | 128 |
|
87 | | - let mut shortcuts = vec![]; |
| 129 | + pub fn validate(&self) -> Result<(), Error> { |
| 130 | + let mut map: HashMap<KeyBind, Vec<Command>> = HashMap::new(); |
88 | 131 |
|
89 | | - let mut push = |key_binds: &KeyBinds, command| { |
90 | | - shortcuts.extend( |
91 | | - key_binds |
92 | | - .iter() |
93 | | - .cloned() |
94 | | - .map(|key_bind| shortcut(key_bind, command)), |
95 | | - ); |
96 | | - }; |
| 132 | + for (keybinds, command) in self.keybind_pairs() { |
| 133 | + for key in keybinds.iter() { |
| 134 | + map.entry(key.clone()).or_default().push(command); |
| 135 | + } |
| 136 | + } |
97 | 137 |
|
98 | | - push(&self.move_up, MoveUp); |
99 | | - push(&self.move_down, MoveDown); |
100 | | - push(&self.move_left, MoveLeft); |
101 | | - push(&self.move_right, MoveRight); |
102 | | - push(&self.new_horizontal_buffer, NewHorizontalBuffer); |
103 | | - push(&self.new_vertical_buffer, NewVerticalBuffer); |
104 | | - push(&self.close_buffer, CloseBuffer); |
105 | | - push(&self.maximize_buffer, MaximizeBuffer); |
106 | | - push(&self.restore_buffer, RestoreBuffer); |
107 | | - push(&self.cycle_next_buffer, CycleNextBuffer); |
108 | | - push(&self.cycle_previous_buffer, CyclePreviousBuffer); |
109 | | - push(&self.leave_buffer, LeaveBuffer); |
110 | | - push(&self.toggle_nick_list, ToggleNicklist); |
111 | | - push(&self.toggle_topic, ToggleTopic); |
112 | | - push(&self.toggle_sidebar, ToggleSidebar); |
113 | | - push(&self.toggle_fullscreen, ToggleFullscreen); |
114 | | - push(&self.command_bar, CommandBar); |
115 | | - push(&self.reload_configuration, ReloadConfiguration); |
116 | | - push(&self.file_transfers, FileTransfers); |
117 | | - push(&self.logs, Logs); |
118 | | - push(&self.theme_editor, ThemeEditor); |
119 | | - push(&self.scroll_up_page, ScrollUpPage); |
120 | | - push(&self.scroll_down_page, ScrollDownPage); |
121 | | - push(&self.scroll_to_top, ScrollToTop); |
122 | | - push(&self.scroll_to_bottom, ScrollToBottom); |
123 | | - push(&self.highlights, Highlights); |
124 | | - push(&self.cycle_next_unread_buffer, CycleNextUnreadBuffer); |
125 | | - push( |
126 | | - &self.cycle_previous_unread_buffer, |
127 | | - CyclePreviousUnreadBuffer, |
128 | | - ); |
129 | | - push(&self.mark_as_read, MarkAsRead); |
130 | | - push(&self.quit_application, QuitApplication); |
131 | | - push(&self.open_config_file, OpenConfigFile); |
| 138 | + for (key, commands) in map { |
| 139 | + if commands.len() > 1 { |
| 140 | + return Err(Error::KeyBindConflict { |
| 141 | + keybind: key, |
| 142 | + actions: Commands::from(commands), |
| 143 | + }); |
| 144 | + } |
| 145 | + } |
| 146 | + |
| 147 | + Ok(()) |
| 148 | + } |
132 | 149 |
|
133 | | - shortcuts |
| 150 | + pub fn shortcuts(&self) -> Vec<Shortcut> { |
| 151 | + self.keybind_pairs() |
| 152 | + .into_iter() |
| 153 | + .flat_map(|(keybinds, command)| { |
| 154 | + keybinds |
| 155 | + .iter() |
| 156 | + .cloned() |
| 157 | + .map(move |key_bind| shortcut(key_bind, command)) |
| 158 | + }) |
| 159 | + .collect() |
134 | 160 | } |
135 | 161 | } |
0 commit comments