Be more cautious in completing Eshell variable assignments

Previously, Eshell treated cases like the second argument in "tar
--directory=dir" as a variable assignment, but that prevented
'pcomplete/tar' from implementing its own completion for that
argument (bug#61778).

* lisp/eshell/esh-var.el (eshell-complete-variable-assignment): Only
handle completion when all initial arguments are variable assignments.

* test/lisp/eshell/em-cmpl-tests.el
(em-cmpl-test/variable-assign-completion/non-assignment): New test.
This commit is contained in:
Jim Porter 2023-02-24 21:49:54 -08:00
parent 2baf08683f
commit 9565e34762
2 changed files with 27 additions and 5 deletions

View file

@ -862,11 +862,19 @@ START and END."
(defun eshell-complete-variable-assignment ()
"If there is a variable assignment, allow completion of entries."
(let ((arg (pcomplete-actual-arg)) pos)
(when (string-match (concat "\\`" eshell-variable-name-regexp "=") arg)
(setq pos (match-end 0))
(if (string-match "\\(:\\)[^:]*\\'" arg)
(setq pos (match-end 1)))
(catch 'not-assignment
;; The current argument can only be a variable assignment if all
;; arguments leading up to it are also variable assignments. See
;; `eshell-handle-local-variables'.
(dotimes (offset (1+ pcomplete-index))
(unless (string-match (concat "\\`" eshell-variable-name-regexp "=")
(pcomplete-actual-arg 'first offset))
(throw 'not-assignment nil)))
;; We have a variable assignment. Handle it.
(let ((arg (pcomplete-actual-arg))
(pos (match-end 0)))
(when (string-match "\\(:\\)[^:]*\\'" arg)
(setq pos (match-end 1)))
(setq pcomplete-stub (substring arg pos))
(throw 'pcomplete-completions (pcomplete-entries)))))

View file

@ -217,6 +217,20 @@ See <lisp/eshell/esh-var.el>."
(should (equal (eshell-insert-and-complete "VAR=f")
"VAR=file.txt ")))))
(ert-deftest em-cmpl-test/variable-assign-completion/non-assignment ()
"Test completion of things that look like variable assignment, but aren't.
For example, the second argument in \"tar --directory=dir\" looks
like it could be a variable assignment, but it's not. We should
let `pcomplete-tar' handle it instead.
See <lisp/eshell/esh-var.el>."
(with-temp-eshell
(ert-with-temp-directory default-directory
(write-region nil nil (expand-file-name "file.txt"))
(make-directory "dir")
(should (equal (eshell-insert-and-complete "tar --directory=")
"tar --directory=dir/")))))
(ert-deftest em-cmpl-test/user-ref-completion ()
"Test completion of user references like \"~user\".
See <lisp/eshell/em-dirs.el>."