From ce28de5d3a1293ceaf4317520ec8c3d2095ab947 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Fri, 18 Mar 2022 11:59:32 -0400 Subject: [PATCH] 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`. --- lisp/eshell/em-cmpl.el | 23 +++++++++++++---------- lisp/pcomplete.el | 18 +++++++++++++++++- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/lisp/eshell/em-cmpl.el b/lisp/eshell/em-cmpl.el index b79475f6e07..f4c1302629b 100644 --- a/lisp/eshell/em-cmpl.el +++ b/lisp/eshell/em-cmpl.el @@ -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) diff --git a/lisp/pcomplete.el b/lisp/pcomplete.el index 289312e0bbc..a1492af89d2 100644 --- a/lisp/pcomplete.el +++ b/lisp/pcomplete.el @@ -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)) -- 2.39.2