emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 82c76e3: * lisp/eshell/em-cmpl.el: Try and fix bug#41423


From: Stefan Monnier
Subject: master 82c76e3: * lisp/eshell/em-cmpl.el: Try and fix bug#41423
Date: Sun, 31 Jan 2021 19:27:16 -0500 (EST)

branch: master
commit 82c76e3aeb2465d1d1e66eae5db13ba53e38ed84
Author: Stefan Monnier <monnier@iro.umontreal.ca>
Commit: Stefan Monnier <monnier@iro.umontreal.ca>

    * lisp/eshell/em-cmpl.el: Try and fix bug#41423
    
    (eshell--complete-commands-list): Rename from 
`eshell-complete-commands-list`.
    Return a (dynamic) completion table rather than a list of completions.
    Use `dolist` and `push`.
---
 lisp/eshell/em-cmpl.el | 118 +++++++++++++++++++++++++------------------------
 1 file changed, 60 insertions(+), 58 deletions(-)

diff --git a/lisp/eshell/em-cmpl.el b/lisp/eshell/em-cmpl.el
index 0200631..e0b3ab1 100644
--- a/lisp/eshell/em-cmpl.el
+++ b/lisp/eshell/em-cmpl.el
@@ -211,7 +211,7 @@ to writing a completion function."
 
 (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)
@@ -403,64 +403,66 @@ 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.
+  (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 (glob-name)
+         (if (and (> (length filename) 0)
+                 (eq (aref filename 0) eshell-explicit-command-char))
+            ;; FIXME: Shouldn't we handle this `*' outside of the
+            ;; `pcomplete-here' in `eshell-command-completion-function'?
+            (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)))
+               (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")
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]