Merge remote-tracking branch 'origin/master' into feature/android
This commit is contained in:
commit
4bcf251308
11 changed files with 150 additions and 72 deletions
|
@ -574,7 +574,7 @@
|
|||
((memq state '(insert-state replace-state))
|
||||
viper-minibuffer-insert-face))))
|
||||
|
||||
(if (viper-is-in-minibuffer)
|
||||
(if (and (viper-is-in-minibuffer) viper-enable-minibuffer-faces)
|
||||
(viper-set-minibuffer-overlay))
|
||||
)
|
||||
|
||||
|
|
|
@ -317,8 +317,7 @@ to writing a completion function."
|
|||
(eshell--pcomplete-insert-tab))
|
||||
(let ((end (point-marker))
|
||||
(begin (save-excursion (beginning-of-line) (point)))
|
||||
(posns (list t))
|
||||
args delim)
|
||||
args posns delim)
|
||||
(when (and pcomplete-allow-modifications
|
||||
(memq this-command '(pcomplete-expand
|
||||
pcomplete-expand-and-complete)))
|
||||
|
@ -330,21 +329,25 @@ to writing a completion function."
|
|||
(catch 'eshell-incomplete
|
||||
(ignore
|
||||
(setq args (eshell-parse-arguments begin end)))))
|
||||
(cond ((memq (car delim) '(?\{ ?\<))
|
||||
(cond ((member (car delim) '("{" "${" "$<"))
|
||||
(setq begin (1+ (cadr delim))
|
||||
args (eshell-parse-arguments begin end)))
|
||||
((eq (car delim) ?\()
|
||||
((member (car delim) '("$'" "$\""))
|
||||
;; Add the (incomplete) argument to our arguments, and
|
||||
;; note its position.
|
||||
(setq args (append (nth 2 delim) (list (car delim))))
|
||||
(push (- (nth 1 delim) 2) posns))
|
||||
((member (car delim) '("(" "$("))
|
||||
(throw 'pcompleted (elisp-completion-at-point)))
|
||||
(t
|
||||
(eshell--pcomplete-insert-tab))))
|
||||
(when (get-text-property (1- end) 'comment)
|
||||
(eshell--pcomplete-insert-tab))
|
||||
(let ((pos begin))
|
||||
(while (< pos end)
|
||||
(if (get-text-property pos 'arg-begin)
|
||||
(nconc posns (list pos)))
|
||||
(setq pos (1+ pos))))
|
||||
(setq posns (cdr posns))
|
||||
(let ((pos (1- end)))
|
||||
(while (>= pos begin)
|
||||
(when (get-text-property pos 'arg-begin)
|
||||
(push pos posns))
|
||||
(setq pos (1- pos))))
|
||||
(cl-assert (= (length args) (length posns)))
|
||||
(let ((a args) (i 0) new-start)
|
||||
(while a
|
||||
|
|
|
@ -281,15 +281,32 @@ 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)
|
||||
(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 for
|
||||
;; `try-completion', 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
|
||||
(test-completion string names pred))
|
||||
('metadata
|
||||
'(metadata (category . file)))
|
||||
(`(boundaries . ,suffix)
|
||||
`(boundaries 0 . ,(string-search "/" suffix))))))))))
|
||||
|
||||
(defun eshell/pwd (&rest _args)
|
||||
"Change output from `pwd' to be cleaner."
|
||||
|
|
|
@ -171,7 +171,7 @@ interpretation."
|
|||
(end (eshell-find-delimiter
|
||||
delim (if (eq delim ?\[) ?\] ?\)))))
|
||||
(if (not end)
|
||||
(throw 'eshell-incomplete delim)
|
||||
(throw 'eshell-incomplete (char-to-string delim))
|
||||
(if (and (eshell-using-module 'eshell-pred)
|
||||
(eshell-arg-delimiter (1+ end)))
|
||||
(ignore (goto-char here))
|
||||
|
|
|
@ -293,7 +293,7 @@ This function is specially for adding onto `eshell-parse-argument-hook'."
|
|||
(forward-char)
|
||||
(let ((end (eshell-find-delimiter ?\( ?\))))
|
||||
(if (not end)
|
||||
(throw 'eshell-incomplete ?\()
|
||||
(throw 'eshell-incomplete "(")
|
||||
(when (eshell-arg-delimiter (1+ end))
|
||||
(save-restriction
|
||||
(narrow-to-region (point) end)
|
||||
|
|
|
@ -421,7 +421,7 @@ backslash is in a quoted string, the backslash and the character
|
|||
after are both returned."
|
||||
(when (eq (char-after) ?\\)
|
||||
(when (eshell-looking-at-backslash-return (point))
|
||||
(throw 'eshell-incomplete ?\\))
|
||||
(throw 'eshell-incomplete "\\"))
|
||||
(forward-char 2) ; Move one char past the backslash.
|
||||
(let ((special-chars (if eshell-current-quoted
|
||||
eshell-special-chars-inside-quoting
|
||||
|
@ -447,7 +447,7 @@ after are both returned."
|
|||
(if (eq (char-after) ?\')
|
||||
(let ((end (eshell-find-delimiter ?\' ?\')))
|
||||
(if (not end)
|
||||
(throw 'eshell-incomplete ?\')
|
||||
(throw 'eshell-incomplete "'")
|
||||
(let ((string (buffer-substring-no-properties (1+ (point)) end)))
|
||||
(goto-char (1+ end))
|
||||
(while (string-match "''" string)
|
||||
|
@ -460,7 +460,7 @@ after are both returned."
|
|||
(let* ((end (eshell-find-delimiter ?\" ?\" nil nil t))
|
||||
(eshell-current-quoted t))
|
||||
(if (not end)
|
||||
(throw 'eshell-incomplete ?\")
|
||||
(throw 'eshell-incomplete "\"")
|
||||
(prog1
|
||||
(save-restriction
|
||||
(forward-char)
|
||||
|
@ -514,7 +514,7 @@ If the form has no `type', the syntax is parsed as if `type' were
|
|||
t)) ;; buffer-p is non-nil by default.
|
||||
(end (eshell-find-delimiter ?\< ?\>)))
|
||||
(when (not end)
|
||||
(throw 'eshell-incomplete ?\<))
|
||||
(throw 'eshell-incomplete "#<"))
|
||||
(if (eshell-arg-delimiter (1+ end))
|
||||
(prog1
|
||||
(list (if buffer-p 'get-buffer-create 'get-process)
|
||||
|
|
|
@ -681,7 +681,7 @@ This means an exit code of 0."
|
|||
(not (eq (char-after (1+ (point))) ?\}))))
|
||||
(let ((end (eshell-find-delimiter ?\{ ?\})))
|
||||
(if (not end)
|
||||
(throw 'eshell-incomplete ?\{)
|
||||
(throw 'eshell-incomplete "{")
|
||||
(when (eshell-arg-delimiter (1+ end))
|
||||
(prog1
|
||||
`(eshell-as-subcommand
|
||||
|
@ -698,7 +698,7 @@ This means an exit code of 0."
|
|||
(condition-case nil
|
||||
(read (current-buffer))
|
||||
(end-of-file
|
||||
(throw 'eshell-incomplete ?\()))))
|
||||
(throw 'eshell-incomplete "(")))))
|
||||
(if (eshell-arg-delimiter)
|
||||
`(eshell-command-to-value
|
||||
(eshell-lisp-command (quote ,obj)))
|
||||
|
|
|
@ -580,7 +580,7 @@ will return the parsed command."
|
|||
(setq command (eshell-parse-command (cons beg end)
|
||||
args t)))))
|
||||
(ignore
|
||||
(message "Expecting completion of delimiter %c ..."
|
||||
(message "Expecting completion of delimiter %s ..."
|
||||
(if (listp delim)
|
||||
(car delim)
|
||||
delim)))
|
||||
|
|
|
@ -434,9 +434,14 @@ the values of nil for each."
|
|||
|
||||
(defun eshell-envvar-names (&optional environment)
|
||||
"Return a list of currently visible environment variable names."
|
||||
(mapcar (lambda (x)
|
||||
(substring x 0 (string-search "=" x)))
|
||||
(or environment process-environment)))
|
||||
(delete-dups
|
||||
(append
|
||||
;; Real environment variables
|
||||
(mapcar (lambda (x)
|
||||
(substring x 0 (string-search "=" x)))
|
||||
(or environment process-environment))
|
||||
;; Eshell variable aliases
|
||||
(mapcar #'car eshell-variable-aliases-list))))
|
||||
|
||||
(defun eshell-environment-variables ()
|
||||
"Return a `process-environment', fully updated.
|
||||
|
@ -503,7 +508,7 @@ Possible variable references are:
|
|||
((eq (char-after) ?{)
|
||||
(let ((end (eshell-find-delimiter ?\{ ?\})))
|
||||
(if (not end)
|
||||
(throw 'eshell-incomplete ?\{)
|
||||
(throw 'eshell-incomplete "${")
|
||||
(forward-char)
|
||||
(prog1
|
||||
`(eshell-apply-indices
|
||||
|
@ -527,7 +532,7 @@ Possible variable references are:
|
|||
((eq (char-after) ?\<)
|
||||
(let ((end (eshell-find-delimiter ?\< ?\>)))
|
||||
(if (not end)
|
||||
(throw 'eshell-incomplete ?\<)
|
||||
(throw 'eshell-incomplete "$<")
|
||||
(let* ((temp (make-temp-file temporary-file-directory))
|
||||
(cmd (concat (buffer-substring (1+ (point)) end)
|
||||
" > " temp)))
|
||||
|
@ -560,15 +565,19 @@ Possible variable references are:
|
|||
(current-buffer)))))
|
||||
indices ,eshell-current-quoted)
|
||||
(end-of-file
|
||||
(throw 'eshell-incomplete ?\())))
|
||||
(throw 'eshell-incomplete "$("))))
|
||||
((looking-at (rx-to-string
|
||||
`(or "'" ,(if eshell-current-quoted "\\\"" "\""))))
|
||||
(eshell-with-temp-command
|
||||
(or (eshell-unescape-inner-double-quote (point-max))
|
||||
(cons (point) (point-max)))
|
||||
(let ((name (if (eq (char-after) ?\')
|
||||
(eshell-parse-literal-quote)
|
||||
(eshell-parse-double-quote))))
|
||||
(let (name)
|
||||
(when-let ((delim
|
||||
(catch 'eshell-incomplete
|
||||
(ignore (setq name (if (eq (char-after) ?\')
|
||||
(eshell-parse-literal-quote)
|
||||
(eshell-parse-double-quote)))))))
|
||||
(throw 'eshell-incomplete (concat "$" delim)))
|
||||
(when name
|
||||
`(eshell-get-variable ,(eval name) indices ,eshell-current-quoted)))))
|
||||
((assoc (char-to-string (char-after))
|
||||
|
@ -597,7 +606,7 @@ For example, \"[0 1][2]\" becomes:
|
|||
(while (eq (char-after) ?\[)
|
||||
(let ((end (eshell-find-delimiter ?\[ ?\])))
|
||||
(if (not end)
|
||||
(throw 'eshell-incomplete ?\[)
|
||||
(throw 'eshell-incomplete "[")
|
||||
(forward-char)
|
||||
(eshell-with-temp-command (or (eshell-unescape-inner-double-quote end)
|
||||
(cons (point) end))
|
||||
|
@ -816,33 +825,40 @@ START and END."
|
|||
(let ((arg (pcomplete-actual-arg)))
|
||||
(when (string-match
|
||||
(rx "$" (? (or "#" "@"))
|
||||
(? (group (regexp eshell-variable-name-regexp)))
|
||||
string-end)
|
||||
(? (or (group-n 1 (regexp eshell-variable-name-regexp)
|
||||
string-end)
|
||||
(seq (group-n 2 (or "'" "\""))
|
||||
(group-n 1 (+ anychar))))))
|
||||
arg)
|
||||
(setq pcomplete-stub (substring arg (match-beginning 1)))
|
||||
(let ((delimiter (match-string 2 arg)))
|
||||
;; When finished with completion, insert the trailing
|
||||
;; delimiter, if any, and add a trailing slash if the variable
|
||||
;; refers to a directory.
|
||||
(add-function
|
||||
:before-until (var pcomplete-exit-function)
|
||||
(lambda (variable status)
|
||||
(when (eq status 'finished)
|
||||
(when delimiter
|
||||
(if (looking-at (regexp-quote delimiter))
|
||||
(goto-char (match-end 0))
|
||||
(insert delimiter)))
|
||||
(let ((non-essential t)
|
||||
(value (eshell-get-variable variable)))
|
||||
(when (and (stringp value) (file-directory-p value))
|
||||
(insert "/")
|
||||
;; Tell Pcomplete not to insert its own termination
|
||||
;; string.
|
||||
t))))))
|
||||
(throw 'pcomplete-completions (eshell-variables-list)))))
|
||||
|
||||
(defun eshell-variables-list ()
|
||||
"Generate list of applicable variables."
|
||||
(let ((argname pcomplete-stub)
|
||||
completions)
|
||||
(dolist (alias eshell-variable-aliases-list)
|
||||
(if (string-match (concat "^" argname) (car alias))
|
||||
(setq completions (cons (car alias) completions))))
|
||||
(let ((argname pcomplete-stub))
|
||||
(sort
|
||||
(append
|
||||
(mapcar
|
||||
(lambda (varname)
|
||||
(let ((value (eshell-get-variable varname)))
|
||||
(if (and value
|
||||
(stringp value)
|
||||
(file-directory-p value))
|
||||
(concat varname "/")
|
||||
varname)))
|
||||
(eshell-envvar-names (eshell-environment-variables)))
|
||||
(all-completions argname obarray 'boundp)
|
||||
completions)
|
||||
'string-lessp)))
|
||||
(append (eshell-envvar-names)
|
||||
(all-completions argname obarray #'boundp))
|
||||
#'string-lessp)))
|
||||
|
||||
(defun eshell-complete-variable-assignment ()
|
||||
"If there is a variable assignment, allow completion of entries."
|
||||
|
|
|
@ -362,6 +362,32 @@ modified to be an empty string, or the desired separation string."
|
|||
|
||||
;;; User Functions:
|
||||
|
||||
(defun pcomplete-default-exit-function (_s status)
|
||||
"The default exit function to use in `pcomplete-completions-at-point'.
|
||||
This just adds `pcomplete-termination-string' after the
|
||||
completion if STATUS is `finished'."
|
||||
(unless (zerop (length pcomplete-termination-string))
|
||||
(when (eq status 'finished)
|
||||
(if (looking-at
|
||||
(regexp-quote pcomplete-termination-string))
|
||||
(goto-char (match-end 0))
|
||||
(insert pcomplete-termination-string)))))
|
||||
|
||||
(defvar pcomplete-exit-function #'pcomplete-default-exit-function
|
||||
"The exit function to call in `pcomplete-completions-at-point'.
|
||||
|
||||
This variable is let-bound in `pcomplete-completions-at-point',
|
||||
so you can modify or advise it in order to adjust the behavior
|
||||
for a specific completion. For example, you might do the
|
||||
following in a `pcomplete-try-first-hook' function to insert a
|
||||
trailing slash after a completion:
|
||||
|
||||
(add-function
|
||||
:before (var pcomplete-exit-function)
|
||||
(lambda (_ status)
|
||||
(when (eq status \\='finished)
|
||||
(insert \"/\"))))")
|
||||
|
||||
;;; Alternative front-end using the standard completion facilities.
|
||||
|
||||
;; The way pcomplete-parse-arguments and pcomplete-stub work only
|
||||
|
@ -406,6 +432,7 @@ Same as `pcomplete' but using the standard completion UI."
|
|||
(if pcomplete-allow-modifications buffer-read-only t))
|
||||
pcomplete-seen pcomplete-norm-func
|
||||
pcomplete-args pcomplete-last pcomplete-index
|
||||
(pcomplete-exit-function pcomplete-exit-function)
|
||||
(pcomplete-autolist pcomplete-autolist)
|
||||
(pcomplete-suffix-list pcomplete-suffix-list)
|
||||
;; Apparently the vars above are global vars modified by
|
||||
|
@ -494,16 +521,7 @@ Same as `pcomplete' but using the standard completion UI."
|
|||
(get-text-property 0 'pcomplete-help cand)))
|
||||
:predicate pred
|
||||
:exit-function
|
||||
;; If completion is finished, add a terminating space.
|
||||
;; We used to also do this if STATUS is `sole', but
|
||||
;; that does not work right when completion cycling.
|
||||
(unless (zerop (length pcomplete-termination-string))
|
||||
(lambda (_s status)
|
||||
(when (eq status 'finished)
|
||||
(if (looking-at
|
||||
(regexp-quote pcomplete-termination-string))
|
||||
(goto-char (match-end 0))
|
||||
(insert pcomplete-termination-string)))))))))))
|
||||
pcomplete-exit-function))))))
|
||||
|
||||
;; I don't think such commands are usable before first setting up buffer-local
|
||||
;; variables to parse args, so there's no point autoloading it.
|
||||
|
|
|
@ -183,6 +183,31 @@ See <lisp/eshell/esh-var.el>."
|
|||
(should (equal (eshell-insert-and-complete "echo $system-nam")
|
||||
"echo $system-name "))))
|
||||
|
||||
(ert-deftest em-cmpl-test/quoted-variable-ref-completion ()
|
||||
"Test completion of variable references like \"$'var'\".
|
||||
See <lisp/eshell/esh-var.el>."
|
||||
(with-temp-eshell
|
||||
(should (equal (eshell-insert-and-complete "echo $'system-nam")
|
||||
"echo $'system-name' ")))
|
||||
(with-temp-eshell
|
||||
(should (equal (eshell-insert-and-complete "echo $\"system-nam")
|
||||
"echo $\"system-name\" "))))
|
||||
|
||||
(ert-deftest em-cmpl-test/variable-ref-completion/directory ()
|
||||
"Test completion of variable references that expand to directories.
|
||||
See <lisp/eshell/esh-var.el>."
|
||||
(with-temp-eshell
|
||||
(should (equal (eshell-insert-and-complete "echo $PW")
|
||||
"echo $PWD/")))
|
||||
(with-temp-eshell
|
||||
(let ((minibuffer-message-timeout 0)
|
||||
(inhibit-message t))
|
||||
(should (equal (eshell-insert-and-complete "echo $PWD")
|
||||
"echo $PWD/"))))
|
||||
(with-temp-eshell
|
||||
(should (equal (eshell-insert-and-complete "echo $'PW")
|
||||
"echo $'PWD'/"))))
|
||||
|
||||
(ert-deftest em-cmpl-test/variable-assign-completion ()
|
||||
"Test completion of variable assignments like \"var=value\".
|
||||
See <lisp/eshell/esh-var.el>."
|
||||
|
@ -193,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)))
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue