From 280187c4133d9a8bade3d48a485a7c0aaff28fb9 Mon Sep 17 00:00:00 2001 From: Francesco Giudici Date: Mon, 13 Jun 2016 18:59:31 +0200 Subject: nmcli: enable connection autocompletion for 802.1x properties nmcli bash autocompletion leveraged on "nmcli connection edit", "print" to retrieve the specific properties of a connection. Anyway, the interactive editor is smart and just prints the used components, so in a connection where 802.1x is not enabled we had no autocompletion. Solved adding an "hidden" command "nmcli connection modify --complete" as suggested in bgo #724860 in order to retrieve ALL the available properties for use in autocompletion. https://bugzilla.gnome.org/show_bug.cgi?id=724860 https://bugzilla.redhat.com/show_bug.cgi?id=1301226 --- clients/cli/connections.c | 65 +++++++++++++++++++++++++++++++++++++++++++- clients/cli/nmcli-completion | 11 ++++++-- 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/clients/cli/connections.c b/clients/cli/connections.c index 0c61667d92..b3e5c51fd2 100644 --- a/clients/cli/connections.c +++ b/clients/cli/connections.c @@ -2900,6 +2900,38 @@ get_valid_settings_array (const char *con_type) return NULL; } +static char * +get_valid_autocompletion_string (const NameItem *array, const NameItem *array_slv) +{ + const NameItem *iter = array; + const NmcOutputField *field_iter; + GString *str; + int i; + + str = g_string_sized_new (1024); + + for (i = 0; i < 2; i++, iter = array_slv) { + while (iter && iter->name) { + int j = 0; + + while ((nmc_fields_settings_names[j].name) && + g_strcmp0 (iter->name, nmc_fields_settings_names[j].name)) + j++; + + field_iter = nmc_fields_settings_names[j].group; + j = 0; + while (field_iter[j].name) { + g_string_append_printf (str, "%s.%s ", iter->name, field_iter[j].name); + if (iter->alias) + g_string_append_printf (str, "%s.%s ", iter->alias, field_iter[j].name); + j++; + } + iter++; + } + } + return g_string_free (str, FALSE); +} + /* * Check if 'val' is valid string in either array->name or array->alias for * both array parameters (array & array_slv). @@ -10128,6 +10160,7 @@ modify_connection_cb (GObject *connection, static NMCResultCode do_connection_modify (NmCli *nmc, gboolean temporary, + gboolean complete, int argc, char **argv) { @@ -10177,6 +10210,30 @@ do_connection_modify (NmCli *nmc, goto finish; } + /* Query comes from shell autocomplete function */ + if (complete) { + NMSettingConnection *s_con; + const NameItem *valid_settings_main = NULL; + const NameItem *valid_settings_slave = NULL; + const char *connection_type = NULL; + const char *slave_type = NULL; + gs_free char *slv_type = NULL; + gs_free char *word_list = NULL; + + connection_type = nm_connection_get_connection_type (connection); + s_con = nm_connection_get_setting_connection (connection); + if (s_con) + slave_type = nm_setting_connection_get_slave_type (s_con); + slv_type = g_strdup_printf ("%s-slave", slave_type ? slave_type : "no"); + valid_settings_main = get_valid_settings_array (connection_type); + valid_settings_slave = get_valid_settings_array (slv_type); + + word_list = get_valid_autocompletion_string (valid_settings_main, valid_settings_slave); + if (word_list) + g_print ("%s", word_list); + goto finish; + } + if (next_arg (&argc, &argv) != 0) { g_string_printf (nmc->return_text, _("Error: . argument is missing.")); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; @@ -11114,13 +11171,19 @@ do_connections (NmCli *nmc, int argc, char **argv) nmc->return_value = do_connection_load (nmc, argc-1, argv+1); } else if (matches (*argv, "modify") == 0) { gboolean temporary = FALSE; + gboolean complete = FALSE; next_arg (&argc, &argv); + /* Check modify options [--complete] or [--temporary] */ if (nmc_arg_is_option (*argv, "temporary")) { temporary = TRUE; next_arg (&argc, &argv); } - nmc->return_value = do_connection_modify (nmc, temporary, argc, argv); + if (nmc_arg_is_option (*argv, "complete")) { + complete = TRUE; + next_arg (&argc, &argv); + } + nmc->return_value = do_connection_modify (nmc, temporary, complete, argc, argv); } else if (matches (*argv, "clone") == 0) { gboolean temporary = FALSE; diff --git a/clients/cli/nmcli-completion b/clients/cli/nmcli-completion index 2e9a149f5b..7b653da414 100644 --- a/clients/cli/nmcli-completion +++ b/clients/cli/nmcli-completion @@ -763,19 +763,24 @@ _nmcli_compl_PROPERTIES() { while [[ "${#words[@]}" -gt 0 ]]; do if [[ ${#words[@]} -le 1 ]]; then - local PREFIX="" + local PREFIX="" item list="" if [[ "${words[0]:0:1}" == [+-] ]]; then PREFIX="${words[0]:0:1}" fi - _nmcli_list_nl "$(echo -e 'print\nquit\nyes' |nmcli c edit "$@" 2>/dev/null |awk -F: '/\..*:/ {print "'$PREFIX'"$1}')" + item="$(nmcli c modify --complete "$@" 2>/dev/null)" + ### add prefix to each element + for item in $item; do + list="${list}${PREFIX}${item} " + done + _nmcli_list "$list" return 0 elif [[ ${#words[@]} -le 2 ]]; then return 0 fi _nmcli_array_delete_at words 0 1 done - _nmcli_list_nl "$(echo -e 'print\nquit\nyes' |nmcli c edit "$@" 2>/dev/null |awk -F: '/\..*:/ {print $1}')" + _nmcli_list "$(nmcli c modify --complete "$@" 2>/dev/null)" } _nmcli() -- cgit v1.2.1