public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Andrew Burgess <aburgess@redhat.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: lsix@lancelotsix.com, gdb-patches@sourceware.org
Subject: Re: [PATCH 2/6] gdb: move display of completion results into completion_result class
Date: Sat, 13 Apr 2024 10:09:52 +0100	[thread overview]
Message-ID: <87cyqt4oin.fsf@redhat.com> (raw)
In-Reply-To: <86zftxrcpx.fsf@gnu.org>

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Andrew Burgess <aburgess@redhat.com>
>> Cc: lsix@lancelotsix.com, gdb-patches@sourceware.org
>> Date: Fri, 12 Apr 2024 23:20:33 +0100
>> 
>> OK, so now the bad news.
>> 
>> My patched GDB doesn't "just work" with emacs.
>> 
>> Remember though, an unpatched GDB doesn't work either when trying to
>> complete a filename with spaces in, so it's not that I've made things
>> worse.
>> 
>> I tracked at least one bug down to this function in gud.el:
>> 
>>   (defun gud-gdb-completion-at-point ()
>>     "Return the data to complete the GDB command before point."
>>     (let ((end (point))
>>           (start
>>            (save-excursion
>>              (skip-chars-backward "^ " (comint-line-beginning-position))
>>              (point))))
>>       ;; FIXME: `gud-gdb-run-command-fetch-lines' has some nasty side-effects on
>>       ;; the buffer (via `gud-delete-prompt-marker'): it removes the prompt and
>>       ;; then re-adds it later, thus messing up markers and overlays along the
>>       ;; way (bug#18282).
>>       ;; We use an "insert-before" marker for `start', since it's typically right
>>       ;; after the prompt, which works around the problem, but is a hack (and
>>       ;; comes with other downsides, e.g. if completion adds text at `start').
>>       (list (copy-marker start t) end
>>             (completion-table-dynamic
>>              (apply-partially gud-gdb-completion-function
>>                               (buffer-substring (comint-line-beginning-position)
>>                                                 start))))))
>>                                                 
>> This is trying to figure out everything before the completion word on
>> the current line and doing the apply-partial with this context on
>> gud-gdb-completion-function.
>> 
>> So if we are completing 'file /tmp/abc<tab>' then we'd end up doing:
>> 
>>   (apply-partial gud-gdb-completion-function "file ")
>> 
>> The completion context is calculated as running from the start of the
>> line up to 'start', which is calculated in the 'let'.  And 'start' is
>> calculated by starting from 'point' and moving backward to the first
>> whitespace.
>> 
>> That's not going to work for completing any line that contains a space.
>> 
>> I think this function would need to get smarter to understand about
>> escaping and quoting.
>
> Yes.  Would you mind submitting a bug report about that, using the
> command "M-x report-emacs-bug"?

I absolutely will file the bug report once this series (or whatever this
series becomes) is merged.  However, I wanted to see if there were
additional bugs hiding in the emacs code, these might indicate changes
that need to be made (or not made) on the GDB side.

So the good news is, that with a little hacking I managed to get emacs
working!

Disclaimer: My emacs lisp knowledge is pretty weak, so please consider
this a proof of concept rather than code I'm actually suggesting should
be merged into emacs.  When I file the bug I'll include this code again,
but by adding it here we can hopefully see what needs to change.

The new and updated emacs code is at the end of this email if anyone
wants to play with emacs and this new completion.  Drop this new code
into a file, load the emacs 'gdb' mode, then eval the new code.  This
adds some new functions, and replaces one existing function.

With this in place I now get completion for filenames containing
whitespace.  Given this directory tree:

  /tmp/eee/
  ├── aa bb
  │   ├── f1
  │   └── f2
  └── aa cc
      ├── g1
      └── g2

  (gdb) file /tmp/eee/aa<TAB>
    =>  file /tmp/eee/aa\ <TAB>
  Possible completions are:		<--- These are offered in a new buffer.
  /tmp/eee/aa\ bb/			<--- I select this entry.
  /tmp/eee/aa\ cc/
    => file /tmp/eee/aa\ bb/<TAB>
    => file /tmp/eee/aa\ bb/f<TAB>
  Possible completions are:		<--- These are offered in a new buffer.
  /tmp/eee/aa\ bb/f1
  /tmp/eee/aa\ bb/f2			<--- I select this entry.
    => file /tmp/eee/aa\ bb/f2<ENTER>
  ... gdb tries to load the file ...

And if also works with quoting:

  (gdb) file "/tmp/eee/a<TAB>
    =>  file "/tmp/eee/aa <TAB>
  Possible completions are:		<--- These are offered in a new buffer.
  "/tmp/eee/aa bb/
  "/tmp/eee/aa cc/			<--- I select this entry.
    =>  file "/tmp/eee/aa cc/<TAB>
    =>  file "/tmp/eee/aa cc/g<TAB>
  Possible completions are:		<--- These are offered in a new buffer.
  "/tmp/eee/aa cc/g1"			<--- I select this entry.
  "/tmp/eee/aa cc/g2"
    =>  file "/tmp/eee/aa cc/g1"<ENTER>
 ... gdb tries to load the file ...

As I said, I'm not claiming that emacs is "fixed", but I think I've
shown what needs to be done to get this working, and also I've
satisfied myself that everything can be made to work.

Thanks,
Andrew



---

;; New function: Return true if the character at POS is escaped, that
;; is, is the character as POS preceeded by a backslash.
(defun gud-gdb-is-char-escaped (pos)
  (char-equal ?\\ (char-before pos)))

;; New function: Move point forward as skip-chars-forward does,
;; passing CHARS and LIMIT to skip-chars-forward.  However, after
;; calling skip-chars-forward, if the character we are looking at is
;; escaped (with a backslash) then skip that character, and call
;; skip-chars-forward again.
(defun gud-gdb-skip-to-unquoted (chars limit)
  (while (and (< (point) limit)
              (progn
                (skip-chars-forward chars limit)
                (if (gud-gdb-is-char-escaped (point))
                    (progn
                      (forward-char)
                      t)
                  nil)))))

;; New function: Move point forward skipping over a 'word'.  A word
;; can be quoted, starts with a single or double quote, in which case
;; the corresponding quote marks the end of the word.  Or a word can
;; be unquoted, in which case the word ends at the next white space.
;;
;; Never move forward past LIMIT.
;;
;; In an unquoted word white space can be escaped.
;;
;; In a double quoted word, double quotes can be escaped.
(defun gud-gdb-forward-maybe-quoted-word (limit)
  (cond ((char-equal ?\' (char-after))
         (progn
           (forward-char)
           (skip-chars-forward "^'" limit)))
        ((char-equal ?\" (char-after))
         (progn
           (forward-char)
           (gud-gdb-skip-to-unquoted "^\"" limit)))
        (t
         (progn
           (gud-gdb-skip-to-unquoted "^[:space:]" limit)))))

;; Assuming point is at the start of a line, return the position for
;; the start of a completion word.  The point will be moved by calling
;; this function.
;;
;; Never search past LIMIT.
;;
;; The completion word is the last word on the line, the word might be
;; quoted though.
(defun gud-gdb-find-completion-word (limit)
  (let ((completion-word-start nil))
    (while (< (point) limit)
      (setf completion-word-start (point))
      (gud-gdb-forward-maybe-quoted-word limit)
      (skip-chars-forward " " limit))

    completion-word-start))

;; This replaces an existing emacs function.  I've changed the logic
;; for finding the completion word.
(defun gud-gdb-completion-at-point ()
  "Return the data to complete the GDB command before point."
  (let* ((end (point))
        (start
         (save-excursion
           (goto-char (comint-line-beginning-position))
           (gud-gdb-find-completion-word end))))
    ;; FIXME: `gud-gdb-run-command-fetch-lines' has some nasty side-effects on
    ;; the buffer (via `gud-delete-prompt-marker'): it removes the prompt and
    ;; then re-adds it later, thus messing up markers and overlays along the
    ;; way (bug#18282).
    ;; We use an "insert-before" marker for `start', since it's typically right
    ;; after the prompt, which works around the problem, but is a hack (and
    ;; comes with other downsides, e.g. if completion adds text at `start').
    (list (copy-marker start t) end
          (completion-table-dynamic
           (apply-partially gud-gdb-completion-function
                            (buffer-substring (comint-line-beginning-position)
                                              start))))))


  reply	other threads:[~2024-04-13  9:09 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-29 11:42 [PATCH 0/6] Further filename completion improvements Andrew Burgess
2024-03-29 11:42 ` [PATCH 1/6] gdb: improve escaping when completing filenames Andrew Burgess
2024-03-30 23:48   ` Lancelot SIX
2024-03-29 11:42 ` [PATCH 2/6] gdb: move display of completion results into completion_result class Andrew Burgess
2024-03-29 12:14   ` Eli Zaretskii
2024-03-30 23:30     ` Lancelot SIX
2024-03-31  5:49       ` Eli Zaretskii
2024-04-12 17:24         ` Andrew Burgess
2024-04-12 18:42           ` Eli Zaretskii
2024-04-12 22:20             ` Andrew Burgess
2024-04-13  6:36               ` Eli Zaretskii
2024-04-13  9:09                 ` Andrew Burgess [this message]
2024-04-13  9:46                   ` Eli Zaretskii
2024-04-12 17:31       ` Andrew Burgess
2024-03-29 11:42 ` [PATCH 3/6] gdb: simplify completion_result::print_matches Andrew Burgess
2024-03-30 23:48   ` Lancelot SIX
2024-03-29 11:42 ` [PATCH 4/6] gdb: add match formatter mechanism for 'complete' command output Andrew Burgess
2024-03-30 23:49   ` Lancelot SIX
2024-03-31  5:55     ` Eli Zaretskii
2024-04-12 17:42       ` Andrew Burgess
2024-04-12 18:44         ` Eli Zaretskii
2024-04-12 22:29           ` Andrew Burgess
2024-04-13  6:39             ` Eli Zaretskii
2024-03-29 11:42 ` [PATCH 5/6] gdb: apply escaping to filenames in 'complete' results Andrew Burgess
2024-03-29 11:42 ` [PATCH 6/6] gdb: improve gdb_rl_find_completion_word for quoted words Andrew Burgess
2024-04-20  9:10 ` [PATCHv2 0/8] Further filename completion improvements Andrew Burgess
2024-04-20  9:10   ` [PATCHv2 1/8] gdb/doc: document how filename arguments are formatted Andrew Burgess
2024-04-20  9:44     ` Eli Zaretskii
2024-04-27 10:01       ` Andrew Burgess
2024-04-27 10:06         ` Eli Zaretskii
2024-04-29  9:10           ` Andrew Burgess
2024-04-20  9:10   ` [PATCHv2 2/8] gdb: split apart two different types of filename completion Andrew Burgess
2024-04-20  9:10   ` [PATCHv2 3/8] gdb: improve escaping when completing filenames Andrew Burgess
2024-04-20  9:10   ` [PATCHv2 4/8] gdb: move display of completion results into completion_result class Andrew Burgess
2024-04-20  9:10   ` [PATCHv2 5/8] gdb: simplify completion_result::print_matches Andrew Burgess
2024-04-20  9:10   ` [PATCHv2 6/8] gdb: add match formatter mechanism for 'complete' command output Andrew Burgess
2024-04-20  9:10   ` [PATCHv2 7/8] gdb: apply escaping to filenames in 'complete' results Andrew Burgess
2024-04-20  9:10   ` [PATCHv2 8/8] gdb: improve gdb_rl_find_completion_word for quoted words Andrew Burgess

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87cyqt4oin.fsf@redhat.com \
    --to=aburgess@redhat.com \
    --cc=eliz@gnu.org \
    --cc=gdb-patches@sourceware.org \
    --cc=lsix@lancelotsix.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).