Pcomplete: Better obey completion-at-point-functions

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`.
This commit is contained in:
Stefan Monnier 2022-03-18 11:59:32 -04:00
parent f51e12fece
commit ce28de5d3a
2 changed files with 30 additions and 11 deletions

View 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)

View 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))