emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Comint: handle raw tab


From: Stefan Monnier
Subject: Re: Comint: handle raw tab
Date: Tue, 13 Sep 2011 14:19:09 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.50 (gnu/linux)

>> IMO native tab completion for subprocess REPLs is a common enough need
>> that the basic machinery should be handled by Emacs itself, i.e.
>> probably the comint library. I'm somewhat surprised there is no such
>> code yet (or is there, outside Emacs perhaps?).
> I agree with the exposed above, many modern REPLs comint can interact with
> have TAB completion out of the box.  We should use that when it's available
> instead of duplicating efforts.

I agree that would be good.
You can check the gdb completion code in gud.el for an example.


        Stefan


(defun gud-gdb-completions (context command)
  "Completion table for GDB commands.
COMMAND is the prefix for which we seek completion.
CONTEXT is the text before COMMAND on the line."
  (let* ((start (- (point) (field-beginning)))
         (complete-list
          (gud-gdb-run-command-fetch-lines (concat "complete " context command)
                                           (current-buffer)
                                           ;; From string-match above.
                                           (length context))))
    ;; `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.
    ;; This is a problem for completion-in-region which uses an overlay to
    ;; create a field.
    ;; So we restore completion-in-region's field if needed.
    ;; FIXME: change gud-gdb-run-command-fetch-lines so it doesn't modify the
    ;; buffer at all.
    (when (/= start (- (point) (field-beginning)))
      (dolist (ol (overlays-at (1- (point))))
        (when (eq (overlay-get ol 'field) 'completion)
          (move-overlay ol (- (point) start) (overlay-end ol)))))
    ;; Protect against old versions of GDB.
    (and complete-list
         (string-match "^Undefined command: \"complete\"" (car complete-list))
         (error "This version of GDB doesn't support the `complete' command"))
    ;; Sort the list like readline.
    (setq complete-list (sort complete-list (function string-lessp)))
    ;; Remove duplicates.
    (let ((first complete-list)
          (second (cdr complete-list)))
      (while second
        (if (string-equal (car first) (car second))
            (setcdr first (setq second (cdr second)))
          (setq first second
                second (cdr second)))))
    ;; Add a trailing single quote if there is a unique completion
    ;; and it contains an odd number of unquoted single quotes.
    (and (= (length complete-list) 1)
         (let ((str (car complete-list))
               (pos 0)
               (count 0))
           (while (string-match "\\([^'\\]\\|\\\\'\\)*'" str pos)
             (setq count (1+ count)
                   pos (match-end 0)))
           (and (= (mod count 2) 1)
                (setq complete-list (list (concat str "'"))))))
    complete-list))

(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))))
    (list start end
          (completion-table-dynamic
           (apply-partially #'gud-gdb-completions
                            (buffer-substring (comint-line-beginning-position)
                                              start))))))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]