emacs-elpa-diffs
[Top][All Lists]
Advanced

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

[nongnu] elpa/exec-path-from-shell ad68d36747 102/114: Instead of checki


From: ELPA Syncer
Subject: [nongnu] elpa/exec-path-from-shell ad68d36747 102/114: Instead of checking startup files, just warn if execution is slow
Date: Tue, 5 Sep 2023 04:00:07 -0400 (EDT)

branch: elpa/exec-path-from-shell
commit ad68d367475e698cee043df3af160d85d5fa29e4
Author: Steve Purcell <steve@sanityinc.com>
Commit: Steve Purcell <steve@sanityinc.com>

    Instead of checking startup files, just warn if execution is slow
    
    See #100
---
 README.md               | 40 +++++++++++++++++++++++++++++-----------
 exec-path-from-shell.el | 41 ++++++++++++++++++-----------------------
 2 files changed, 47 insertions(+), 34 deletions(-)

diff --git a/README.md b/README.md
index 9f7acccafc..a50fc66cc2 100644
--- a/README.md
+++ b/README.md
@@ -97,15 +97,21 @@ but instead do this:
 export PATH=/usr/local/bin:/usr/bin:/bin
 ```
 
-You should also set your environment variables so that they are
-available to both interactive and non-interactive shells. In practical
-terms, for most people this means setting them in `~/.profile`,
-`~/.bash_profile`, `~/.zshenv` instead of `~/.bashrc` and
-`~/.zshrc`. By default, `exec-path-from-shell` checks for this
-mistake, at the cost of some execution time. If your config files are
-set up properly, you can set `exec-path-from-shell-arguments`
-appropriately (often to `nil`) before calling
-`exec-path-from-shell-initialize` to avoid this overhead.
+To be safe, `exec-path-from-shell` starts an interactive (and login)
+shell by default, but this can be much slower than necessary.
+Interactive shells often have fancy features enabled that are only
+helpful when one interacts directly with the shell, and this can
+frequently cause startup time to exceed 750ms.  This can be avoided:
+
+* Follow best practice by setting your environment variables so that
+  they are available to both interactive and non-interactive shells.
+  In practical terms, for most people this means setting them in
+  `~/.profile`, `~/.bash_profile`, `~/.zshenv` instead of `~/.bashrc`
+  and `~/.zshrc`.
+* Once a non-interactive shell sets your environment variables
+  correctly, adjust `exec-path-from-shell-arguments` appropriately
+  (often to `nil`) before calling `exec-path-from-shell-initialize` so
+  that it will start a non-interactive shell.
 
 To learn more about how popular shells load start-up files, read
 [this helpful 
article](https://blog.flowblok.id.au/2013-02/shell-startup-scripts.html).
@@ -113,8 +119,20 @@ To learn more about how popular shells load start-up 
files, read
 Making `exec-path-from-shell` faster
 ------------------------------------
 
-* Invoking the shell has a non-trivial overhead. Don't call 
`exec-path-from-shell-copy-env` repeatedly, since each invocation starts a 
shell. Instead, set `exec-path-from-shell-variables` to the full list of vars 
you want, and call `exec-path-from-shell-initialize` once.
-* Non-interactive shells start up faster. Follow the steps in the section 
above so that you can run your shell without `-i` and still get the right 
environment variable settings. When `"-i"` is then removed from 
`exec-path-from-shell-arguments`, this package becomes more efficient.
+If evaluation takes more than
+`exec-path-from-shell-warn-duration-millis` (500ms by default) then
+`exec-path-from-shell` will print a warning.
+
+* Non-interactive shells start up faster. Follow the steps in the
+  section above so that you can run your shell without `-i` and still
+  get the right environment variable settings. When `"-i"` is then
+  removed from `exec-path-from-shell-arguments`, this package becomes
+  more efficient.
+* Invoking the shell has a non-trivial overhead in any case. Don't
+  call `exec-path-from-shell-copy-env` repeatedly, since each
+  invocation starts a shell. Instead, set
+  `exec-path-from-shell-variables` to the full list of vars you want,
+  and call `exec-path-from-shell-initialize` once.
 
 Further help
 ------------
diff --git a/exec-path-from-shell.el b/exec-path-from-shell.el
index 6caa746ae6..87a9e88f69 100644
--- a/exec-path-from-shell.el
+++ b/exec-path-from-shell.el
@@ -87,12 +87,9 @@
   :type '(repeat (string :tag "Environment variable"))
   :group 'exec-path-from-shell)
 
-(defcustom exec-path-from-shell-check-startup-files t
-  "If non-nil, warn if variables are being set in the wrong shell startup 
files.
-Environment variables should be set in .profile or .zshenv rather than
-.bashrc or .zshrc."
-  :type 'boolean
-  :group 'exec-path-from-shell)
+(defcustom exec-path-from-shell-warn-duration-millis 500
+  "Print a warning message if shell execution takes longer than this many 
milliseconds."
+  :type 'integer)
 
 (defcustom exec-path-from-shell-shell-name nil
   "If non-nil, use this shell executable.
@@ -141,6 +138,19 @@ The default value denotes an interactive login shell."
   "Return non-nil iff SHELL supports the standard ${VAR-default} syntax."
   (not (string-match "\\(fish\\|t?csh\\)$" shell)))
 
+(defmacro exec-path-from-shell--warn-duration (&rest body)
+  "Evaluate BODY and warn if execution duration exceeds a time limit.
+The limit is given by `exec-path-from-shell-warn-duration-millis'."
+  (let ((start-time (gensym))
+        (duration-millis (gensym)))
+    `(let ((,start-time (current-time)))
+       (prog1
+           (progn ,@body)
+         (let ((,duration-millis (* 1000.0 (float-time (time-subtract 
(current-time) ,start-time)))))
+           (if (> ,duration-millis exec-path-from-shell-warn-duration-millis)
+               (message "Warning: exec-path-from-shell execution took %dms. 
See the README for tips on reducing this." ,duration-millis)
+             (exec-path-from-shell--debug "Shell execution took %dms" 
,duration-millis)))))))
+
 (defun exec-path-from-shell-printf (str &optional args)
   "Return the result of printing STR in the user's shell.
 
@@ -166,7 +176,8 @@ shell-escaped, so they may contain $ etc."
                                      (concat "sh -c " (shell-quote-argument 
printf-command)))))))
     (with-temp-buffer
       (exec-path-from-shell--debug "Invoking shell %s with args %S" shell 
shell-args)
-      (let ((exit-code (apply #'call-process shell nil t nil shell-args)))
+      (let ((exit-code (exec-path-from-shell--warn-duration
+                        (apply #'call-process shell nil t nil shell-args))))
         (exec-path-from-shell--debug "Shell printed: %S" (buffer-string))
         (unless (zerop exit-code)
           (error "Non-zero exit code from shell %s invoked with args %S.  
Output was:\n%S"
@@ -225,26 +236,10 @@ As a special case, if the variable is $PATH, then the 
variables
 The result is an alist, as described by
 `exec-path-from-shell-getenvs'."
   (let ((pairs (exec-path-from-shell-getenvs names)))
-    (when exec-path-from-shell-check-startup-files
-      (exec-path-from-shell--maybe-warn-about-startup-files pairs))
     (mapc (lambda (pair)
             (exec-path-from-shell-setenv (car pair) (cdr pair)))
           pairs)))
 
