Don't add a space after the trailing slash when completing ~USER in Eshell

This provides a programmed completion function that works similarly to
~USER completion in 'completion-file-name-table'.

* lisp/eshell/em-dirs.el (eshell-complete-user-reference): Throw a
programmed completion function.

* test/lisp/eshell/em-cmpl-tests.el
(em-cmpl-test/user-ref-completion): Update test.
This commit is contained in:
Jim Porter 2023-02-01 17:48:47 -08:00
parent 4b364a990a
commit 9d48c9844b
2 changed files with 30 additions and 12 deletions

View file

@ -281,15 +281,34 @@ Thus, this does not include the current directory.")
(let ((arg (pcomplete-actual-arg)))
(when (string-match "\\`~[a-z]*\\'" arg)
(setq pcomplete-stub (substring arg 1)
pcomplete-last-completion-raw t)
(throw 'pcomplete-completions
(progn
(eshell-read-user-names)
(pcomplete-uniquify-list
(mapcar
(lambda (user)
(file-name-as-directory (cdr user)))
eshell-user-names)))))))
pcomplete-last-completion-raw t)
;; pcomplete-exit-function #'eshell-complete-user-ref--exit)
(eshell-read-user-names)
(let ((names (pcomplete-uniquify-list
(mapcar (lambda (user)
(file-name-as-directory (cdr user)))
eshell-user-names))))
(throw 'pcomplete-completions
;; Provide a programmed completion table. This works
;; just like completing over the list of names, except
;; it always returns the completed string, never `t'.
;; That's because this is only completing a directory
;; name, and so the completion isn't actually finished
;; yet.
(lambda (string pred action)
(pcase action
('nil ; try-completion
(let ((result (try-completion string names pred)))
(if (eq result t) string result)))
('t ; all-completions
(all-completions string names pred))
('lambda ; test-completion
(let ((result (test-completion string names pred)))
(if (eq result t) string result)))
('metadata
'(metadata (category . file)))
(`(boundaries . ,suffix)
`(boundaries 0 . ,(string-search "/" suffix))))))))))
(defun eshell/pwd (&rest _args)
"Change output from `pwd' to be cleaner."

View file

@ -218,15 +218,14 @@ See <lisp/eshell/esh-var.el>."
"VAR=file.txt ")))))
(ert-deftest em-cmpl-test/user-ref-completion ()
"Test completeion of user references like \"~user\".
"Test completion of user references like \"~user\".
See <lisp/eshell/em-dirs.el>."
(unwind-protect
(with-temp-eshell
(cl-letf (((symbol-function 'eshell-read-user-names)
(lambda () (setq eshell-user-names '((1234 . "user"))))))
;; FIXME: Should this really add a space at the end?
(should (equal (eshell-insert-and-complete "echo ~us")
"echo ~user/ "))))
"echo ~user/"))))
;; Clear the cached user names we set above.
(setq eshell-user-names nil)))