summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiří Klimeš <jklimes@redhat.com>2013-10-03 20:20:58 +0200
committerJiří Klimeš <jklimes@redhat.com>2013-11-22 14:09:10 +0100
commitcdec23d314347acbd2bdbe8d79de9cd2f5e164e4 (patch)
tree0229c2679cb8123c32a42228f8d83b6c11249d34
parenta3c06afc12e0cab6e09ec32139fa5cb0d4d98e2d (diff)
downloadNetworkManager-cdec23d314347acbd2bdbe8d79de9cd2f5e164e4.tar.gz
cli: complete file names for properties whose value is a file name
Note: Tilde expansion is enabled, so ~/abc<TAB> expands the string to /home/joe/abc. However, when user did not use the completion and typed "~/myfile" manually, the path could not be opened. nmcli 802-1x.ca-cert> set ~/newca.crt Error: failed to set 'ca-cert' property: Failed to open file '~/newca.crt': No such file or directory
-rw-r--r--cli/src/connections.c89
1 files changed, 83 insertions, 6 deletions
diff --git a/cli/src/connections.c b/cli/src/connections.c
index 05b3d3435b..fc4b10a300 100644
--- a/cli/src/connections.c
+++ b/cli/src/connections.c
@@ -4588,6 +4588,7 @@ typedef struct {
char **rl_line_buffer_x;
char **rl_prompt_x;
int *rl_attempted_completion_over_x;
+ int *rl_complete_with_tilde_expansion_x;
int *rl_completion_append_character_x;
const char **rl_completer_word_break_characters_x;
void (*rl_free_line_state_func) (void);
@@ -4905,6 +4906,63 @@ should_complete_cmd (const char *line, int end, const char *cmd,
return ret;
}
+static gboolean
+should_complete_files (const char *prompt, const char *line)
+{
+ char *prop = NULL;
+ gboolean found = FALSE;
+ const char *file_properties[] = {
+ /* '802-1x' properties */
+ "ca-cert",
+ "ca-path",
+ "client-cert",
+ "pac-file",
+ "phase2-ca-cert",
+ "phase2-ca-path",
+ "phase2-client-cert",
+ "private-key",
+ "phase2-private-key",
+ /* 'team' and 'team-port' properties */
+ "config",
+ NULL
+ };
+
+ /* If prompt is set take the property name from it, else extract it from line */
+ if (!prompt) {
+ const char *p1;
+ size_t num;
+ p1 = strchr (line, '.');
+ if (p1) {
+ p1++;
+ } else {
+ size_t n1, n2, n3;
+ n1 = strspn (line, " \t");
+ n2 = strcspn (line+n1, " \t\0") + n1;
+ n3 = strspn (line+n2, " \t") + n2;
+ p1 = line + n3;
+ }
+ num = strcspn (p1, " \t\0");
+ prop = g_strndup (p1, num);
+ } else {
+ const char *p1, *dot;
+ size_t num;
+ p1 = strchr (prompt, ' ');
+ /* prompt looks like this: "nmcli 802-1x>" or "nmcli 802-1x.pac-file>" */
+ if (p1) {
+ dot = strchr (p1 + 1, '.');
+ p1 = dot ? dot + 1 : p1;
+ num = strcspn (p1, ">");
+ prop = g_strndup (p1, num);
+ }
+ }
+
+ if (prop) {
+ found = !!nmc_string_is_valid (prop, file_properties, NULL);
+ g_free (prop);
+ }
+ return found;
+}
+
/*
* Attempt to complete on the contents of TEXT. START and END show the
* region of TEXT that contains the word to complete. We can use the
@@ -4928,6 +4986,12 @@ nmcli_editor_tab_completion (char *text, int start, int end)
/* Restore standard append character to space */
*edit_lib_symbols.rl_completion_append_character_x = ' ';
+ /* Disable default filename completion */
+ *edit_lib_symbols.rl_attempted_completion_over_x = 1;
+
+ /* Enable tilde expansion when filenames are completed */
+ *edit_lib_symbols.rl_complete_with_tilde_expansion_x = 1;
+
/* Filter out possible ANSI color escape sequences */
p1 = prompt;
p2 = prompt_tmp = g_strdup (prompt);
@@ -4967,8 +5031,17 @@ nmcli_editor_tab_completion (char *text, int start, int end)
generator_func = gen_setting_names;
else
generator_func = gen_property_names;
- } else if ( ( should_complete_cmd (line, end, "set", &num, NULL)
- || should_complete_cmd (line, end, "remove", &num, NULL)
+ } else if (should_complete_cmd (line, end, "set", &num, NULL)) {
+ if (num < 3) {
+ if (level == 0 && (!dot || dot >= line + end)) {
+ generator_func = gen_setting_names;
+ *edit_lib_symbols.rl_completion_append_character_x = '.';
+ } else
+ generator_func = gen_property_names;
+ } else if (num == 3 && should_complete_files (NULL, line)) {
+ *edit_lib_symbols.rl_attempted_completion_over_x = 0;
+ }
+ } else if ( ( should_complete_cmd (line, end, "remove", &num, NULL)
|| should_complete_cmd (line, end, "describe", &num, NULL))
&& num <= 2) {
if (level == 0 && (!dot || dot >= line + end)) {
@@ -4995,6 +5068,11 @@ nmcli_editor_tab_completion (char *text, int start, int end)
if (start == n1)
generator_func = gen_nmcli_cmds_submenu;
else {
+ if ( should_complete_cmd (line, end, "add", &num, NULL)
+ || should_complete_cmd (line, end, "set", &num, NULL)) {
+ if (num <= 2 && should_complete_files (prompt_tmp, line))
+ *edit_lib_symbols.rl_attempted_completion_over_x = 0;
+ }
if (should_complete_cmd (line, end, "print", &num, NULL) && num <= 2)
generator_func = gen_cmd_print2;
else if (should_complete_cmd (line, end, "help", &num, NULL) && num <= 2)
@@ -5006,10 +5084,6 @@ nmcli_editor_tab_completion (char *text, int start, int end)
if (generator_func)
match_array = edit_lib_symbols.completion_matches_func (text, generator_func);
- /* Disable default filename completion */
- if (!match_array)
- *edit_lib_symbols.rl_attempted_completion_over_x = 1;
-
g_free (prompt_tmp);
g_free (word);
return match_array;
@@ -5063,6 +5137,9 @@ load_cmd_line_edit_lib (void)
if (!g_module_symbol (module, "rl_attempted_completion_over",
(gpointer) (&edit_lib_symbols.rl_attempted_completion_over_x)))
goto error;
+ if (!g_module_symbol (module, "rl_complete_with_tilde_expansion",
+ (gpointer) (&edit_lib_symbols.rl_complete_with_tilde_expansion_x)))
+ goto error;
if (!g_module_symbol (module, "rl_completion_append_character",
(gpointer) (&edit_lib_symbols.rl_completion_append_character_x)))
goto error;