summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clients/cli/common.c32
-rw-r--r--clients/cli/common.h1
-rw-r--r--clients/cli/connections.c69
-rw-r--r--clients/cli/nmcli.h2
-rw-r--r--clients/common/nm-meta-setting-desc.c34
-rw-r--r--clients/common/nm-meta-setting-desc.h2
6 files changed, 90 insertions, 50 deletions
diff --git a/clients/cli/common.c b/clients/cli/common.c
index 8738cef7b6..e37d9d8c8b 100644
--- a/clients/cli/common.c
+++ b/clients/cli/common.c
@@ -1126,6 +1126,38 @@ nmc_rl_gen_func_basic (const char *text, int state, const char *const*words)
return NULL;
}
+static struct {
+ bool initialized;
+ guint idx;
+ char **values;
+} _rl_compentry_func_wrap = { 0 };
+
+static char *
+_rl_compentry_func_wrap_fcn (const char *text, int state)
+{
+ g_return_val_if_fail (_rl_compentry_func_wrap.initialized, NULL);
+
+ if ( !_rl_compentry_func_wrap.values
+ || !_rl_compentry_func_wrap.values[_rl_compentry_func_wrap.idx]) {
+ g_strfreev (_rl_compentry_func_wrap.values);
+ _rl_compentry_func_wrap.values = NULL;
+ _rl_compentry_func_wrap.initialized = FALSE;
+ return NULL;
+ }
+
+ return g_strdup (_rl_compentry_func_wrap.values[_rl_compentry_func_wrap.idx++]);
+}
+
+NmcCompEntryFunc
+nmc_rl_compentry_func_wrap (const char *const*values)
+{
+ g_strfreev (_rl_compentry_func_wrap.values);
+ _rl_compentry_func_wrap.values = g_strdupv ((char **) values);
+ _rl_compentry_func_wrap.idx = 0;
+ _rl_compentry_func_wrap.initialized = TRUE;
+ return _rl_compentry_func_wrap_fcn;
+}
+
char *
nmc_rl_gen_func_ifnames (const char *text, int state)
{
diff --git a/clients/cli/common.h b/clients/cli/common.h
index 4f0f1b1ddb..b7057e462f 100644
--- a/clients/cli/common.h
+++ b/clients/cli/common.h
@@ -53,6 +53,7 @@ char *nmc_unique_connection_name (const GPtrArray *connections,
void nmc_cleanup_readline (void);
char *nmc_readline (const char *prompt_fmt, ...) G_GNUC_PRINTF (1, 2);
char *nmc_readline_echo (gboolean echo_on, const char *prompt_fmt, ...) G_GNUC_PRINTF (2, 3);
+NmcCompEntryFunc nmc_rl_compentry_func_wrap (const char *const*values);
char *nmc_rl_gen_func_basic (const char *text, int state, const char *const*words);
char *nmc_rl_gen_func_ifnames (const char *text, int state);
gboolean nmc_get_in_readline (void);
diff --git a/clients/cli/connections.c b/clients/cli/connections.c
index cf1a750805..dd7cfc5261 100644
--- a/clients/cli/connections.c
+++ b/clients/cli/connections.c
@@ -184,8 +184,6 @@ typedef struct {
} TabCompletionInfo;
static TabCompletionInfo nmc_tab_completion = {NULL, NULL, NULL, NULL};
-static char *gen_connection_types (const char *text, int state);
-
static void
usage (void)
{
@@ -2771,7 +2769,7 @@ finish:
return nmc->return_value;
}
-/*----------------------------------------------------------------------------*/
+/*****************************************************************************/
/*
* Return the most appropriate name for the connection of a type 'name' possibly with given 'slave_type'
@@ -3097,7 +3095,7 @@ is_setting_mandatory (NMConnection *connection, NMSetting *setting)
return FALSE;
}
-/*----------------------------------------------------------------------------*/
+/*****************************************************************************/
static const char *
_strip_master_prefix (const char *master, const char *(**func)(NMConnection *))
@@ -3685,7 +3683,7 @@ ensure_settings (NMConnection *connection, const NMMetaSettingValidPartItem *con
}
}
-/*----------------------------------------------------------------------------*/
+/*****************************************************************************/
static char *
gen_func_bool_values_l10n (const char *text, int state)
@@ -3721,7 +3719,7 @@ gen_func_bond_lacp_rate (const char *text, int state)
return nmc_rl_gen_func_basic (text, state, words);
}
-/*----------------------------------------------------------------------------*/
+/*****************************************************************************/
static gboolean
set_connection_type (NmCli *nmc, NMConnection *con, const OptionInfo *option, const char *value, GError **error)
@@ -4002,7 +4000,7 @@ _meta_abstract_get_option_info (const NMMetaAbstractInfo *abstract_info)
.check_and_set = check_and_set_, \
.generator_func = generator_func_, \
}
- OPTION_INFO (CONNECTION, NM_SETTING_CONNECTION_TYPE, "type", set_connection_type, gen_connection_types),
+ OPTION_INFO (CONNECTION, NM_SETTING_CONNECTION_TYPE, "type", set_connection_type, NULL),
OPTION_INFO (CONNECTION, NM_SETTING_CONNECTION_INTERFACE_NAME, "ifname", set_connection_iface, NULL),
OPTION_INFO (CONNECTION, NM_SETTING_CONNECTION_MASTER, "master", set_connection_master, NULL),
OPTION_INFO (BLUETOOTH, NM_SETTING_BLUETOOTH_TYPE, "bt-type", set_bluetooth_type, gen_func_bt_type),
@@ -4053,7 +4051,7 @@ option_relevant (NMConnection *connection, const NMMetaAbstractInfo *abstract_in
return TRUE;
}
-/*----------------------------------------------------------------------------*/
+/*****************************************************************************/
static void
complete_property_name (NmCli *nmc, NMConnection *connection,
@@ -4173,15 +4171,12 @@ complete_property (const gchar *setting_name, const gchar *property, const gchar
return;
}
- if (strcmp (setting_name, NM_SETTING_CONNECTION_SETTING_NAME) == 0) {
- if (strcmp (property, NM_SETTING_CONNECTION_TYPE) == 0)
- run_rl_generator (gen_connection_types, prefix);
- } else if ( strcmp (setting_name, NM_SETTING_BLUETOOTH_SETTING_NAME) == 0
+ if ( strcmp (setting_name, NM_SETTING_BLUETOOTH_SETTING_NAME) == 0
&& strcmp (property, NM_SETTING_BLUETOOTH_TYPE) == 0)
run_rl_generator (gen_func_bt_type, prefix);
}
-/*----------------------------------------------------------------------------*/
+/*****************************************************************************/
static gboolean
get_value (const char **value, int *argc, char ***argv, const char *option, GError **error)
@@ -4481,9 +4476,7 @@ nmcli_con_add_tab_completion (const char *text, int start, int end)
}
next:
- if (g_str_has_prefix (rl_prompt, NM_META_TEXT_PROMPT_CON_TYPE))
- generator_func = gen_connection_types;
- else if (g_str_has_prefix (rl_prompt, NM_META_TEXT_PROMPT_BT_TYPE))
+ if (g_str_has_prefix (rl_prompt, NM_META_TEXT_PROMPT_BT_TYPE))
generator_func = gen_func_bt_type;
else if (g_str_has_prefix (rl_prompt, NM_META_TEXT_PROMPT_BOND_MODE))
generator_func = gen_func_bond_mode;
@@ -4841,7 +4834,7 @@ finish:
return nmc->return_value;
}
-/*----------------------------------------------------------------------------*/
+/*****************************************************************************/
/* Functions for readline TAB completion in editor */
static void
@@ -4961,36 +4954,14 @@ gen_cmd_save (const char *text, int state)
return nmc_rl_gen_func_basic (text, state, words);
}
-static char *
-gen_connection_types (const char *text, int state)
+static rl_compentry_func_t *
+gen_connection_types (const char *text)
{
- static int list_idx, len;
- static int had_name;
+ gs_strfreev char **values = NULL;
- if (!state) {
- list_idx = 0;
- len = strlen (text);
- had_name = FALSE;
- }
-
- for (; list_idx < _NM_META_SETTING_TYPE_NUM; ) {
- const NMMetaSettingInfoEditor *setting_info = &nm_meta_setting_infos_editor[list_idx];
-
- if (!had_name) {
- had_name = TRUE;
- if (!text || strncmp (text, setting_info->general->setting_name, len) == 0)
- return g_strdup (setting_info->general->setting_name);
- }
-
- had_name = FALSE;
- list_idx++;
- if (setting_info->alias) {
- if (!text || strncmp (text, setting_info->alias, len) == 0)
- return g_strdup (setting_info->alias);
- }
- }
-
- return NULL;
+ values = _meta_abstract_complete ((const NMMetaAbstractInfo *) nm_meta_property_info_connection_type,
+ text);
+ return nmc_rl_compentry_func_wrap ((const char *const*) values);
}
static char *
@@ -5586,7 +5557,7 @@ nmcli_editor_tab_completion (const char *text, int start, int end)
/* Choose the right generator function */
if (strcmp (prompt_tmp, EDITOR_PROMPT_CON_TYPE) == 0)
- generator_func = gen_connection_types;
+ generator_func = gen_connection_types (text);
else if (strcmp (prompt_tmp, EDITOR_PROMPT_SETTING) == 0)
generator_func = gen_setting_names;
else if (strcmp (prompt_tmp, EDITOR_PROMPT_PROPERTY) == 0)
@@ -5772,7 +5743,7 @@ save_history_cmds (const char *uuid)
}
}
-/*----------------------------------------------------------------------------*/
+/*****************************************************************************/
static void
editor_show_connection (NMConnection *connection, NmCli *nmc)
@@ -6125,7 +6096,7 @@ editor_sub_usage (const char *command)
}
}
-/*----------------------------------------------------------------------------*/
+/*****************************************************************************/
typedef struct {
NMDevice *device;
@@ -6250,7 +6221,7 @@ activate_connection_editor_cb (GObject *client,
g_clear_error (&error);
}
-/*----------------------------------------------------------------------------*/
+/*****************************************************************************/
static void
print_property_description (NMSetting *setting, const char *prop_name)
diff --git a/clients/cli/nmcli.h b/clients/cli/nmcli.h
index 7203b21c8e..839a49bbc0 100644
--- a/clients/cli/nmcli.h
+++ b/clients/cli/nmcli.h
@@ -32,6 +32,8 @@
typedef gpointer NMPolkitListener;
#endif
+typedef char *(*NmcCompEntryFunc) (const char *, int);
+
/* nmcli exit codes */
typedef enum {
/* Indicates successful execution */
diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c
index 402566bfcf..ddcce8c04e 100644
--- a/clients/common/nm-meta-setting-desc.c
+++ b/clients/common/nm-meta-setting-desc.c
@@ -2272,6 +2272,37 @@ _set_fcn_connection_type (ARGS_SET_FCN)
return TRUE;
}
+static const char *const*
+_complete_fcn_connection_type (ARGS_COMPLETE_FCN)
+{
+ guint i, j;
+ char **result;
+ gsize text_len;
+
+ result = g_new (char *, _NM_META_SETTING_TYPE_NUM * 2 + 1);
+
+ text_len = text ? strlen (text) : 0;
+
+ for (i = 0, j = 0; i < _NM_META_SETTING_TYPE_NUM; i++) {
+ const NMMetaSettingInfoEditor *setting_info = &nm_meta_setting_infos_editor[i];
+ const char *v;
+
+ v = setting_info->alias;
+ if (v) {
+ if (!text || strncmp (text, v, text_len) == 0)
+ result[j++] = g_strdup (v);
+ }
+ if (!text || !*text || !v) {
+ v = setting_info->general->setting_name;
+ if (!text || strncmp (text, v, text_len) == 0)
+ result[j++] = g_strdup (v);
+ }
+ }
+ result[j++] = NULL;
+
+ return (const char *const*) (*out_to_free = result);
+}
+
/* define from libnm-core/nm-setting-connection.c */
#define PERM_USER_PREFIX "user:"
@@ -5451,7 +5482,7 @@ static const NMMetaPropertyInfo property_infos_CONNECTION[] = {
.complete_fcn = _complete_fcn_gobject_devices,
),
},
- {
+ [_NM_META_PROPERTY_TYPE_CONNECTION_TYPE] = {
PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_TYPE),
.is_cli_option = TRUE,
.property_alias = "type",
@@ -5460,6 +5491,7 @@ static const NMMetaPropertyInfo property_infos_CONNECTION[] = {
.property_type = DEFINE_PROPERTY_TYPE (
.get_fcn = _get_fcn_gobject,
.set_fcn = _set_fcn_connection_type,
+ .complete_fcn = _complete_fcn_connection_type,
),
},
{
diff --git a/clients/common/nm-meta-setting-desc.h b/clients/common/nm-meta-setting-desc.h
index 6a750d5c8a..859f453d2f 100644
--- a/clients/common/nm-meta-setting-desc.h
+++ b/clients/common/nm-meta-setting-desc.h
@@ -252,8 +252,10 @@ typedef enum {
enum {
_NM_META_PROPERTY_TYPE_VPN_SERVICE_TYPE = 0,
+ _NM_META_PROPERTY_TYPE_CONNECTION_TYPE = 4,
};
+#define nm_meta_property_info_connection_type (&nm_meta_setting_infos_editor[NM_META_SETTING_TYPE_CONNECTION].properties[_NM_META_PROPERTY_TYPE_CONNECTION_TYPE])
#define nm_meta_property_info_vpn_service_type (&nm_meta_setting_infos_editor[NM_META_SETTING_TYPE_VPN].properties[_NM_META_PROPERTY_TYPE_VPN_SERVICE_TYPE])
struct _NMMetaPropertyInfo {