diff options
Diffstat (limited to 'lisp/eshell/em-cmpl.el')
-rw-r--r-- | lisp/eshell/em-cmpl.el | 189 |
1 files changed, 85 insertions, 104 deletions
diff --git a/lisp/eshell/em-cmpl.el b/lisp/eshell/em-cmpl.el index 0200631da66..cbfe0b81545 100644 --- a/lisp/eshell/em-cmpl.el +++ b/lisp/eshell/em-cmpl.el @@ -91,27 +91,23 @@ variable names, arguments, etc." (defcustom eshell-cmpl-load-hook nil "A list of functions to run when `eshell-cmpl' is loaded." :version "24.1" ; removed eshell-cmpl-initialize - :type 'hook - :group 'eshell-cmpl) + :type 'hook) (defcustom eshell-show-lisp-completions nil "If non-nil, include Lisp functions in the command completion list. If this variable is nil, Lisp completion can still be done in command position by using M-TAB instead of TAB." - :type 'boolean - :group 'eshell-cmpl) + :type 'boolean) (defcustom eshell-show-lisp-alternatives t "If non-nil, and no other completions found, show Lisp functions. Setting this variable means nothing if `eshell-show-lisp-completions' is non-nil." - :type 'boolean - :group 'eshell-cmpl) + :type 'boolean) (defcustom eshell-no-completion-during-jobs t "If non-nil, don't allow completion while a process is running." - :type 'boolean - :group 'eshell-cmpl) + :type 'boolean) (defcustom eshell-command-completions-alist '(("acroread" . "\\.pdf\\'") @@ -136,8 +132,7 @@ is non-nil." "An alist that defines simple argument type correlations. This is provided for common commands, as a simplistic alternative to writing a completion function." - :type '(repeat (cons string regexp)) - :group 'eshell-cmpl) + :type '(repeat (cons string regexp))) (defun eshell-cmpl--custom-variable-docstring (pcomplete-var) "Generate the docstring of a variable derived from a pcomplete-* variable." @@ -148,23 +143,19 @@ to writing a completion function." (defcustom eshell-cmpl-file-ignore "~\\'" (eshell-cmpl--custom-variable-docstring 'pcomplete-file-ignore) - :type (get 'pcomplete-file-ignore 'custom-type) - :group 'eshell-cmpl) + :type (get 'pcomplete-file-ignore 'custom-type)) (defcustom eshell-cmpl-dir-ignore "\\`\\(\\.\\.?\\|CVS\\)/\\'" (eshell-cmpl--custom-variable-docstring 'pcomplete-dir-ignore) - :type (get 'pcomplete-dir-ignore 'custom-type) - :group 'eshell-cmpl) + :type (get 'pcomplete-dir-ignore 'custom-type)) (defcustom eshell-cmpl-ignore-case (eshell-under-windows-p) - (eshell-cmpl--custom-variable-docstring 'pcomplete-ignore-case) - :type (get 'pcomplete-ignore-case 'custom-type) - :group 'eshell-cmpl) + (eshell-cmpl--custom-variable-docstring 'completion-ignore-case) + :type (get 'completion-ignore-case 'custom-type)) (defcustom eshell-cmpl-autolist nil (eshell-cmpl--custom-variable-docstring 'pcomplete-autolist) - :type (get 'pcomplete-autolist 'custom-type) - :group 'eshell-cmpl) + :type (get 'pcomplete-autolist 'custom-type)) (defcustom eshell-cmpl-suffix-list (list ?/ ?:) (eshell-cmpl--custom-variable-docstring 'pcomplete-suffix-list) @@ -176,51 +167,42 @@ to writing a completion function." (defcustom eshell-cmpl-recexact nil (eshell-cmpl--custom-variable-docstring 'pcomplete-recexact) - :type (get 'pcomplete-recexact 'custom-type) - :group 'eshell-cmpl) + :type (get 'pcomplete-recexact 'custom-type)) -(defcustom eshell-cmpl-man-function 'man +(defcustom eshell-cmpl-man-function #'man (eshell-cmpl--custom-variable-docstring 'pcomplete-man-function) - :type (get 'pcomplete-man-function 'custom-type) - :group 'eshell-cmpl) + :type (get 'pcomplete-man-function 'custom-type)) -(defcustom eshell-cmpl-compare-entry-function 'file-newer-than-file-p +(defcustom eshell-cmpl-compare-entry-function #'file-newer-than-file-p (eshell-cmpl--custom-variable-docstring 'pcomplete-compare-entry-function) - :type (get 'pcomplete-compare-entry-function 'custom-type) - :group 'eshell-cmpl) + :type (get 'pcomplete-compare-entry-function 'custom-type)) (defcustom eshell-cmpl-expand-before-complete nil (eshell-cmpl--custom-variable-docstring 'pcomplete-expand-before-complete) - :type (get 'pcomplete-expand-before-complete 'custom-type) - :group 'eshell-cmpl) + :type (get 'pcomplete-expand-before-complete 'custom-type)) (defcustom eshell-cmpl-cycle-completions t (eshell-cmpl--custom-variable-docstring 'pcomplete-cycle-completions) - :type (get 'pcomplete-cycle-completions 'custom-type) - :group 'eshell-cmpl) + :type (get 'pcomplete-cycle-completions 'custom-type)) (defcustom eshell-cmpl-cycle-cutoff-length 5 (eshell-cmpl--custom-variable-docstring 'pcomplete-cycle-cutoff-length) - :type (get 'pcomplete-cycle-cutoff-length 'custom-type) - :group 'eshell-cmpl) + :type (get 'pcomplete-cycle-cutoff-length 'custom-type)) (defcustom eshell-cmpl-restore-window-delay 1 (eshell-cmpl--custom-variable-docstring 'pcomplete-restore-window-delay) - :type (get 'pcomplete-restore-window-delay 'custom-type) - :group 'eshell-cmpl) + :type (get 'pcomplete-restore-window-delay 'custom-type)) (defcustom eshell-command-completion-function (lambda () - (pcomplete-here (eshell-complete-commands-list))) + (pcomplete-here (eshell--complete-commands-list))) (eshell-cmpl--custom-variable-docstring 'pcomplete-command-completion-function) - :type (get 'pcomplete-command-completion-function 'custom-type) - :group 'eshell-cmpl) + :type (get 'pcomplete-command-completion-function 'custom-type)) (defcustom eshell-cmpl-command-name-function - 'eshell-completion-command-name + #'eshell-completion-command-name (eshell-cmpl--custom-variable-docstring 'pcomplete-command-name-function) - :type (get 'pcomplete-command-name-function 'custom-type) - :group 'eshell-cmpl) + :type (get 'pcomplete-command-name-function 'custom-type)) (defcustom eshell-default-completion-function (lambda () @@ -229,13 +211,11 @@ to writing a completion function." (cdr (assoc (funcall eshell-cmpl-command-name-function) eshell-command-completions-alist)))))) (eshell-cmpl--custom-variable-docstring 'pcomplete-default-completion-function) - :type (get 'pcomplete-default-completion-function 'custom-type) - :group 'eshell-cmpl) + :type (get 'pcomplete-default-completion-function 'custom-type)) (defcustom eshell-cmpl-use-paring t (eshell-cmpl--custom-variable-docstring 'pcomplete-use-paring) - :type (get 'pcomplete-use-paring 'custom-type) - :group 'eshell-cmpl) + :type (get 'pcomplete-use-paring 'custom-type)) ;;; Functions: @@ -274,12 +254,12 @@ to writing a completion function." (setq-local pcomplete-default-completion-function eshell-default-completion-function) (setq-local pcomplete-parse-arguments-function - 'eshell-complete-parse-arguments) + #'eshell-complete-parse-arguments) (setq-local pcomplete-file-ignore eshell-cmpl-file-ignore) (setq-local pcomplete-dir-ignore eshell-cmpl-dir-ignore) - (setq-local pcomplete-ignore-case + (setq-local completion-ignore-case eshell-cmpl-ignore-case) (setq-local pcomplete-autolist eshell-cmpl-autolist) @@ -403,64 +383,65 @@ to writing a completion function." args) posns))) -(defun eshell-complete-commands-list () +(defun eshell--complete-commands-list () "Generate list of applicable, visible commands." - (let ((filename (pcomplete-arg)) glob-name) - (if (file-name-directory filename) - (if eshell-force-execution - (pcomplete-dirs-or-entries nil #'file-readable-p) - (pcomplete-executables)) - (if (and (> (length filename) 0) - (eq (aref filename 0) eshell-explicit-command-char)) - (setq filename (substring filename 1) - pcomplete-stub filename - glob-name t)) - (let* ((paths (eshell-get-path)) - (cwd (file-name-as-directory - (expand-file-name default-directory))) - (path "") (comps-in-path ()) - (file "") (filepath "") (completions ())) - ;; Go thru each path in the search path, finding completions. - (while paths - (setq path (file-name-as-directory - (expand-file-name (or (car paths) "."))) - comps-in-path - (and (file-accessible-directory-p path) - (file-name-all-completions filename path))) - ;; Go thru each completion found, to see whether it should - ;; be used. - (while comps-in-path - (setq file (car comps-in-path) - filepath (concat path file)) - (if (and (not (member file completions)) ; - (or (string-equal path cwd) - (not (file-directory-p filepath))) - (if eshell-force-execution - (file-readable-p filepath) - (file-executable-p filepath))) - (setq completions (cons file completions))) - (setq comps-in-path (cdr comps-in-path))) - (setq paths (cdr paths))) - ;; Add aliases which are currently visible, and Lisp functions. - (pcomplete-uniquify-list - (if glob-name - completions - (setq completions - (append (if (fboundp 'eshell-alias-completions) - (eshell-alias-completions filename)) - (eshell-winnow-list - (mapcar - (lambda (name) - (substring name 7)) - (all-completions (concat "eshell/" filename) - obarray #'functionp)) - nil '(eshell-find-alias-function)) - completions)) - (append (and (or eshell-show-lisp-completions - (and eshell-show-lisp-alternatives - (null completions))) - (all-completions filename obarray #'functionp)) - completions))))))) + ;; Building the commands list can take quite a while, especially over Tramp + ;; (bug#41423), so do it lazily. + (let ((glob-name + ;; When a command is specified using `eshell-explicit-command-char', + ;; that char is not part of the command and hence not part of what + ;; we complete. Adjust `pcomplete-stub' accordingly! + (if (and (> (length pcomplete-stub) 0) + (eq (aref pcomplete-stub 0) eshell-explicit-command-char)) + (setq pcomplete-stub (substring pcomplete-stub 1))))) + (completion-table-dynamic + (lambda (filename) + (if (file-name-directory filename) + (if eshell-force-execution + (pcomplete-dirs-or-entries nil #'file-readable-p) + (pcomplete-executables)) + (let* ((paths (eshell-get-path)) + (cwd (file-name-as-directory + (expand-file-name default-directory))) + (filepath "") (completions ())) + ;; Go thru each path in the search path, finding completions. + (dolist (path paths) + (setq path (file-name-as-directory + (expand-file-name (or path ".")))) + ;; Go thru each completion found, to see whether it should + ;; be used. + (dolist (file (and (file-accessible-directory-p path) + (file-name-all-completions filename path))) + (setq filepath (concat path file)) + (if (and (not (member file completions)) ; + (or (string-equal path cwd) + (not (file-directory-p filepath))) + ;; FIXME: Those repeated file tests end up + ;; very costly over Tramp, we should cache the result. + (if eshell-force-execution + (file-readable-p filepath) + (file-executable-p filepath))) + (push file completions)))) + ;; Add aliases which are currently visible, and Lisp functions. + (pcomplete-uniquify-list + (if glob-name + completions + (setq completions + (append (if (fboundp 'eshell-alias-completions) + (eshell-alias-completions filename)) + (eshell-winnow-list + (mapcar + (lambda (name) + (substring name 7)) + (all-completions (concat "eshell/" filename) + obarray #'functionp)) + nil '(eshell-find-alias-function)) + completions)) + (append (and (or eshell-show-lisp-completions + (and eshell-show-lisp-alternatives + (null completions))) + (all-completions filename obarray #'functionp)) + completions))))))))) (define-obsolete-function-alias 'eshell-pcomplete #'completion-at-point "27.1") |