@@ -6,10 +6,14 @@ use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
66pub enum KeyAction {
77 Quit ,
88 OpenFilterMenu ,
9+ OpenHelp ,
910 StartSearch ,
1011 NewUser ,
12+ DeleteSelection ,
1113 SwitchTab ,
1214 ToggleUsersFocus ,
15+ ToggleGroupsFocus ,
16+ ToggleKeybindsPane ,
1317 EnterAction ,
1418 MoveUp ,
1519 MoveDown ,
@@ -37,21 +41,32 @@ impl Keymap {
3741 bindings. insert ( ( M :: NONE , Char ( 'f' ) ) , KeyAction :: OpenFilterMenu ) ;
3842 bindings. insert ( ( M :: NONE , Char ( '/' ) ) , KeyAction :: StartSearch ) ;
3943 bindings. insert ( ( M :: NONE , Char ( 'n' ) ) , KeyAction :: NewUser ) ;
44+ bindings. insert ( ( M :: NONE , Char ( '?' ) ) , KeyAction :: OpenHelp ) ;
45+ bindings. insert ( ( M :: NONE , KeyCode :: Delete ) , KeyAction :: DeleteSelection ) ;
4046 bindings. insert ( ( M :: NONE , Tab ) , KeyAction :: SwitchTab ) ;
4147 // Shift+Tab is BackTab in crossterm
4248 bindings. insert ( ( M :: NONE , BackTab ) , KeyAction :: ToggleUsersFocus ) ;
49+ // Some terminals report BackTab with SHIFT modifier, and some send Tab+SHIFT
50+ bindings. insert ( ( M :: SHIFT , BackTab ) , KeyAction :: ToggleUsersFocus ) ;
51+ bindings. insert ( ( M :: SHIFT , Tab ) , KeyAction :: ToggleUsersFocus ) ;
52+ // Ctrl+Tab no longer toggles panes in Groups
4353
4454 bindings. insert ( ( M :: NONE , Enter ) , KeyAction :: EnterAction ) ;
4555 // Navigation
4656 bindings. insert ( ( M :: NONE , Up ) , KeyAction :: MoveUp ) ;
4757 bindings. insert ( ( M :: NONE , Down ) , KeyAction :: MoveDown ) ;
4858 bindings. insert ( ( M :: NONE , Left ) , KeyAction :: MoveLeftPage ) ;
4959 bindings. insert ( ( M :: NONE , Right ) , KeyAction :: MoveRightPage ) ;
50- // Vim keys
60+ // Vim-like keys
5161 bindings. insert ( ( M :: NONE , Char ( 'k' ) ) , KeyAction :: MoveUp ) ;
5262 bindings. insert ( ( M :: NONE , Char ( 'j' ) ) , KeyAction :: MoveDown ) ;
5363 bindings. insert ( ( M :: NONE , Char ( 'h' ) ) , KeyAction :: MoveLeftPage ) ;
5464 bindings. insert ( ( M :: NONE , Char ( 'l' ) ) , KeyAction :: MoveRightPage ) ;
65+ // Toggle keybindings pane (support Shift+K variants across terminals)
66+ bindings. insert ( ( M :: SHIFT , Char ( 'k' ) ) , KeyAction :: ToggleKeybindsPane ) ;
67+ bindings. insert ( ( M :: SHIFT , Char ( 'K' ) ) , KeyAction :: ToggleKeybindsPane ) ;
68+ bindings. insert ( ( M :: NONE , Char ( 'K' ) ) , KeyAction :: ToggleKeybindsPane ) ;
69+
5570 // Page keys
5671 bindings. insert ( ( M :: NONE , PageUp ) , KeyAction :: PageUp ) ;
5772 bindings. insert ( ( M :: NONE , PageDown ) , KeyAction :: PageDown ) ;
@@ -106,8 +121,9 @@ impl Keymap {
106121 let mut buf = String :: new ( ) ;
107122 buf. push_str ( "# usrgrp-manager keybindings\n " ) ;
108123 buf. push_str ( "# Format: <Action> = <KeySpec>\n " ) ;
109- buf. push_str ( "# KeySpec examples: q, Ctrl+q, Enter, Esc, Tab, BackTab, Up, Down, Left, Right, PageUp, PageDown, /, n, f, j, k, h, l\n " ) ;
110- buf. push_str ( "# Actions: Quit, OpenFilterMenu, StartSearch, NewUser, SwitchTab, ToggleUsersFocus, EnterAction, MoveUp, MoveDown, MoveLeftPage, MoveRightPage, PageUp, PageDown, Ignore\n \n " ) ;
124+ buf. push_str ( "# KeySpec examples: q, Ctrl+q, Enter, Esc, Tab, BackTab, Up, Down, Left, Right, PageUp, PageDown, Delete, /, n, f, j, k, h, l\n " ) ;
125+ buf. push_str ( "# Actions: Quit, OpenFilterMenu, StartSearch, NewUser, DeleteSelection, SwitchTab, ToggleUsersFocus, ToggleGroupsFocus, ToggleKeybindsPane, EnterAction, MoveUp, MoveDown, MoveLeftPage, MoveRightPage, PageUp, PageDown, Ignore\n \n " ) ;
126+ buf. push_str ( "# Additional: OpenHelp (mapped to '?')\n \n " ) ;
111127
112128 // Emit a stable, readable subset of current bindings
113129 let dump = [
@@ -118,6 +134,7 @@ impl Keymap {
118134 ( "n" , KeyAction :: NewUser ) ,
119135 ( "Tab" , KeyAction :: SwitchTab ) ,
120136 ( "BackTab" , KeyAction :: ToggleUsersFocus ) ,
137+ ( "?" , KeyAction :: OpenHelp ) ,
121138 ( "Enter" , KeyAction :: EnterAction ) ,
122139 ( "Up" , KeyAction :: MoveUp ) ,
123140 ( "Down" , KeyAction :: MoveDown ) ,
@@ -129,6 +146,7 @@ impl Keymap {
129146 ( "l" , KeyAction :: MoveRightPage ) ,
130147 ( "PageUp" , KeyAction :: PageUp ) ,
131148 ( "PageDown" , KeyAction :: PageDown ) ,
149+ ( "Delete" , KeyAction :: DeleteSelection ) ,
132150 ] ;
133151 for ( k, a) in dump {
134152 let _ = writeln ! ( & mut buf, "{} = {}" , format_action( a) , k) ;
@@ -142,6 +160,40 @@ impl Keymap {
142160 let code = key. code ;
143161 self . bindings . get ( & ( mm, code) ) . copied ( )
144162 }
163+
164+ /// Return a snapshot of all bindings as ((modifiers, code), action) pairs.
165+ pub fn all_bindings ( & self ) -> Vec < ( ( KeyModifiers , KeyCode ) , KeyAction ) > {
166+ self . bindings . iter ( ) . map ( |( k, v) | ( * k, * v) ) . collect ( )
167+ }
168+
169+ /// Format a key (modifiers + code) into a human-readable spec like "Ctrl+q", "BackTab".
170+ pub fn format_key ( mods : KeyModifiers , code : KeyCode ) -> String {
171+ use KeyCode :: * ;
172+ let base = match code {
173+ Enter => "Enter" . to_string ( ) ,
174+ Delete => "Delete" . to_string ( ) ,
175+ Esc => "Esc" . to_string ( ) ,
176+ Tab => "Tab" . to_string ( ) ,
177+ BackTab => "BackTab" . to_string ( ) ,
178+ Up => "Up" . to_string ( ) ,
179+ Down => "Down" . to_string ( ) ,
180+ Left => "Left" . to_string ( ) ,
181+ Right => "Right" . to_string ( ) ,
182+ PageUp => "PageUp" . to_string ( ) ,
183+ PageDown => "PageDown" . to_string ( ) ,
184+ Char ( '/' ) => "/" . to_string ( ) ,
185+ Char ( c) => c. to_string ( ) ,
186+ _ => format ! ( "{:?}" , code) ,
187+ } ;
188+ if mods. contains ( KeyModifiers :: CONTROL ) {
189+ format ! ( "Ctrl+{}" , base)
190+ } else if mods. is_empty ( ) {
191+ base
192+ } else {
193+ // Future: format other modifiers when supported
194+ base
195+ }
196+ }
145197}
146198
147199impl Default for Keymap {
@@ -162,6 +214,7 @@ fn parse_key(spec: &str) -> Option<(KeyModifiers, KeyCode)> {
162214 // Future: Alt+ / Shift+
163215 let code = match rest {
164216 "Enter" => Enter ,
217+ "Delete" => Delete ,
165218 "/" => Char ( '/' ) ,
166219 "Esc" | "Escape" => Esc ,
167220 "Tab" => Tab ,
@@ -188,10 +241,14 @@ fn parse_action(s: &str) -> Option<KeyAction> {
188241 match s. trim ( ) {
189242 "Quit" => Some ( KeyAction :: Quit ) ,
190243 "OpenFilterMenu" => Some ( KeyAction :: OpenFilterMenu ) ,
244+ "OpenHelp" => Some ( KeyAction :: OpenHelp ) ,
191245 "StartSearch" => Some ( KeyAction :: StartSearch ) ,
192246 "NewUser" => Some ( KeyAction :: NewUser ) ,
247+ "DeleteSelection" => Some ( KeyAction :: DeleteSelection ) ,
193248 "SwitchTab" => Some ( KeyAction :: SwitchTab ) ,
194249 "ToggleUsersFocus" => Some ( KeyAction :: ToggleUsersFocus ) ,
250+ "ToggleGroupsFocus" => Some ( KeyAction :: ToggleGroupsFocus ) ,
251+ "ToggleKeybindsPane" => Some ( KeyAction :: ToggleKeybindsPane ) ,
195252 "EnterAction" => Some ( KeyAction :: EnterAction ) ,
196253 "MoveUp" => Some ( KeyAction :: MoveUp ) ,
197254 "MoveDown" => Some ( KeyAction :: MoveDown ) ,
@@ -204,14 +261,18 @@ fn parse_action(s: &str) -> Option<KeyAction> {
204261 }
205262}
206263
207- fn format_action ( a : KeyAction ) -> & ' static str {
264+ pub fn format_action ( a : KeyAction ) -> & ' static str {
208265 match a {
209266 KeyAction :: Quit => "Quit" ,
210267 KeyAction :: OpenFilterMenu => "OpenFilterMenu" ,
268+ KeyAction :: OpenHelp => "OpenHelp" ,
211269 KeyAction :: StartSearch => "StartSearch" ,
212270 KeyAction :: NewUser => "NewUser" ,
271+ KeyAction :: DeleteSelection => "DeleteSelection" ,
213272 KeyAction :: SwitchTab => "SwitchTab" ,
214273 KeyAction :: ToggleUsersFocus => "ToggleUsersFocus" ,
274+ KeyAction :: ToggleGroupsFocus => "ToggleGroupsFocus" ,
275+ KeyAction :: ToggleKeybindsPane => "ToggleKeybindsPane" ,
215276 KeyAction :: EnterAction => "EnterAction" ,
216277 KeyAction :: MoveUp => "MoveUp" ,
217278 KeyAction :: MoveDown => "MoveDown" ,
0 commit comments