aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Porter2023-03-10 19:02:26 -0800
committerJim Porter2024-05-29 12:09:05 -0700
commit6c2f21e4a6ff65cc1697cb8a6ba0e1ef1a52ae1c (patch)
tree45e81f3bd365ef76fcf7f08ae00e5bfab9173af3
parent98149ad31ea2cfd5a82f95443affd665c9da667b (diff)
downloademacs-6c2f21e4a6ff65cc1697cb8a6ba0e1ef1a52ae1c.tar.gz
emacs-6c2f21e4a6ff65cc1697cb8a6ba0e1ef1a52ae1c.zip
Consolidate Eshell module loading/unloading code
This also adds the ability to suppress module loading/unloading messages, which will be necessary to support running Eshell scripts as batch scripts. * lisp/eshell/esh-mode.el (eshell-mode): Move module loading/initialization to... * lisp/eshell/esh-module.el (eshell-load-modules) (eshell-initialize-modules): ... here. (eshell-module-loading-messages): New option. (eshell-module--feature-name): Improve docstring. (eshell-unload-modules): Display a real warning if unable to unload a module. * test/lisp/eshell/eshell-tests-helpers.el (with-temp-eshell) (eshell-command-result-equal): * test/lisp/eshell/eshell-tests-unload.el (load-eshell): Silence Eshell loading messages.
-rw-r--r--lisp/eshell/esh-mode.el31
-rw-r--r--lisp/eshell/esh-module.el70
-rw-r--r--test/lisp/eshell/eshell-tests-helpers.el10
-rw-r--r--test/lisp/eshell/eshell-tests-unload.el2
4 files changed, 72 insertions, 41 deletions
diff --git a/lisp/eshell/esh-mode.el b/lisp/eshell/esh-mode.el
index c4ae55afe3f..7290c29b008 100644
--- a/lisp/eshell/esh-mode.el
+++ b/lisp/eshell/esh-mode.el
@@ -372,36 +372,15 @@ and the hook `eshell-exit-hook'."
372 ;; strong R2L character. 372 ;; strong R2L character.
373 (setq bidi-paragraph-direction 'left-to-right) 373 (setq bidi-paragraph-direction 'left-to-right)
374 374
375 ;; load extension modules into memory. This will cause any global 375 ;; Load extension modules into memory.
376 ;; variables they define to be visible, since some of the core 376 (eshell-load-modules eshell-modules-list)
377 ;; modules sometimes take advantage of their functionality if used.
378 (dolist (module eshell-modules-list)
379 (let ((module-fullname (symbol-name module))
380 module-shortname)
381 (if (string-match "^eshell-\\(.*\\)" module-fullname)
382 (setq module-shortname
383 (concat "em-" (match-string 1 module-fullname))))
384 (unless module-shortname
385 (error "Invalid Eshell module name: %s" module-fullname))
386 (unless (featurep (intern module-shortname))
387 (condition-case nil
388 (load module-shortname)
389 (error (lwarn 'eshell :error
390 "Unable to load module `%s' (defined in `eshell-modules-list')"
391 module-fullname))))))
392 377
393 (unless (file-exists-p eshell-directory-name) 378 (unless (file-exists-p eshell-directory-name)
394 (eshell-make-private-directory eshell-directory-name t)) 379 (eshell-make-private-directory eshell-directory-name t))
395 380
396 ;; Load core Eshell modules, then extension modules, for this session. 381 ;; Initialize core Eshell modules, then extension modules, for this session.
397 (dolist (module (append (eshell-subgroups 'eshell) eshell-modules-list)) 382 (eshell-initialize-modules (eshell-subgroups 'eshell))
398 (let ((load-hook (intern-soft (format "%s-load-hook" module))) 383 (eshell-initialize-modules eshell-modules-list)
399 (initfunc (intern-soft (format "%s-initialize" module))))
400 (when (and load-hook (boundp load-hook))
401 (if (memq initfunc (symbol-value load-hook)) (setq initfunc nil))
402 (run-hooks load-hook))
403 ;; So we don't need the -initialize functions on the hooks (bug#5375).
404 (and initfunc (fboundp initfunc) (funcall initfunc))))
405 384
406 (if eshell-send-direct-to-subprocesses 385 (if eshell-send-direct-to-subprocesses
407 (add-hook 'pre-command-hook #'eshell-intercept-commands t t)) 386 (add-hook 'pre-command-hook #'eshell-intercept-commands t t))
diff --git a/lisp/eshell/esh-module.el b/lisp/eshell/esh-module.el
index fbd5ae4b9b8..88221638e16 100644
--- a/lisp/eshell/esh-module.el
+++ b/lisp/eshell/esh-module.el
@@ -49,6 +49,12 @@ customizing the variable `eshell-modules-list'."
49 :group 'eshell-module) 49 :group 'eshell-module)
50(make-obsolete-variable 'eshell-module-unload-hook nil "30.1") 50(make-obsolete-variable 'eshell-module-unload-hook nil "30.1")
51 51
52(defcustom eshell-module-loading-messages t
53 "If non-nil, display messages when loading/unloading Eshell modules."
54 :type 'boolean
55 :group 'eshell-module
56 :version "30.1")
57
52(defcustom eshell-modules-list 58(defcustom eshell-modules-list
53 '(eshell-alias 59 '(eshell-alias
54 eshell-banner 60 eshell-banner
@@ -87,7 +93,9 @@ Changes will only take effect in future Eshell buffers."
87;;; Code: 93;;; Code:
88 94
89(defsubst eshell-module--feature-name (module &optional kind) 95(defsubst eshell-module--feature-name (module &optional kind)
90 "Get the feature name for the specified Eshell MODULE." 96 "Get the feature name for the specified Eshell MODULE.
97KIND can be either `core' for a core module or `extension' for an
98extension module; if nil, KIND defaults to `extension'."
91 (let ((module-name (symbol-name module)) 99 (let ((module-name (symbol-name module))
92 (prefix (cond ((eq kind 'core) "esh-") 100 (prefix (cond ((eq kind 'core) "esh-")
93 ((memq kind '(extension nil)) "em-") 101 ((memq kind '(extension nil)) "em-")
@@ -102,17 +110,57 @@ The MODULE should be a symbol corresponding to that module's
102customization group. Example: `eshell-cmpl' for that module." 110customization group. Example: `eshell-cmpl' for that module."
103 (memq module eshell-modules-list)) 111 (memq module eshell-modules-list))
104 112
105(defun eshell-unload-modules (modules &optional kind) 113(defun eshell-load-modules (modules)
106 "Try to unload the specified Eshell MODULES." 114 "Load Eshell MODULES into memory.
115This will cause any global variables they define to be visible so
116that other modules can take advantage of their functionality if
117desired."
118 (let ((verbose eshell-module-loading-messages))
119 (dolist (module modules)
120 (let ((module-feature-name (eshell-module--feature-name module)))
121 (unless (featurep (intern module-feature-name))
122 (when verbose (message "Loading %s..." module))
123 (condition-case-unless-debug nil
124 (progn
125 (load module-feature-name nil t)
126 (when verbose (message "Loading %s...done" module)))
127 (error (when verbose (message "Loading %s...failed" module))
128 (lwarn 'eshell :error
129 "Unable to load Eshell module `%s'"
130 module))))))))
131
132(defun eshell-initialize-modules (modules)
133 "Initialize Eshell MODULES.
134This calls `MODULE-load-hook' and `MODULE-initialize' for each
135MODULE, if they're defined."
107 (dolist (module modules) 136 (dolist (module modules)
108 (let ((module-feature (intern (eshell-module--feature-name module kind)))) 137 (let ((load-hook (intern-soft (format "%s-load-hook" module)))
109 (when (featurep module-feature) 138 (initfunc (intern-soft (format "%s-initialize" module))))
110 (message "Unloading %s..." (symbol-name module)) 139 (when (and load-hook (boundp load-hook))
111 (condition-case-unless-debug _ 140 (if (memq initfunc (symbol-value load-hook)) (setq initfunc nil))
112 (progn 141 (run-hooks load-hook))
113 (unload-feature module-feature) 142 ;; So we don't need the -initialize functions on the hooks (bug#5375).
114 (message "Unloading %s...done" (symbol-name module))) 143 (and initfunc (fboundp initfunc) (funcall initfunc)))))
115 (error (message "Unloading %s...failed" (symbol-name module)))))))) 144
145(defun eshell-unload-modules (modules &optional kind)
146 "Try to unload the specified Eshell MODULES.
147KIND can be either `core' for core modules or `extension' for
148extension modules; if nil, KIND defaults to `extension'."
149 ;; We're about to unload this module, but we need to remember whether
150 ;; to print messages.
151 (let ((verbose eshell-module-loading-messages))
152 (dolist (module modules)
153 (let ((module-feature (intern (eshell-module--feature-name module kind))))
154 (when (featurep module-feature)
155 (when verbose (message "Unloading %s..." module))
156 (condition-case-unless-debug nil
157 (progn
158 (unload-feature module-feature)
159 (when verbose (message "Unloading %s...done" module)))
160 (error (when verbose (message "Unloading %s...failed" module))
161 (lwarn 'eshell :error
162 "Unable to unload Eshell module `%s'"
163 module))))))))
116 164
117(defun eshell-unload-extension-modules () 165(defun eshell-unload-extension-modules ()
118 "Try to unload all currently-loaded Eshell extension modules." 166 "Try to unload all currently-loaded Eshell extension modules."
diff --git a/test/lisp/eshell/eshell-tests-helpers.el b/test/lisp/eshell/eshell-tests-helpers.el
index 652146fefcc..3f1c55f420d 100644
--- a/test/lisp/eshell/eshell-tests-helpers.el
+++ b/test/lisp/eshell/eshell-tests-helpers.el
@@ -63,6 +63,7 @@ beginning of the test file."
63 (eshell-debug-command (cons 'process eshell-debug-command)) 63 (eshell-debug-command (cons 'process eshell-debug-command))
64 (eshell-history-file-name nil) 64 (eshell-history-file-name nil)
65 (eshell-last-dir-ring-file-name nil) 65 (eshell-last-dir-ring-file-name nil)
66 (eshell-module-loading-messages nil)
66 (eshell-buffer (eshell t))) 67 (eshell-buffer (eshell t)))
67 (unwind-protect 68 (unwind-protect
68 (with-current-buffer eshell-buffer 69 (with-current-buffer eshell-buffer
@@ -183,10 +184,11 @@ inserting the command."
183(defun eshell-command-result-equal (command result) 184(defun eshell-command-result-equal (command result)
184 "Execute COMMAND non-interactively and compare it to RESULT." 185 "Execute COMMAND non-interactively and compare it to RESULT."
185 (ert-info (#'eshell-get-debug-logs :prefix "Command logs: ") 186 (ert-info (#'eshell-get-debug-logs :prefix "Command logs: ")
186 (should (eshell-command-result--equal 187 (let ((eshell-module-loading-messages nil))
187 command 188 (should (eshell-command-result--equal
188 (eshell-test-command-result command) 189 command
189 result)))) 190 (eshell-test-command-result command)
191 result)))))
190 192
191(provide 'eshell-tests-helpers) 193(provide 'eshell-tests-helpers)
192 194
diff --git a/test/lisp/eshell/eshell-tests-unload.el b/test/lisp/eshell/eshell-tests-unload.el
index bf8291ba47a..479090e8f8c 100644
--- a/test/lisp/eshell/eshell-tests-unload.el
+++ b/test/lisp/eshell/eshell-tests-unload.el
@@ -33,6 +33,7 @@
33(defvar eshell-history-file-name) 33(defvar eshell-history-file-name)
34(defvar eshell-last-dir-ring-file-name) 34(defvar eshell-last-dir-ring-file-name)
35(defvar eshell-modules-list) 35(defvar eshell-modules-list)
36(defvar eshell-module-loading-messages)
36 37
37(declare-function eshell-module--feature-name "esh-module" 38(declare-function eshell-module--feature-name "esh-module"
38 (module &optional kind)) 39 (module &optional kind))
@@ -51,6 +52,7 @@ See `unload-eshell'.")
51 (process-environment (cons "HISTFILE" process-environment)) 52 (process-environment (cons "HISTFILE" process-environment))
52 (eshell-history-file-name nil) 53 (eshell-history-file-name nil)
53 (eshell-last-dir-ring-file-name nil) 54 (eshell-last-dir-ring-file-name nil)
55 (eshell-module-loading-messages nil)
54 (eshell-buffer (eshell t))) 56 (eshell-buffer (eshell t)))
55 (let (kill-buffer-query-functions) 57 (let (kill-buffer-query-functions)
56 (kill-buffer eshell-buffer)))))) 58 (kill-buffer eshell-buffer))))))