-(defun exec-path-from-shell--maybe-warn-about-startup-files (pairs)
-  "Warn the user if the value of PAIRS seems to depend on interactive shell 
startup files."
-  (let ((without-minus-i (remove "-i" exec-path-from-shell-arguments)))
-    ;; If the user is using "-i", we warn them if it is necessary.
-    (unless (eq exec-path-from-shell-arguments without-minus-i)
-      (let* ((exec-path-from-shell-arguments without-minus-i)
-             (alt-pairs (exec-path-from-shell-getenvs (mapcar 'car pairs)))
-             different)
-        (dolist (pair pairs)
-          (unless (equal pair (assoc (car pair) alt-pairs))
-            (push (car pair) different)))
-        (when different
-          (message "You appear to be setting environment variables %S in your 
.bashrc or .zshrc: those files are only read by interactive shells, so you 
should instead set environment variables in startup files like .profile, 
.bash_profile or .zshenv.  Refer to your shell's man page for more info.  
Customize `exec-path-from-shell-arguments' to remove \"-i\" when done, or 
disable `exec-path-from-shell-check-startup-files' to disable this message." 
different))))))
-
 ;;;###autoload
 (defun exec-path-from-shell-copy-env (name)
   "Set the environment variable $NAME from the user's shell.



reply via email to

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