]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[dynui] Allow for duplicate shortcut keys
authorMichael Brown <mcb30@ipxe.org>
Thu, 26 Feb 2026 12:28:50 +0000 (12:28 +0000)
committerMichael Brown <mcb30@ipxe.org>
Thu, 26 Feb 2026 12:28:50 +0000 (12:28 +0000)
When searching for a shortcut key, search first from the currently
selected menu item and then from the start of the list.

This allows several ways for a shortcut key to be meaningfully used
multiple times within the same menu.  For example, two sections may
have the same shortcut key:

  item --key s --gap (S)ection 1
  item ...
  item ...
  item --key s --gap (S)ection 2
  item ...

With the above menu, repeated "s" keypresses would cycle through the
sections.

As another example, entries within different sections may have the
same shortcut keys.  For example:

  item --key d --gap (D)ebian
  item --key s debst Debian (s)table release
  item --key u debun Debian (u)nstable release
  item --key f --gap (F)edora
  item --key s fedst Fedora (s)table release
  item --key u fedun Fedora (u)nstable release

With the above menu, a shortcut key sequence such as "f", "s" can be
used to select an entry within a specific section, avoiding the need
to choose shortcut keys that are globally unique within the menu.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/core/dynui.c
src/hci/tui/form_ui.c
src/hci/tui/menu_ui.c
src/include/ipxe/dynui.h

index c2af95f86b76720d2629e6efe94f6ea49759086a..921716a72316b8eb7a39d38d221591a447fa163b 100644 (file)
@@ -207,15 +207,26 @@ struct dynamic_item * dynui_item ( struct dynamic_ui *dynui,
  *
  * @v dynui            Dynamic user interface
  * @v key              Shortcut key
+ * @v index            Starting index
  * @ret item           User interface item, or NULL if not found
  */
-struct dynamic_item * dynui_shortcut ( struct dynamic_ui *dynui, int key ) {
+struct dynamic_item * dynui_shortcut ( struct dynamic_ui *dynui, int key,
+                                      unsigned int index ) {
        struct dynamic_item *item;
 
+       /* Do nothing unless shortcut key is set */
+       if ( ! key )
+               return NULL;
+
+       /* Search from current list index */
        list_for_each_entry ( item, &dynui->items, list ) {
-               if ( key && ( key == item->shortcut ) )
+               if ( ( key == item->shortcut ) && ( item->index >= index ) )
                        return item;
        }
 
+       /* If not found, search again from start of list */
+       if ( index )
+               return dynui_shortcut ( dynui, key, 0 );
+
        return NULL;
 }
index 2bce952fa81f1b74fa46f2399561976f69aa58c5..9fa0dbd12ef4d56bbc3ede7247899cada741883d 100644 (file)
@@ -480,7 +480,8 @@ static int form_loop ( struct form *form ) {
                        break;
                default:
                        /* Move to input with matching shortcut key, if any */
-                       item = dynui_shortcut ( form->dynui, key );
+                       item = dynui_shortcut ( form->dynui, key,
+                                               scroll->current );
                        if ( item ) {
                                scroll->current = item->index;
                                if ( ! item->name )
index f789a298f0001689bb118f050f342122cfe09c48..b085be1bdbe15c94c493dd4a00d4955654c8deeb 100644 (file)
@@ -200,7 +200,8 @@ static int menu_loop ( struct menu_ui *ui, struct dynamic_item **selected ) {
                                chosen = 1;
                                break;
                        default:
-                               item = dynui_shortcut ( ui->dynui, key );
+                               item = dynui_shortcut ( ui->dynui, key,
+                                                       ui->scroll.current );
                                if ( item ) {
                                        ui->scroll.current = item->index;
                                        if ( item->name ) {
index e50c6ab49abcf9695114171ce460f5751b2d33e7..2dd23873d04ab9ebbe8eb662d1b9ef2c9ca94edd 100644 (file)
@@ -59,7 +59,7 @@ extern struct dynamic_ui * find_dynui ( const char *name );
 extern struct dynamic_item * dynui_item ( struct dynamic_ui *dynui,
                                          unsigned int index );
 extern struct dynamic_item * dynui_shortcut ( struct dynamic_ui *dynui,
-                                             int key );
+                                             int key, unsigned int index );
 extern int show_menu ( struct dynamic_ui *dynui, unsigned long timeout,
                       unsigned long retimeout, const char *select,
                       struct dynamic_item **selected );