summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrancesco Giudici <fgiudici@redhat.com>2016-06-18 21:17:57 +0200
committerFrancesco Giudici <fgiudici@redhat.com>2016-06-21 16:28:48 +0200
commit00b362bcf2052671788ce03d6cafb253904e991b (patch)
treeb65780fecbe62b7a11115a8254de3b841e34da9d
parent3aff650e2219d45a9c353dfebe590a638a470727 (diff)
downloadNetworkManager-fg/autocomplete_fix_rh1301226_with_LR_patches.tar.gz
nmcli: add support to shortnames for connection properties autocompletionfg/autocomplete_fix_rh1301226_with_LR_patches
-rw-r--r--clients/cli/connections.c99
1 files changed, 73 insertions, 26 deletions
diff --git a/clients/cli/connections.c b/clients/cli/connections.c
index d612a80937..c10db7b446 100644
--- a/clients/cli/connections.c
+++ b/clients/cli/connections.c
@@ -2911,47 +2911,90 @@ get_valid_settings_array (const char *con_type)
return NULL;
}
+/* get_valid_properties_string:
+ * @array: base properties for the current connection type
+ * @array_slv: slave properties (or ipv4/ipv6 ones) for the current connection type
+ * @modifier: to prepend to each element of the returned list
+ * @prefix: only properties matching the prefix will be returned
+ * @postfix: required prefix on the property args; if a empty string is passed, is
+ * assumed that the @prefix is a shortcut, so it should not be completed
+ * but left as is (and an additional check for shortcut ambiguity is performed)
+ *
+ * Returns a list of properties compatible with the current connection type
+ * for the shell autocompletion functionality.
+ *
+ * Returns: list of property.arg elements
+ */
static char *
-get_valid_properties_string (const NameItem *array, const NameItem *array_slv, char modifier, const char *prefix)
+get_valid_properties_string (const NameItem *array,
+ const NameItem *array_slv,
+ char modifier,
+ const char *prefix,
+ const char *postfix)
{
const NameItem *iter = array;
const NmcOutputField *field_iter;
+ const char *prop_name = NULL;
GString *str;
- int i;
+ int i, j;
+
+ g_return_val_if_fail (prefix, NULL);
str = g_string_sized_new (1024);
for (i = 0; i < 2; i++, iter = array_slv) {
while (iter && iter->name) {
- int j = 0;
+ if ( !(g_str_has_prefix (iter->name, prefix))
+ && (!(iter->alias) || !g_str_has_prefix (iter->alias, prefix))) {
+ iter++;
+ continue;
+ }
+ /* If postix (so prefix is terminated by a dot), check
+ * that prefix is not ambiguous */
+ if (postfix) {
+ if (prop_name)
+ return g_string_free (str, TRUE);
+ prop_name = prefix;
+ } else {
+ prop_name = iter->name;
+ }
- while ((nmc_fields_settings_names[j].name) &&
- g_strcmp0 (iter->name, nmc_fields_settings_names[j].name))
+ /* Search the array with the arguments of the current property */
+ j = 0;
+ while (!nm_streq0 (iter->name, nmc_fields_settings_names[j].name)) {
+ g_assert (nmc_fields_settings_names[j].name);
j++;
-
+ }
field_iter = nmc_fields_settings_names[j].group;
+
j = 0;
while (field_iter[j].name) {
gchar *new;
+ const char *arg_name = field_iter[j].name;
- new = g_strdup_printf ("%s.%s\n", iter->name, field_iter[j].name);
- if (g_str_has_prefix (new, prefix)) {
+ /* If required, expand the alias too */
+ if (!postfix && iter->alias) {
if (modifier)
g_string_append_c (str, modifier);
+ new = g_strdup_printf ("%s.%s\n",
+ iter->alias,
+ arg_name);
g_string_append (str, new);
+ g_free (new);
}
- g_free (new);
- if (iter->alias) {
- new = g_strdup_printf ("%s.%s\n", iter->alias, field_iter[j].name);
- if (g_str_has_prefix (new, prefix)) {
- if (modifier)
- g_string_append_c (str, modifier);
- g_string_append (str, new);
- }
- g_free (new);
+ if (postfix && !g_str_has_prefix (arg_name, postfix)) {
+ j++;
+ continue;
}
+ if (modifier)
+ g_string_append_c (str, modifier);
+ new = g_strdup_printf ("%s.%s\n",
+ prop_name,
+ arg_name);
+ g_string_append (str, new);
+ g_free (new);
j++;
}
iter++;
@@ -4662,7 +4705,10 @@ do_questionnaire_ip_tunnel (char **local, char **parent)
}
static void
-complete_property_name (NmCli *nmc, NMConnection *connection, char modifier, const gchar *prefix)
+complete_property_name (NmCli *nmc, NMConnection *connection,
+ char modifier,
+ const gchar *prefix,
+ const gchar *postfix)
{
NMSettingConnection *s_con;
const NameItem *valid_settings_main = NULL;
@@ -4680,7 +4726,7 @@ complete_property_name (NmCli *nmc, NMConnection *connection, char modifier, con
valid_settings_main = get_valid_settings_array (connection_type);
valid_settings_slave = get_valid_settings_array (slv_type);
- word_list = get_valid_properties_string (valid_settings_main, valid_settings_slave, modifier, prefix);
+ word_list = get_valid_properties_string (valid_settings_main, valid_settings_slave, modifier, prefix, postfix);
if (word_list)
g_print ("%s", word_list);
}
@@ -4738,11 +4784,12 @@ read_connection_properties (NmCli *nmc,
strv = g_strsplit (s_dot_p, ".", 2);
if (g_strv_length (strv) != 2) {
- if (nmc->complete)
- complete_property_name (nmc, connection, modifier, s_dot_p);
- else
- g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
- _("Error: invalid <setting>.<property> '%s'."), s_dot_p);
+ if (nmc->complete) {
+ complete_property_name (nmc, connection, modifier, s_dot_p, NULL);
+ break;
+ }
+ g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
+ _("Error: invalid <setting>.<property> '%s'."), s_dot_p);
goto finish;
}
@@ -4827,7 +4874,7 @@ read_connection_properties (NmCli *nmc,
success = TRUE;
finish:
if (!success && nmc->complete) {
- complete_property_name (nmc, connection, modifier, s_dot_p);
+ complete_property_name (nmc, connection, modifier, strv[0], strv[1]);
success = TRUE;
}
if (strv)
@@ -10263,7 +10310,7 @@ do_connection_modify (NmCli *nmc,
if (next_arg (&argc, &argv) != 0) {
if (nmc->complete) {
- complete_property_name (nmc, NM_CONNECTION (rc), '\0', "");
+ complete_property_name (nmc, NM_CONNECTION (rc), '\0', "", NULL);
goto finish;
}
g_string_printf (nmc->return_text, _("Error: <setting>.<property> argument is missing."));