aboutsummaryrefslogtreecommitdiff
path: root/src/hci
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2024-06-20 14:24:53 -0700
committerMichael Brown <mcb30@ipxe.org>2024-06-20 14:26:06 -0700
commit5719cde838b6e86a02831373dae81642653b872f (patch)
treee4159ca36ce356a80df7909dfabeaececc6fefdc /src/hci
parent122777f789a68512593e4aa6da3ace3d0d8664ec (diff)
downloadipxe-5719cde838b6e86a02831373dae81642653b872f.zip
ipxe-5719cde838b6e86a02831373dae81642653b872f.tar.gz
ipxe-5719cde838b6e86a02831373dae81642653b872f.tar.bz2
[dynui] Generalise the concept of a menu to a dynamic user interface
We currently have an abstract model of a dynamic menu as a list of items, each of which has a name, a description, and assorted metadata such as a shortcut key. The "menu" and "item" commands construct representations in this abstract model, and the "choose" command then presents the items as a single-choice menu, with the selected item's name used as the output value. This same abstraction may be used to model a dynamic form as a list of editable items, each of which has a corresponding setting name, an optional description label, and assorted metadata such as a shortcut key. By defining a "form" command as an alias for the "menu" command, we could construct and present forms using commands such as: #!ipxe form Login to ${url} item username Username or email address item --secret password Password present or #!ipxe form Configure IPv4 networking for ${netX/ifname} item netX/ip IPv4 address item netX/netmask Subnet mask item netX/gateway Gateway address item netX/dns DNS server address present Reusing the same abstract model for both menus and forms allows us to minimise the increase in code size, since the implementation of the "form" and "item" commands is essentially zero-cost. Rename everything within the abstract data model from "menu" to "dynamic user interface" to reflect this generalisation. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/hci')
-rw-r--r--src/hci/commands/dynui_cmd.c (renamed from src/hci/commands/menu_cmd.c)109
-rw-r--r--src/hci/tui/menu_ui.c43
2 files changed, 77 insertions, 75 deletions
diff --git a/src/hci/commands/menu_cmd.c b/src/hci/commands/dynui_cmd.c
index 8b6d2a9..dbaa669 100644
--- a/src/hci/commands/menu_cmd.c
+++ b/src/hci/commands/dynui_cmd.c
@@ -25,7 +25,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** @file
*
- * Menu commands
+ * Dynamic user interface commands
*
*/
@@ -34,7 +34,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <string.h>
#include <errno.h>
#include <getopt.h>
-#include <ipxe/menu.h>
+#include <ipxe/dynui.h>
#include <ipxe/command.h>
#include <ipxe/parseopt.h>
#include <ipxe/settings.h>
@@ -42,42 +42,42 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
FEATURE ( FEATURE_MISC, "Menu", DHCP_EB_FEATURE_MENU, 1 );
-/** "menu" options */
-struct menu_options {
+/** "dynui" options */
+struct dynui_options {
/** Name */
char *name;
/** Delete */
int delete;
};
-/** "menu" option list */
-static struct option_descriptor menu_opts[] = {
+/** "dynui" option list */
+static struct option_descriptor dynui_opts[] = {
OPTION_DESC ( "name", 'n', required_argument,
- struct menu_options, name, parse_string ),
+ struct dynui_options, name, parse_string ),
OPTION_DESC ( "delete", 'd', no_argument,
- struct menu_options, delete, parse_flag ),
+ struct dynui_options, delete, parse_flag ),
};
-/** "menu" command descriptor */
-static struct command_descriptor menu_cmd =
- COMMAND_DESC ( struct menu_options, menu_opts, 0, MAX_ARGUMENTS,
+/** "dynui" command descriptor */
+static struct command_descriptor dynui_cmd =
+ COMMAND_DESC ( struct dynui_options, dynui_opts, 0, MAX_ARGUMENTS,
"[<title>]" );
/**
- * The "menu" command
+ * The "dynui" command
*
* @v argc Argument count
* @v argv Argument list
* @ret rc Return status code
*/
-static int menu_exec ( int argc, char **argv ) {
- struct menu_options opts;
- struct menu *menu;
+static int dynui_exec ( int argc, char **argv ) {
+ struct dynui_options opts;
+ struct dynamic_ui *dynui;
char *title;
int rc;
/* Parse options */
- if ( ( rc = parse_options ( argc, argv, &menu_cmd, &opts ) ) != 0 )
+ if ( ( rc = parse_options ( argc, argv, &dynui_cmd, &opts ) ) != 0 )
goto err_parse_options;
/* Parse title */
@@ -87,21 +87,21 @@ static int menu_exec ( int argc, char **argv ) {
goto err_parse_title;
}
- /* Create menu */
- menu = create_menu ( opts.name, title );
- if ( ! menu ) {
+ /* Create dynamic user interface */
+ dynui = create_dynui ( opts.name, title );
+ if ( ! dynui ) {
rc = -ENOMEM;
- goto err_create_menu;
+ goto err_create_dynui;
}
- /* Destroy menu, if applicable */
+ /* Destroy dynamic user interface, if applicable */
if ( opts.delete )
- destroy_menu ( menu );
+ destroy_dynui ( dynui );
/* Success */
rc = 0;
- err_create_menu:
+ err_create_dynui:
free ( title );
err_parse_title:
err_parse_options:
@@ -110,8 +110,8 @@ static int menu_exec ( int argc, char **argv ) {
/** "item" options */
struct item_options {
- /** Menu name */
- char *menu;
+ /** Dynamic user interface name */
+ char *dynui;
/** Shortcut key */
unsigned int key;
/** Use as default */
@@ -123,7 +123,7 @@ struct item_options {
/** "item" option list */
static struct option_descriptor item_opts[] = {
OPTION_DESC ( "menu", 'm', required_argument,
- struct item_options, menu, parse_string ),
+ struct item_options, dynui, parse_string ),
OPTION_DESC ( "key", 'k', required_argument,
struct item_options, key, parse_key ),
OPTION_DESC ( "default", 'd', no_argument,
@@ -146,8 +146,8 @@ static struct command_descriptor item_cmd =
*/
static int item_exec ( int argc, char **argv ) {
struct item_options opts;
- struct menu *menu;
- struct menu_item *item;
+ struct dynamic_ui *dynui;
+ struct dynamic_item *item;
char *name = NULL;
char *text = NULL;
int rc;
@@ -169,23 +169,23 @@ static int item_exec ( int argc, char **argv ) {
}
}
- /* Identify menu */
- if ( ( rc = parse_menu ( opts.menu, &menu ) ) != 0 )
- goto err_parse_menu;
+ /* Identify dynamic user interface */
+ if ( ( rc = parse_dynui ( opts.dynui, &dynui ) ) != 0 )
+ goto err_parse_dynui;
- /* Add menu item */
- item = add_menu_item ( menu, name, ( text ? text : "" ),
- opts.key, opts.is_default );
+ /* Add dynamic user interface item */
+ item = add_dynui_item ( dynui, name, ( text ? text : "" ),
+ opts.key, opts.is_default );
if ( ! item ) {
rc = -ENOMEM;
- goto err_add_menu_item;
+ goto err_add_dynui_item;
}
/* Success */
rc = 0;
- err_add_menu_item:
- err_parse_menu:
+ err_add_dynui_item:
+ err_parse_dynui:
free ( text );
err_parse_text:
err_parse_options:
@@ -194,20 +194,20 @@ static int item_exec ( int argc, char **argv ) {
/** "choose" options */
struct choose_options {
- /** Menu name */
- char *menu;
+ /** Dynamic user interface name */
+ char *dynui;
/** Timeout */
unsigned long timeout;
/** Default selection */
char *select;
- /** Keep menu */
+ /** Keep dynamic user interface */
int keep;
};
/** "choose" option list */
static struct option_descriptor choose_opts[] = {
OPTION_DESC ( "menu", 'm', required_argument,
- struct choose_options, menu, parse_string ),
+ struct choose_options, dynui, parse_string ),
OPTION_DESC ( "default", 'd', required_argument,
struct choose_options, select, parse_string ),
OPTION_DESC ( "timeout", 't', required_argument,
@@ -230,8 +230,8 @@ static struct command_descriptor choose_cmd =
static int choose_exec ( int argc, char **argv ) {
struct choose_options opts;
struct named_setting setting;
- struct menu *menu;
- struct menu_item *item;
+ struct dynamic_ui *dynui;
+ struct dynamic_item *item;
int rc;
/* Parse options */
@@ -243,12 +243,13 @@ static int choose_exec ( int argc, char **argv ) {
&setting ) ) != 0 )
goto err_parse_setting;
- /* Identify menu */
- if ( ( rc = parse_menu ( opts.menu, &menu ) ) != 0 )
- goto err_parse_menu;
+ /* Identify dynamic user interface */
+ if ( ( rc = parse_dynui ( opts.dynui, &dynui ) ) != 0 )
+ goto err_parse_dynui;
- /* Show menu */
- if ( ( rc = show_menu ( menu, opts.timeout, opts.select, &item ) ) != 0)
+ /* Show as menu */
+ if ( ( rc = show_menu ( dynui, opts.timeout, opts.select,
+ &item ) ) != 0 )
goto err_show_menu;
/* Apply default type if necessary */
@@ -268,20 +269,20 @@ static int choose_exec ( int argc, char **argv ) {
err_store:
err_show_menu:
- /* Destroy menu, if applicable */
+ /* Destroy dynamic user interface, if applicable */
if ( ! opts.keep )
- destroy_menu ( menu );
- err_parse_menu:
+ destroy_dynui ( dynui );
+ err_parse_dynui:
err_parse_setting:
err_parse_options:
return rc;
}
-/** Menu commands */
-struct command menu_commands[] __command = {
+/** Dynamic user interface commands */
+struct command dynui_commands[] __command = {
{
.name = "menu",
- .exec = menu_exec,
+ .exec = dynui_exec,
},
{
.name = "item",
diff --git a/src/hci/tui/menu_ui.c b/src/hci/tui/menu_ui.c
index 067e2d8..ab4e602 100644
--- a/src/hci/tui/menu_ui.c
+++ b/src/hci/tui/menu_ui.c
@@ -37,7 +37,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/console.h>
#include <ipxe/ansicol.h>
#include <ipxe/jumpscroll.h>
-#include <ipxe/menu.h>
+#include <ipxe/dynui.h>
/* Screen layout */
#define TITLE_ROW 1U
@@ -49,8 +49,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** A menu user interface */
struct menu_ui {
- /** Menu */
- struct menu *menu;
+ /** Dynamic user interface */
+ struct dynamic_ui *dynui;
/** Jump scroller */
struct jump_scroller scroll;
/** Timeout (0=indefinite) */
@@ -60,14 +60,15 @@ struct menu_ui {
/**
* Return a numbered menu item
*
- * @v menu Menu
+ * @v dynui Dynamic user interface
* @v index Index
* @ret item Menu item, or NULL
*/
-static struct menu_item * menu_item ( struct menu *menu, unsigned int index ) {
- struct menu_item *item;
+static struct dynamic_item * menu_item ( struct dynamic_ui *dynui,
+ unsigned int index ) {
+ struct dynamic_item *item;
- list_for_each_entry ( item, &menu->items, list ) {
+ list_for_each_entry ( item, &dynui->items, list ) {
if ( index-- == 0 )
return item;
}
@@ -82,7 +83,7 @@ static struct menu_item * menu_item ( struct menu *menu, unsigned int index ) {
* @v index Index
*/
static void draw_menu_item ( struct menu_ui *ui, unsigned int index ) {
- struct menu_item *item;
+ struct dynamic_item *item;
unsigned int row_offset;
char buf[ MENU_COLS + 1 /* NUL */ ];
char timeout_buf[6]; /* "(xxx)" + NUL */
@@ -95,7 +96,7 @@ static void draw_menu_item ( struct menu_ui *ui, unsigned int index ) {
move ( ( MENU_ROW + row_offset ), MENU_COL );
/* Get menu item */
- item = menu_item ( ui->menu, index );
+ item = menu_item ( ui->dynui, index );
if ( item ) {
/* Draw separators in a different colour */
@@ -171,8 +172,8 @@ static void draw_menu_items ( struct menu_ui *ui ) {
* @ret selected Selected item
* @ret rc Return status code
*/
-static int menu_loop ( struct menu_ui *ui, struct menu_item **selected ) {
- struct menu_item *item;
+static int menu_loop ( struct menu_ui *ui, struct dynamic_item **selected ) {
+ struct dynamic_item *item;
unsigned long timeout;
unsigned int previous;
unsigned int move;
@@ -217,7 +218,7 @@ static int menu_loop ( struct menu_ui *ui, struct menu_item **selected ) {
break;
default:
i = 0;
- list_for_each_entry ( item, &ui->menu->items,
+ list_for_each_entry ( item, &ui->dynui->items,
list ) {
if ( ! ( item->shortcut &&
( item->shortcut == key ) ) ) {
@@ -238,7 +239,7 @@ static int menu_loop ( struct menu_ui *ui, struct menu_item **selected ) {
/* Move selection, if applicable */
while ( move ) {
move = jump_scroll_move ( &ui->scroll, move );
- item = menu_item ( ui->menu, ui->scroll.current );
+ item = menu_item ( ui->dynui, ui->scroll.current );
if ( item->name )
break;
}
@@ -252,7 +253,7 @@ static int menu_loop ( struct menu_ui *ui, struct menu_item **selected ) {
}
/* Record selection */
- item = menu_item ( ui->menu, ui->scroll.current );
+ item = menu_item ( ui->dynui, ui->scroll.current );
assert ( item != NULL );
assert ( item->name != NULL );
*selected = item;
@@ -265,14 +266,14 @@ static int menu_loop ( struct menu_ui *ui, struct menu_item **selected ) {
/**
* Show menu
*
- * @v menu Menu
+ * @v dynui Dynamic user interface
* @v timeout Timeout period, in ticks (0=indefinite)
* @ret selected Selected item
* @ret rc Return status code
*/
-int show_menu ( struct menu *menu, unsigned long timeout,
- const char *select, struct menu_item **selected ) {
- struct menu_item *item;
+int show_menu ( struct dynamic_ui *dynui, unsigned long timeout,
+ const char *select, struct dynamic_item **selected ) {
+ struct dynamic_item *item;
struct menu_ui ui;
char buf[ MENU_COLS + 1 /* NUL */ ];
int named_count = 0;
@@ -280,10 +281,10 @@ int show_menu ( struct menu *menu, unsigned long timeout,
/* Initialise UI */
memset ( &ui, 0, sizeof ( ui ) );
- ui.menu = menu;
+ ui.dynui = dynui;
ui.scroll.rows = MENU_ROWS;
ui.timeout = timeout;
- list_for_each_entry ( item, &menu->items, list ) {
+ list_for_each_entry ( item, &dynui->items, list ) {
if ( item->name ) {
if ( ! named_count )
ui.scroll.current = ui.scroll.count;
@@ -315,7 +316,7 @@ int show_menu ( struct menu *menu, unsigned long timeout,
/* Draw initial content */
attron ( A_BOLD );
- snprintf ( buf, sizeof ( buf ), "%s", ui.menu->title );
+ snprintf ( buf, sizeof ( buf ), "%s", ui.dynui->title );
mvprintw ( TITLE_ROW, ( ( COLS - strlen ( buf ) ) / 2 ), "%s", buf );
attroff ( A_BOLD );
jump_scroll ( &ui.scroll );