(insert-and-inherit "\t")
(throw 'pcompleted t)))
+(defun eshell-complete--eval-argument-form (arg)
+ "Evaluate a single Eshell argument form ARG for the purposes of completion."
+ (let ((result (eshell-do-eval `(eshell-commands ,arg) t)))
+ (cl-assert (eq (car result) 'quote))
+ (cadr result)))
+
(defun eshell-complete-parse-arguments ()
"Parse the command line arguments for `pcomplete-argument'."
(when (and eshell-no-completion-during-jobs
(cl-assert (= (length args) (length posns)))
(let ((a args) (i 0) new-start)
(while a
- ;; Remove any top-level `eshell-splice-args' sigils. These
- ;; are meant to be rewritten and can't actually be called.
- (when (and (consp (car a))
- (eq (caar a) 'eshell-splice-args))
- (setcar a (cadar a)))
;; If there's an unreplaced `eshell-operator' sigil, consider
;; the token after it the new start of our arguments.
(when (and (consp (car a))
(not (eq (char-before (1- end)) ?\\)))
(nconc args (list ""))
(nconc posns (list (point))))
+ ;; Evaluate and expand Eshell forms.
+ (let (evaled-args evaled-posns)
+ (cl-mapc
+ (lambda (arg posn)
+ (pcase arg
+ (`(eshell-splice-args ,val)
+ (dolist (subarg (eshell-complete--eval-argument-form val))
+ (push subarg evaled-args)
+ (push posn evaled-posns)))
+ ((pred listp)
+ (push (eshell-complete--eval-argument-form arg) evaled-args)
+ (push posn evaled-posns))
+ (_
+ (push arg evaled-args)
+ (push posn evaled-posns))))
+ args posns)
+ (setq args (nreverse evaled-args)
+ posns (nreverse evaled-posns)))
+ ;; Convert arguments to forms that Pcomplete can understand.
(cons (mapcar
(lambda (arg)
- (let ((val
- (if (listp arg)
- (let ((result
- (eshell-do-eval
- (list 'eshell-commands arg) t)))
- (cl-assert (eq (car result) 'quote))
- (cadr result))
- arg)))
- (cond ((numberp val)
- (setq val (number-to-string val)))
- ;; expand .../ etc that only eshell understands to
- ;; standard ../../
- ((and (stringp val)) (string-match "\\.\\.\\.+/" val)
- (setq val (eshell-expand-multiple-dots val))))
- (or val "")))
+ (cond
+ ((numberp arg)
+ (number-to-string arg))
+ ;; Expand ".../" etc that only Eshell understands to the
+ ;; standard "../../".
+ ((and (stringp arg) (string-match "\\.\\.\\.+/" arg))
+ (eshell-expand-multiple-dots arg))
+ ((null arg)
+ "")
+ (t
+ arg)))
args)
posns)))
(should (equal (car (eshell-complete-parse-arguments))
'("echo" ("foo" "bar")))))))
+(ert-deftest em-cmpl-test/parse-arguments/variable/splice ()
+ "Test parsing arguments with a spliced variable interpolation."
+ (with-temp-eshell
+ (let ((eshell-test-value '("foo" "bar")))
+ (insert "echo $@eshell-test-value")
+ (should (equal (car (eshell-complete-parse-arguments))
+ '("echo" "foo" "bar"))))))
+
(ert-deftest em-cmpl-test/file-completion/unique ()
"Test completion of file names when there's a unique result."
(with-temp-eshell