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
This commit is contained in:
@@ -4588,6 +4588,7 @@ typedef struct {
|
|||||||
char **rl_line_buffer_x;
|
char **rl_line_buffer_x;
|
||||||
char **rl_prompt_x;
|
char **rl_prompt_x;
|
||||||
int *rl_attempted_completion_over_x;
|
int *rl_attempted_completion_over_x;
|
||||||
|
int *rl_complete_with_tilde_expansion_x;
|
||||||
int *rl_completion_append_character_x;
|
int *rl_completion_append_character_x;
|
||||||
const char **rl_completer_word_break_characters_x;
|
const char **rl_completer_word_break_characters_x;
|
||||||
void (*rl_free_line_state_func) (void);
|
void (*rl_free_line_state_func) (void);
|
||||||
@@ -4905,6 +4906,63 @@ should_complete_cmd (const char *line, int end, const char *cmd,
|
|||||||
return ret;
|
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
|
* 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
|
* 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 */
|
/* Restore standard append character to space */
|
||||||
*edit_lib_symbols.rl_completion_append_character_x = ' ';
|
*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 */
|
/* Filter out possible ANSI color escape sequences */
|
||||||
p1 = prompt;
|
p1 = prompt;
|
||||||
p2 = prompt_tmp = g_strdup (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;
|
generator_func = gen_setting_names;
|
||||||
else
|
else
|
||||||
generator_func = gen_property_names;
|
generator_func = gen_property_names;
|
||||||
} else if ( ( should_complete_cmd (line, end, "set", &num, NULL)
|
} else if (should_complete_cmd (line, end, "set", &num, NULL)) {
|
||||||
|| should_complete_cmd (line, end, "remove", &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))
|
|| should_complete_cmd (line, end, "describe", &num, NULL))
|
||||||
&& num <= 2) {
|
&& num <= 2) {
|
||||||
if (level == 0 && (!dot || dot >= line + end)) {
|
if (level == 0 && (!dot || dot >= line + end)) {
|
||||||
@@ -4995,6 +5068,11 @@ nmcli_editor_tab_completion (char *text, int start, int end)
|
|||||||
if (start == n1)
|
if (start == n1)
|
||||||
generator_func = gen_nmcli_cmds_submenu;
|
generator_func = gen_nmcli_cmds_submenu;
|
||||||
else {
|
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)
|
if (should_complete_cmd (line, end, "print", &num, NULL) && num <= 2)
|
||||||
generator_func = gen_cmd_print2;
|
generator_func = gen_cmd_print2;
|
||||||
else if (should_complete_cmd (line, end, "help", &num, NULL) && num <= 2)
|
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)
|
if (generator_func)
|
||||||
match_array = edit_lib_symbols.completion_matches_func (text, 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 (prompt_tmp);
|
||||||
g_free (word);
|
g_free (word);
|
||||||
return match_array;
|
return match_array;
|
||||||
@@ -5063,6 +5137,9 @@ load_cmd_line_edit_lib (void)
|
|||||||
if (!g_module_symbol (module, "rl_attempted_completion_over",
|
if (!g_module_symbol (module, "rl_attempted_completion_over",
|
||||||
(gpointer) (&edit_lib_symbols.rl_attempted_completion_over_x)))
|
(gpointer) (&edit_lib_symbols.rl_attempted_completion_over_x)))
|
||||||
goto error;
|
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",
|
if (!g_module_symbol (module, "rl_completion_append_character",
|
||||||
(gpointer) (&edit_lib_symbols.rl_completion_append_character_x)))
|
(gpointer) (&edit_lib_symbols.rl_completion_append_character_x)))
|
||||||
goto error;
|
goto error;
|
||||||
|
Reference in New Issue
Block a user