diff options
| author | Jim Porter | 2023-03-10 19:02:26 -0800 |
|---|---|---|
| committer | Jim Porter | 2024-05-29 12:09:05 -0700 |
| commit | 6c2f21e4a6ff65cc1697cb8a6ba0e1ef1a52ae1c (patch) | |
| tree | 45e81f3bd365ef76fcf7f08ae00e5bfab9173af3 | |
| parent | 98149ad31ea2cfd5a82f95443affd665c9da667b (diff) | |
| download | emacs-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.el | 31 | ||||
| -rw-r--r-- | lisp/eshell/esh-module.el | 70 | ||||
| -rw-r--r-- | test/lisp/eshell/eshell-tests-helpers.el | 10 | ||||
| -rw-r--r-- | test/lisp/eshell/eshell-tests-unload.el | 2 |
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. |
| 97 | KIND can be either `core' for a core module or `extension' for an | ||
| 98 | extension 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 | |||
| 102 | customization group. Example: `eshell-cmpl' for that module." | 110 | customization 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. |
| 115 | This will cause any global variables they define to be visible so | ||
| 116 | that other modules can take advantage of their functionality if | ||
| 117 | desired." | ||
| 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. | ||
| 134 | This calls `MODULE-load-hook' and `MODULE-initialize' for each | ||
| 135 | MODULE, 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. | ||
| 147 | KIND can be either `core' for core modules or `extension' for | ||
| 148 | extension 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)))))) |