First of all, sorry about the long delay. I've been meaning to look at
this.
On Wed, Sep 24, 2003 at 04:14:05PM -0700, Jim Ingham wrote:
I was looking at this for some other reason (I want to add an
"interpreter-complete console" type command), and I noticed that
"complete" and the complete_line function that it relies on don't work
when the input text is a filename, and contains more that just the
filename. You can see this easily, do:
(gdb) file /usr/<TAB><TAB>
X11R6 etc info local
share
bin games kerberos lost+found
src
dict i386-glibc21-linux lib man
tmp
doc include libexec sbin
(gdb) complete file /usr/
(gdb)
That isn't right, you should get:
(gdb) complete file /usr/
file /usr/X11R6
file /usr/bin
file /usr/dict
file /usr/doc
file /usr/etc
file /usr/games
file /usr/i386-glibc21-linux
file /usr/include
file /usr/info
file /usr/kerberos
file /usr/lib
file /usr/libexec
file /usr/local
file /usr/lost+found
file /usr/man
file /usr/sbin
file /usr/share
file /usr/src
file /usr/tmp
The attached patch fixes the bug.
The <TAB><TAB> case works because readline advances the first argument
of complete_line past the initial command. But "complete" always
passes both TEXT and LINE_BUFFER as the whole command. This patch
actually does what the comment about file completers above it says it
intends, namely that we should go to the cursor, and then back up to
the first file-wordbreak we find. The old code clearly didn't do
that... Both the <TAB> case and the complete case work now. This
also
makes emacs behave a little better when you try to complete files.
I added a test case for this failure.
I disagree with your analysis. The expectation is that readline may
have broken words prematurely for filenames - which it does, sometimes,
see my mail to gdb@ yesterday - but not failed to break words. So the
caller of complete_line is in error for passing arg. I imagine it
messes up some of the other completers too. Also, you didn't fix
"complete file "; it was right next to the comment in question and had
the same problem.
Here's an alternative patch; tested, no regressions, fixes the problem.
I'll commit it in a few days if no one objects.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
2004-01-19 Daniel Jacobowitz <drow@mvista.com>
* cli/cli-cmds.c: Include readline.h.
(complete_command): Pass the start of the last word to
complete_line.
2004-01-19 Daniel Jacobowitz <drow@mvista.com>
* gdb.base/completion.exp: Kill a stray backslash.
2004-01-19 Jim Ingham <jingham@apple.com>
* gdb.base/completion.exp: Test that "complete file ./gdb.base/compl"
agrees with the result from sending a tab.
Index: cli/cli-cmds.c
===================================================================
RCS file: /cvs/src/src/gdb/cli/cli-cmds.c,v
retrieving revision 1.37
diff -u -p -r1.37 cli-cmds.c
--- cli/cli-cmds.c 17 Dec 2003 21:47:47 -0000 1.37
+++ cli/cli-cmds.c 19 Jan 2004 16:13:31 -0000
@@ -1,6 +1,6 @@
/* GDB CLI commands.
- Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright 2000, 2001, 2002, 2003, 2004 Free Software Foundation,
Inc.
This file is part of GDB.
@@ -20,6 +20,7 @@
Boston, MA 02111-1307, USA. */
#include "defs.h"
+#include <readline/readline.h>
#include <readline/tilde.h>
#include "completer.h"
#include "target.h" /* For baud_rate, remote_debug and
remote_timeout */
@@ -224,7 +225,7 @@ complete_command (char *arg, int from_tt
{
int i;
int argpoint;
- char **completions;
+ char **completions, *point, *arg_prefix;
dont_repeat ();
@@ -232,7 +233,23 @@ complete_command (char *arg, int from_tt
arg = "";
argpoint = strlen (arg);
- completions = complete_line (arg, arg, argpoint);
+ /* complete_line assumes that its first argument is somewhere
within,
+ and except for filenames at the beginning of, the word to be
completed.
+ The following crude imitation of readline's word-breaking tries
to
+ accomodate this. */
+ point = arg + argpoint;
+ while (point > arg)
+ {
+ if (strchr (rl_completer_word_break_characters, point[-1]) != 0)
+ break;
+ point--;
+ }
+
+ arg_prefix = alloca (point - arg + 1);
+ memcpy (arg_prefix, arg, point - arg);
+ arg_prefix[point - arg] = 0;
+
+ completions = complete_line (point, arg, argpoint);
if (completions)
{
@@ -248,7 +265,7 @@ complete_command (char *arg, int from_tt
while (item < size)
{
int next_item;
- printf_unfiltered ("%s\n", completions[item]);
+ printf_unfiltered ("%s%s\n", arg_prefix, completions[item]);
next_item = item + 1;
while (next_item < size
&& ! strcmp (completions[item], completions[next_item]))
Index: testsuite/gdb.base/completion.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/completion.exp,v
retrieving revision 1.20
diff -u -p -r1.20 completion.exp
--- testsuite/gdb.base/completion.exp 13 Jan 2004 23:39:54 -0000 1.20
+++ testsuite/gdb.base/completion.exp 19 Jan 2004 16:13:31 -0000
@@ -657,6 +657,15 @@ gdb_test "cd ${fullsrcdir}" \
"Working directory [string_to_regexp ${fullsrcdir}].*" \
"cd to \${srcdir}"
+send_gdb "complete file ./gdb.base/compl\n"
+sleep 1
+gdb_expect {
+ -re "file ./gdb.base/completion\\.exp.*$gdb_prompt $"
+ { pass "complete-command 'file ./gdb.base/compl'"}
+ -re ".*$gdb_prompt $" { fail "complete-command 'file
./gdb.base/compl'" }
+ timeout { fail "(timeout) complete-command 'file
./gdb.base/compl'" }
+}
+
send_gdb "file ./gdb.base/complet\t"
sleep 1
gdb_expect {
@@ -664,7 +673,6 @@ gdb_expect {
{ send_gdb "\n"
gdb_expect {
-re "\r\nA program is being debugged already\\.
Kill it\\? \\(y or n\\) $"
-\
{ send_gdb "n\n"
gdb_expect {
-re "\r\nProgram not
killed\\.\r\n$gdb_prompt $"\