cli: add a submenu for connection editor for detail property handling

property_edit_submenu() is the main function. It is entered from main menu by
'goto'
command.

Commands of this menu:
set       - set new value to the property
add       - add a value to the property (for non-container properties it is
            the same as set)
change    - allow editing the current property value
remove    - remove the property value(s)
describe  - show the property description and/or usage
print     - show the property value
back      - return to the setting level (main menu)
help      - show help (command descriptions)
quit      - quit nmcli
This commit is contained in:
Jiří Klimeš
2013-03-04 14:07:51 +01:00
parent def37e4e0d
commit 68d69bfce8

View File

@@ -3508,6 +3508,314 @@ editor_main_help (const char *command)
} }
} }
typedef enum {
NMC_EDITOR_SUB_CMD_UNKNOWN = 0,
NMC_EDITOR_SUB_CMD_SET,
NMC_EDITOR_SUB_CMD_ADD,
NMC_EDITOR_SUB_CMD_CHANGE,
NMC_EDITOR_SUB_CMD_REMOVE,
NMC_EDITOR_SUB_CMD_DESCRIBE,
NMC_EDITOR_SUB_CMD_PRINT,
NMC_EDITOR_SUB_CMD_BACK,
NMC_EDITOR_SUB_CMD_HELP,
NMC_EDITOR_SUB_CMD_QUIT
} NmcEditorSubCmd;
static NmcEditorSubCmd
parse_editor_sub_cmd (const char *cmd, char **cmd_arg)
{
NmcEditorSubCmd editor_cmd = NMC_EDITOR_SUB_CMD_UNKNOWN;
char **vec;
vec = g_strsplit_set (cmd, " \t", 2);
if (g_strv_length (vec) < 1) {
if (cmd_arg)
*cmd_arg = NULL;
return NMC_EDITOR_SUB_CMD_UNKNOWN;
}
if (matches (vec[0], "set") == 0)
editor_cmd = NMC_EDITOR_SUB_CMD_SET;
else if (matches (vec[0], "add") == 0)
editor_cmd = NMC_EDITOR_SUB_CMD_ADD;
else if (matches (vec[0], "change") == 0)
editor_cmd = NMC_EDITOR_SUB_CMD_CHANGE;
else if (matches (vec[0], "remove") == 0)
editor_cmd = NMC_EDITOR_SUB_CMD_REMOVE;
else if (matches (vec[0], "describe") == 0)
editor_cmd = NMC_EDITOR_SUB_CMD_DESCRIBE;
else if (matches (vec[0], "print") == 0)
editor_cmd = NMC_EDITOR_SUB_CMD_PRINT;
else if (matches (vec[0], "back") == 0)
editor_cmd = NMC_EDITOR_SUB_CMD_BACK;
else if (matches (vec[0], "help") == 0 || strcmp (vec[0], "?") == 0)
editor_cmd = NMC_EDITOR_SUB_CMD_HELP;
else if (matches (vec[0], "quit") == 0)
editor_cmd = NMC_EDITOR_SUB_CMD_QUIT;
/* set pointer to command argument */
if (cmd_arg)
*cmd_arg = g_strdup (vec[1]);
g_strfreev (vec);
return editor_cmd;
}
static void
editor_sub_help (void)
{
printf ("------------------------------------------------------------------------------\n");
/* TRANSLATORS: do not translate command names and keywords before ::
* However, you should translate terms enclosed in <>.
*/
printf (_("---[ Property menu ]---\n"
"set [<value>] :: set new value\n"
"add [<value>] :: add new option to the property\n"
"change :: change current value\n"
"remove [<index> | <option>] :: delete the value\n"
"describe :: describe property\n"
"print [setting | connection] :: print property (setting/connection) value(s)\n"
"back :: go to upper level\n"
"help/? [<command>] :: print this help or command description\n"
"quit :: exit nmcli\n"));
printf ("------------------------------------------------------------------------------\n");
}
static void
editor_sub_usage (const char *command)
{
if (!command)
editor_sub_help ();
else {
/* detailed command descriptions */
NmcEditorSubCmd cmdsub = parse_editor_sub_cmd (command, NULL);
switch (cmdsub) {
case NMC_EDITOR_SUB_CMD_SET:
printf (_("set [<value>] :: set new value\n\n"
"This command sets provided <value> to this property\n"));
break;
case NMC_EDITOR_SUB_CMD_ADD:
printf (_("add [<value>] :: add new option to the property\n\n"
"This command add provided <value> to this property, if "
"the property is of a container type. For single-valued "
"properties it replaces the value (same as 'set').\n"));
break;
case NMC_EDITOR_SUB_CMD_CHANGE:
printf (_("change :: change current value\n\n"
"Displays current value and allows editing it.\n"));
break;
case NMC_EDITOR_SUB_CMD_REMOVE:
printf (_("remove [<index>|<option>] :: delete the value\n\n"
"Removes the property value (sets it to default).\n"));
break;
case NMC_EDITOR_SUB_CMD_DESCRIBE:
printf (_("describe :: describe property\n\n"
"Shows property description. You can consult nm-settings(5) "
"manual page to see all NM settings and properties.\n"));
break;
case NMC_EDITOR_SUB_CMD_PRINT:
printf (_("print [property|setting|connection] :: print property (setting, connection) value(s)\n\n"
"Shows property value. Providing an argument you can also display "
"values for the whole setting or connection.\n"));
break;
case NMC_EDITOR_SUB_CMD_BACK:
printf (_("back :: go to upper menu level\n\n"));
break;
case NMC_EDITOR_SUB_CMD_HELP:
printf (_("help/? [<command>] :: help for nmcli commands\n\n"));
break;
case NMC_EDITOR_SUB_CMD_QUIT:
printf (_("quit :: exit nmcli\n\n"
"This command exits nmcli. When the connection being edited "
"is not saved, the user is asked to confirm the action.\n"));
break;
default:
printf (_("Unknown command: '%s'\n"), command);
break;
}
}
}
/*----------------------------------------------------------------------------*/
static void
print_property_description (NMSetting *setting, const char *prop_name)
{
char *desc;
desc = nmc_setting_get_property_desc (setting, prop_name);
printf ("\n=== [%s] ===\n%s\n", prop_name, desc);
g_free (desc);
}
static void
print_setting_description (NMSetting *setting)
{
/* Show description of all properties */
char **all_props;
int i;
all_props = nmc_setting_get_valid_properties (setting);
printf (("<<< %s >>>\n"), nm_setting_get_name (setting));
for (i = 0; all_props && all_props[i]; i++)
print_property_description (setting, all_props[i]);
g_strfreev (all_props);
}
/*
* Submenu for detailed property editation
* Return: TRUE - continue; FALSE - should quit
*/
static gboolean
property_edit_submenu (NmCli *nmc, NMConnection *connection, NMSetting *curr_setting, const char *prop_name)
{
NmcEditorSubCmd cmdsub;
gboolean cmd_property_loop = TRUE;
gboolean should_quit = FALSE;
char *prop_val_user, *tmp_prompt;
gboolean set_result;
GError *tmp_err = NULL;
char *prompt;
char *tmp_str;
GValue prop_g_value = G_VALUE_INIT;
prompt = g_strdup_printf (_("nmcli %s.%s> "), nm_setting_get_name (curr_setting), prop_name);
while (cmd_property_loop) {
char *cmd_property_user;
char *cmd_property_arg;
cmd_property_user = readline_x (prompt);
if (!cmd_property_user || *cmd_property_user == '\0')
continue;
cmdsub = parse_editor_sub_cmd (g_strstrip (cmd_property_user), &cmd_property_arg);
switch (cmdsub) {
case NMC_EDITOR_SUB_CMD_SET:
case NMC_EDITOR_SUB_CMD_ADD:
/* list, arrays,...: SET replaces the whole property value
* ADD adds the new value(s)
* single values: : both SET and ADD sets the new value
*/
if (!cmd_property_arg) {
tmp_prompt = g_strdup_printf (_("Enter '%s' value: "), prop_name);
prop_val_user = readline_x (tmp_prompt);
g_free (tmp_prompt);
} else
prop_val_user = g_strdup (cmd_property_arg);
/* nmc_setting_set_property() only adds new value, thus we have to
* remove the original value and save it for error cases.
*/
if (cmdsub == NMC_EDITOR_SUB_CMD_SET) {
nmc_property_get_gvalue (curr_setting, prop_name, &prop_g_value);
nmc_property_set_default_value (curr_setting, prop_name);
}
set_result = nmc_setting_set_property (curr_setting, prop_name, prop_val_user, &tmp_err);
g_free (prop_val_user);
if (!set_result) {
printf (_("Error: failed to set '%s' property: %s\n"), prop_name, tmp_err->message);
g_clear_error (&tmp_err);
if (cmdsub == NMC_EDITOR_SUB_CMD_SET)
nmc_property_set_gvalue (curr_setting, prop_name, &prop_g_value);
}
if (G_IS_VALUE (&prop_g_value))
g_value_unset (&prop_g_value);
break;
case NMC_EDITOR_SUB_CMD_CHANGE:
tmp_prompt = g_strdup_printf (_("Edit '%s' value: "), prop_name);
prop_val_user = readline_x (tmp_prompt);
nmc_property_get_gvalue (curr_setting, prop_name, &prop_g_value);
nmc_property_set_default_value (curr_setting, prop_name);
if (!nmc_setting_set_property (curr_setting, prop_name, prop_val_user, &tmp_err)) {
printf (_("Error: failed to set '%s' property: %s\n"), prop_name, tmp_err->message);
g_clear_error (&tmp_err);
nmc_property_set_gvalue (curr_setting, prop_name, &prop_g_value);
}
g_free (prop_val_user);
g_free (tmp_prompt);
if (G_IS_VALUE (&prop_g_value))
g_value_unset (&prop_g_value);
break;
case NMC_EDITOR_SUB_CMD_REMOVE:
if (cmd_property_arg) {
unsigned long val_int = G_MAXUINT32;
char *option = NULL;
if (!nmc_string_to_uint (cmd_property_arg, TRUE, 0, G_MAXUINT32, &val_int))
option = g_strdup (cmd_property_arg);
if (!nmc_setting_remove_property_option (curr_setting, prop_name,
option ? g_strstrip (option) : NULL,
(guint32) val_int,
&tmp_err)) {
printf (_("Error: %s\n"), tmp_err->message);
g_clear_error (&tmp_err);
}
g_free (option);
} else
nmc_property_set_default_value (curr_setting, prop_name);
break;
case NMC_EDITOR_SUB_CMD_DESCRIBE:
/* Show property description */
print_property_description (curr_setting, prop_name);
break;
case NMC_EDITOR_SUB_CMD_PRINT:
/* Print current connection settings/properties */
if (cmd_property_arg) {
if (matches (cmd_property_arg, "setting") == 0)
editor_show_setting (curr_setting, nmc);
else if ( matches (cmd_property_arg, "connection") == 0
|| matches (cmd_property_arg, "all") == 0)
editor_show_connection (connection, nmc);
else
printf (_("Unknown command argument: '%s'\n"), cmd_property_arg);
} else {
printf ("%s: %s\n",
prop_name,
nmc_setting_get_property (curr_setting, prop_name, NULL));
}
break;
case NMC_EDITOR_SUB_CMD_BACK:
cmd_property_loop = FALSE;
break;
case NMC_EDITOR_SUB_CMD_HELP:
editor_sub_usage (cmd_property_arg);
break;
case NMC_EDITOR_SUB_CMD_QUIT:
do {
tmp_str = nmc_get_user_input (_("Do you really want to quit? [y/n]\n"));
} while (!tmp_str);
if (matches (tmp_str, "yes") == 0) {
cmd_property_loop = FALSE;
should_quit = TRUE; /* we will quit nmcli */
}
g_free (tmp_str);
break;
case NMC_EDITOR_SUB_CMD_UNKNOWN:
default:
printf (_("Unknown command: '%s'\n"), cmd_property_user);
break;
}
g_free (cmd_property_user);
g_free (cmd_property_arg);
}
g_free (prompt);
return !should_quit;
}
/* /*
* Split 'str' in the following format: [[[setting.]property] [value]] * Split 'str' in the following format: [[[setting.]property] [value]]
* and return the components in 'setting', 'property' and 'value' * and return the components in 'setting', 'property' and 'value'
@@ -3670,30 +3978,6 @@ menu_switch_to_level1 (NmcEditorMenuContext *menu_ctx,
menu_ctx->valid_props_str = g_strjoinv (", ", menu_ctx->valid_props); menu_ctx->valid_props_str = g_strjoinv (", ", menu_ctx->valid_props);
} }
static void
print_property_description (NMSetting *setting, const char *prop_name)
{
char *desc;
desc = nmc_setting_get_property_desc (setting, prop_name);
printf ("\n=== [%s] ===\n%s\n", prop_name, desc);
g_free (desc);
}
static void
print_setting_description (NMSetting *setting)
{
/* Show description of all properties */
char **all_props;
int i;
all_props = nmc_setting_get_valid_properties (setting);
printf (("<<< %s >>>\n"), nm_setting_get_name (setting));
for (i = 0; all_props && all_props[i]; i++)
print_property_description (setting, all_props[i]);
g_strfreev (all_props);
}
static gboolean static gboolean
editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_type) editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_type)
{ {
@@ -3864,11 +4148,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
} }
if (menu_ctx.level == 1 || cmd_arg_s) { if (menu_ctx.level == 1 || cmd_arg_s) {
/* level 1 - setting selected */ /* level 1 - setting selected */
char *prop_val_user = NULL;
const char *prop_name; const char *prop_name;
char *prompt;
GError *tmp_err = NULL;
gboolean set_result;
prop_name = ask_check_property (cmd_arg_p, prop_name = ask_check_property (cmd_arg_p,
(const char **) menu_ctx.valid_props, (const char **) menu_ctx.valid_props,
@@ -3876,16 +4156,8 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
if (!prop_name) if (!prop_name)
break; break;
prompt = g_strdup_printf (_("Enter '%s' value: "), prop_name); /* submenu - level 2 - editing properties */
prop_val_user = readline_x (prompt); cmd_loop = property_edit_submenu (nmc, connection, menu_ctx.curr_setting, prop_name);
g_free (prompt);
set_result = nmc_setting_set_property (menu_ctx.curr_setting, prop_name, prop_val_user, &tmp_err);
g_free (prop_val_user);
if (!set_result) {
fprintf (stdout, _("Error: property '%s' set failure: %s\n"), prop_name, tmp_err->message);
g_clear_error (&tmp_err);
}
} }
break; break;