With the quoted filename completion work that I did last year the
deprecated_filename_completer function will now only complete a single
word as a filename, for example:
(gdb) save breakpoints /tm<TAB>
The 'save breakpoints' command uses the deprecated_filename_completer
completion function. In the above '/tm' will complete to '/tmp/' as
expected. However, if you try this:
(gdb) save breakpoints /tmp/ /tm<TAB>
The second '/tm' will not complete for GDB 16.x, but will complete
with GDB 15.x as GDB 15.x is before my changes were merged.
What's actually happening here is that, before my changes, the
filename completion was breaking words on white space, so in the above
the first '/tmp/' and the second '/tm' are seen as separate words for
completion, the second word is therefore seen as the start of a new
filename.
After my changes, deprecated_filename_completer allows spaces to be
part of the filename, so in the above, GDB is actually trying to
complete a filename '/tmp/ /tm' which likely doesn't exist, and so
completion stops.
This change for how deprecated_filename_completer works makes sense,
commands like 'save breakpoints' take their complete command arguments
and treat it as a single filename, so given this:
(gdb) save breakpoints /tmp/ /tm<ENTER>
GDB really will try to save breakpoints to a file called '/tmp/ /tm',
weird as that may seem. How GDB interprets the command arguments
didn't change with my completion patches, I simply brought completion
into line with how GDB interprets the arguments.
The patches I'm talking about here are this set:
*
4076f962e8c gdb: split apart two different types of filename completion
*
dc22ab49e9b gdb: deprecated filename_completer and associated functions
*
35036875913 gdb: improve escaping when completing filenames
*
1d1df753977 gdb: move display of completion results into completion_result class
*
bbbfe4af4fb gdb: simplify completion_result::print_matches
*
2bebc9ee270 gdb: add match formatter mechanism for 'complete' command output
*
f2f866c6ca8 gdb: apply escaping to filenames in 'complete' results
*
8f87fcb1daf gdb: improve gdb_rl_find_completion_word for quoted words
*
67b8e30af90 gdb: implement readline rl_directory_rewrite_hook callback
*
1be3b2e82f7 gdb: extend completion of quoted filenames to work in brkchars phase
*
9dedc2ac713 gdb: fix for completing a second filename for a command
*
4339a3ffc39 gdb: fix filename completion in the middle of a line
Bug PR gdb/32982 identifies a problem with the shell command;
completion broke between 15.x and 16.x. The shell command also uses
deprecated_filename_completer for completion. But consider a shell
command line:
(gdb) shell ls /tm<TAB>
The arguments to the shell command are 'ls /tm' at the point <TAB> is
pressed. Under the old 15.x completion GDB would split the words on
white space and then try to complete '/tm' as a filename.
Under the 16.x model, GDB completes all the arguments as a single
filename, that is 'ls /tm', which is unlikely to match any filenames,
and so completion fails.
The fix is to write a custom completion function for the shell_command
function (cli/cli-cmds.c), this custom completion function will skip
forward to find the last word in the arguments, and then try to
complete that, so in the above example, GDB will skip over 'ls ', and
then tries to complete '/tm', which is exactly what we want.
Given that the filenames passed to the shell command are forwarded to
an actual shell, I have switched over the new quoted filename
completion function for the shell command, this means that white space
within a filename will be escaped with a backslash by the completion
function, which is likely what the user wants, this means the filename
will arrive in the (actual) shell as a single word, rather than
splitting on white space and arriving as two words.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32982
Reviewed-By: Tom Tromey <tom@tromey.com>
shell_escape (arg, from_tty);
}
+/* Completion for the shell command. Currently, this just uses filename
+ completion, but we could, potentially, complete command names from $PATH
+ for the first word, which would make this even more shell like. */
+
+static void
+shell_command_completer (struct cmd_list_element *ignore,
+ completion_tracker &tracker,
+ const char *text, const char * /* word */)
+{
+ tracker.set_use_custom_word_point (true);
+ const char *word
+ = advance_to_filename_maybe_quoted_complete_word_point (tracker, text);
+ filename_maybe_quoted_completer (ignore, tracker, text, word);
+}
+
static void
edit_command (const char *arg, int from_tty)
{
= add_com ("shell", class_support, shell_command, _("\
Execute the rest of the line as a shell command.\n\
With no arguments, run an inferior shell."));
- set_cmd_completer (shell_cmd, deprecated_filename_completer);
+ set_cmd_completer_handle_brkchars (shell_cmd, shell_command_completer);
add_com_alias ("!", shell_cmd, class_support, 0);
remove-symbol-file \
"target core" "target exec" "target tfile" \
"maint print c-tdesc" "save gdb-index"
- "save gdb-index -dwarf-5" }
+ "save gdb-index -dwarf-5" "shell ls"}
if { [allow_compile_tests] } {
lappend all_cmds "compile file"
}
run_quoting_and_escaping_tests_1 $root $cmd
}
}
+
+ # Some additional testing of shell command. Test 'shell' and '!'
+ # when there are multiple filenames on the command line. This
+ # focuses on completion of the final filename. There is also some
+ # testing of the shell command above, this tests completion within
+ # the line.
+ foreach_with_prefix shell_cmd { "shell " "!" } {
+ foreach suffix { "aaa/aa bb" "bb2/dir 1/unique file" } {
+ set dir $root/$suffix
+
+ regsub -all " " "$dir" "\\ " dir_with_backslash
+
+ with_test_prefix "suffix='$suffix'" {
+ with_test_prefix "with_backslash" {
+ run_quoting_and_escaping_tests_1 $root "${shell_cmd}ls $dir_with_backslash"
+ }
+ with_test_prefix "with double quotes" {
+ run_quoting_and_escaping_tests_1 $root "${shell_cmd}ls \"$dir\""
+ }
+ with_test_prefix "with single quotes" {
+ run_quoting_and_escaping_tests_1 $root "${shell_cmd}ls '$dir'"
+ }
+ }
+ }
+ }
}
# Helper for run_unquoted_tests. ROOT is the root directory as setup