]> git.eshelyaron.com Git - emacs.git/commitdiff
Pcomplete: Better obey `completion-at-point-functions`
authorStefan Monnier <monnier@iro.umontreal.ca>
Fri, 18 Mar 2022 15:59:32 +0000 (11:59 -0400)
committerStefan Monnier <monnier@iro.umontreal.ca>
Fri, 18 Mar 2022 15:59:32 +0000 (11:59 -0400)
Functions on `completion-at-point-functions` should not modify
the buffer.  Pcomplete itself mostly abides by this but Eshell's
use of it doesn't.  Try and catch those cases.  Also fix one of
those cases.

* lisp/pcomplete.el (pcomplete-allow-modifications): New var.
(pcomplete-completions-at-point): Enforce it.
(pcomplete, pcomplete-expand-and-complete, pcomplete-expand):
Rebind it since these commands expect the extra side effects.

* lisp/eshell/em-cmpl.el (eshell--pcomplete-insert-tab): New function,
extracted from `eshell-complete-parse-arguments`.
(eshell-complete-parse-arguments): Use it and obey
`pcomplete-allow-modifications`.

lisp/eshell/em-cmpl.el
lisp/pcomplete.el

index b79475f6e07576598ecbd98652a19f9c7902ec5f..f4c1302629b1f98ec7165183300dc6d37a658f9c 100644 (file)
@@ -311,18 +311,24 @@ to writing a completion function."
       (describe-prefix-bindings)
     (call-interactively 'pcomplete-help)))
 
+(defun eshell--pcomplete-insert-tab ()
+  (if (not pcomplete-allow-modifications)
+      (throw 'pcompleted nil)
+    (insert-and-inherit "\t")
+    (throw 'pcompleted t)))
+
 (defun eshell-complete-parse-arguments ()
   "Parse the command line arguments for `pcomplete-argument'."
   (when (and eshell-no-completion-during-jobs
             (eshell-interactive-process-p))
-    (insert-and-inherit "\t")
-    (throw 'pcompleted t))
+    (eshell--pcomplete-insert-tab))
   (let ((end (point-marker))
        (begin (save-excursion (eshell-bol) (point)))
        (posns (list t))
        args delim)
-    (when (memq this-command '(pcomplete-expand
-                              pcomplete-expand-and-complete))
+    (when (and pcomplete-allow-modifications
+              (memq this-command '(pcomplete-expand
+                                   pcomplete-expand-and-complete)))
       (run-hook-with-args 'eshell-expand-input-functions begin end)
       (if (= begin end)
          (end-of-line))
@@ -335,14 +341,11 @@ to writing a completion function."
               (setq begin (1+ (cadr delim))
                     args (eshell-parse-arguments begin end)))
              ((eq (car delim) ?\()
-              (eshell-complete-lisp-symbol)
-              (throw 'pcompleted t))
+              (throw 'pcompleted (elisp-completion-at-point)))
              (t
-              (insert-and-inherit "\t")
-              (throw 'pcompleted t))))
+              (eshell--pcomplete-insert-tab))))
     (when (get-text-property (1- end) 'comment)
-      (insert-and-inherit "\t")
-      (throw 'pcompleted t))
+      (eshell--pcomplete-insert-tab))
     (let ((pos begin))
       (while (< pos end)
        (if (get-text-property pos 'arg-begin)
index 289312e0bbc48f2e3b50acc4dc6309fd31448043..a1492af89d242759e51fcb6b5055311d893909aa 100644 (file)
@@ -189,6 +189,16 @@ and how is entirely up to the behavior of the
 `pcomplete-parse-arguments-function'."
   :type 'boolean)
 
+(defvar pcomplete-allow-modifications nil
+  "If non-nil, allow effects in `pcomplete-parse-arguments-function'.
+For the `pcomplete' command, it was common for functions in
+`pcomplete-parse-arguments-function' to make modifications to the
+buffer, like expanding variables are such.
+For `completion-at-point-functions', this is not an option any more, so
+this variable is used to tell `pcomplete-parse-arguments-function'
+whether it can do the modifications like it used to, or whether
+it should refrain from doing so.")
+
 (defcustom pcomplete-parse-arguments-function
   #'pcomplete-parse-buffer-arguments
   "A function to call to parse the current line's arguments.
@@ -392,6 +402,9 @@ Same as `pcomplete' but using the standard completion UI."
   ;; imposing the pcomplete UI over the standard UI.
   (catch 'pcompleted
     (let* ((pcomplete-stub)
+           (buffer-read-only
+            ;; Make sure the function obeys `pcomplete-allow-modifications'.
+            (if pcomplete-allow-modifications buffer-read-only t))
            pcomplete-seen pcomplete-norm-func
            pcomplete-args pcomplete-last pcomplete-index
            (pcomplete-autolist pcomplete-autolist)
@@ -526,6 +539,7 @@ completion functions list (it should occur fairly early in the list)."
          pcomplete-last-completion-raw nil)
     (catch 'pcompleted
       (let* ((pcomplete-stub)
+            (pcomplete-allow-modifications t)
             pcomplete-seen pcomplete-norm-func
             pcomplete-args pcomplete-last pcomplete-index
             (pcomplete-autolist pcomplete-autolist)
@@ -551,7 +565,8 @@ completion functions list (it should occur fairly early in the list)."
   "Expand the textual value of the current argument.
 This will modify the current buffer."
   (interactive)
-  (let ((pcomplete-expand-before-complete t))
+  (let ((pcomplete-expand-before-complete t)
+       (pcomplete-allow-modifications t))
     (with-suppressed-warnings ((obsolete pcomplete))
       (pcomplete))))
 
@@ -569,6 +584,7 @@ This will modify the current buffer."
 This will modify the current buffer."
   (interactive)
   (let ((pcomplete-expand-before-complete t)
+       (pcomplete-allow-modifications t)
        (pcomplete-expand-only-p t))
     (with-suppressed-warnings ((obsolete pcomplete))
       (pcomplete))