summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Porter <jporterbugs@gmail.com>2024-10-21 14:21:50 -0700
committerJim Porter <jporterbugs@gmail.com>2024-10-21 14:21:50 -0700
commit605f26cf70ab3d7c5ea635c19cd2a280812a4ddc (patch)
tree5970d844fe2e18c0f715e34db9ef5b9e26d2dd1b
parent1f8fbae8df764e9d24f1b824de7369d82e36abae (diff)
Fix a race condition when running Eshell startup scripts
Previously, these scripts could run before all the Eshell modules had fully-initialized. * lisp/eshell/esh-mode.el (eshell-after-initialize-hook): New hook... (eshell-mode): ... run it. * lisp/eshell/em-script.el (eshell-run-startup-scripts): New function... (eshell-script-initialize): ... add it to 'eshell-after-initialize-hook'. * etc/NEWS: Announce 'eshell-after-initialize-hook'.
-rw-r--r--etc/NEWS6
-rw-r--r--lisp/eshell/em-script.el34
-rw-r--r--lisp/eshell/esh-mode.el6
3 files changed, 29 insertions, 17 deletions
diff --git a/etc/NEWS b/etc/NEWS
index cfc5a8e1785..3a8ee7ccacb 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -276,6 +276,12 @@ By passing '-t' or '--timeout', you can specify a maximum time to wait
for the processes to exit. Additionally, you can now wait for external
processes by passing their PIDs.
+---
+*** New hook 'eshell-after-initialize-hook'.
+This hook runs after an Eshell session has been fully initialized,
+immediately before running 'eshell-post-command-hook' for the first
+time.
+
** SHR
+++
diff --git a/lisp/eshell/em-script.el b/lisp/eshell/em-script.el
index 03d9a88e32e..f426afb5d28 100644
--- a/lisp/eshell/em-script.el
+++ b/lisp/eshell/em-script.el
@@ -68,22 +68,24 @@ This includes when running `eshell-command'."
'eshell/source)
eshell-interpreter-alist))
(setq-local eshell-complex-commands
- (append '("source" ".") eshell-complex-commands))
- ;; these two variables are changed through usage, but we don't want
- ;; to ruin it for other modules
- (let (eshell-inside-quote-regexp
- eshell-outside-quote-regexp)
- (and (not (bound-and-true-p eshell-non-interactive-p))
- eshell-login-script
- (file-readable-p eshell-login-script)
- (eshell-do-eval
- `(eshell-commands ,(eshell--source-file eshell-login-script))
- t))
- (and eshell-rc-script
- (file-readable-p eshell-rc-script)
- (eshell-do-eval
- `(eshell-commands ,(eshell--source-file eshell-rc-script))
- t))))
+ (append '("source" ".") eshell-complex-commands))
+ ;; Run our startup scripts once this Eshell session has finished
+ ;; initialization.
+ (add-hook 'eshell-after-initialize-hook #'eshell-run-startup-scripts 90 t))
+
+(defun eshell-run-startup-scripts ()
+ "Run any necessary startup scripts for the current Eshell session."
+ (when (and (not (bound-and-true-p eshell-non-interactive-p))
+ eshell-login-script
+ (file-readable-p eshell-login-script))
+ (eshell-do-eval
+ `(eshell-commands ,(eshell--source-file eshell-login-script))
+ t))
+ (when (and eshell-rc-script
+ (file-readable-p eshell-rc-script))
+ (eshell-do-eval
+ `(eshell-commands ,(eshell--source-file eshell-rc-script))
+ t)))
(defun eshell--source-file (file &optional args subcommand-p)
"Return a Lisp form for executing the Eshell commands in FILE, passing ARGS.
diff --git a/lisp/eshell/esh-mode.el b/lisp/eshell/esh-mode.el
index ead5a20bec8..37a88fce790 100644
--- a/lisp/eshell/esh-mode.el
+++ b/lisp/eshell/esh-mode.el
@@ -90,6 +90,10 @@
That is to say, the first time during an Emacs session."
:type 'hook)
+(defcustom eshell-after-initialize-hook nil
+ "A hook that gets run after an Eshell session has been fully initialized."
+ :type 'hook)
+
(defcustom eshell-exit-hook nil
"A hook that is run whenever `eshell' is exited.
This hook is only run if exiting actually kills the buffer."
@@ -406,7 +410,7 @@ and the hook `eshell-exit-hook'."
(when eshell-first-time-p
(setq eshell-first-time-p nil)
(run-hooks 'eshell-first-time-mode-hook))
-
+ (run-hooks 'eshell-after-initialize-hook)
(run-hooks 'eshell-post-command-hook))
(put 'eshell-mode 'mode-class 'special)