aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Porter2023-08-29 17:02:40 -0700
committerJim Porter2023-08-31 18:42:03 -0700
commitccb62321d234993a66287c4e1a3cfdea63d140ff (patch)
tree7ffd2b146ef96a19522ae701586fa82b73ddc680
parent17188e07ab9084f8d25dedcb784957a461348fa9 (diff)
downloademacs-ccb62321d234993a66287c4e1a3cfdea63d140ff.tar.gz
emacs-ccb62321d234993a66287c4e1a3cfdea63d140ff.zip
Fix handling of Eshell debug modes
Previously, these were enabled/disabled at byte-compilation time, but we want to control them at runtime. * lisp/eshell/esh-cmd.el (eshell-eval-command): Call 'eshell-debug-command-start'. (eshell-manipulate): Check 'eshell-debug-command' at runtime. Update callers. (eshell-debug-command): Move to "esh-util.el". (eshell/eshell-debug, pcomplate/eshell-mode/eshell-debug): Move to "em-basic.el". (eshell-debug-show-parsed-args): Update implementation. * lisp/eshell/esh-util.el (eshell-debug-command): Move from "esh-cmd.el" and convert to a list. (eshell-debug-command-buffer): New variable. (eshell-condition-case): Check 'eshell-handle-errors' at runtime. (eshell-debug-command-start): New function. (eshell-debug-command): Move from "esh-cmd.el" and convert to a macro. * lisp/eshell/em-basic.el (eshell/eshell-debug) (pcomplete/eshell-mode/eshell-debug): Move from "esh-cmd.el" and reimplement. * lisp/eshell/eshell.el (eshell-command): Pass the original input to 'eshell-eval-command'. * doc/misc/eshell.texi (Built-ins): Update documentation for 'eshell-debug'.
-rw-r--r--doc/misc/eshell.texi17
-rw-r--r--lisp/eshell/em-basic.el31
-rw-r--r--lisp/eshell/esh-cmd.el105
-rw-r--r--lisp/eshell/esh-util.el44
-rw-r--r--lisp/eshell/eshell.el3
5 files changed, 108 insertions, 92 deletions
diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi
index f8f60bae13a..ee6c0f10b34 100644
--- a/doc/misc/eshell.texi
+++ b/doc/misc/eshell.texi
@@ -619,10 +619,19 @@ environment.
619@item eshell-debug 619@item eshell-debug
620@cmindex eshell-debug 620@cmindex eshell-debug
621Toggle debugging information for Eshell itself. You can pass this 621Toggle debugging information for Eshell itself. You can pass this
622command the argument @code{errors} to enable/disable Eshell trapping 622command one or more of the following arguments:
623errors when evaluating commands, or the argument @code{commands} to 623
624show/hide command execution progress in the buffer @code{*eshell last 624@itemize @bullet
625cmd*}. 625
626@item
627@code{error}, to enable/disable Eshell trapping errors when
628evaluating commands; or
629
630@item
631@code{form}, to show/hide Eshell command form manipulation in the
632buffer @code{*eshell last cmd*}.
633
634@end itemize
626 635
627@item exit 636@item exit
628@cmindex exit 637@cmindex exit
diff --git a/lisp/eshell/em-basic.el b/lisp/eshell/em-basic.el
index 016afe811b2..554ee83b015 100644
--- a/lisp/eshell/em-basic.el
+++ b/lisp/eshell/em-basic.el
@@ -188,6 +188,37 @@ or `eshell-printn' for display."
188 188
189(put 'eshell/umask 'eshell-no-numeric-conversions t) 189(put 'eshell/umask 'eshell-no-numeric-conversions t)
190 190
191(defun eshell/eshell-debug (&rest args)
192 "A command for toggling certain debug variables."
193 (eshell-eval-using-options
194 "eshell-debug" args
195 '((?h "help" nil nil "display this usage message")
196 :usage "[KIND]...
197This command is used to aid in debugging problems related to Eshell
198itself. It is not useful for anything else. The recognized `kinds'
199are:
200
201 error stops Eshell from trapping errors
202 form shows command form manipulation in `*eshell last cmd*'")
203 (if args
204 (dolist (kind args)
205 (if (equal kind "error")
206 (setq eshell-handle-errors (not eshell-handle-errors))
207 (let ((kind-sym (intern kind)))
208 (if (memq kind-sym eshell-debug-command)
209 (setq eshell-debug-command
210 (delq kind-sym eshell-debug-command))
211 (push kind-sym eshell-debug-command)))))
212 ;; Output the currently-enabled debug kinds.
213 (unless eshell-handle-errors
214 (eshell-print "errors\n"))
215 (dolist (kind eshell-debug-command)
216 (eshell-printn (symbol-name kind))))))
217
218(defun pcomplete/eshell-mode/eshell-debug ()
219 "Completion for the `debug' command."
220 (while (pcomplete-here '("error" "form"))))
221
191(provide 'em-basic) 222(provide 'em-basic)
192 223
193;; Local Variables: 224;; Local Variables:
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index 80066263396..ed2d6c71fc8 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -237,17 +237,6 @@ return non-nil if the command is complex."
237 :version "24.1" ; removed eshell-cmd-initialize 237 :version "24.1" ; removed eshell-cmd-initialize
238 :type 'hook) 238 :type 'hook)
239 239
240(defcustom eshell-debug-command nil
241 "If non-nil, enable Eshell debugging code.
242This is slow, and only useful for debugging problems with Eshell.
243If you change this without using customize after Eshell has loaded,
244you must re-load `esh-cmd.el'."
245 :initialize 'custom-initialize-default
246 :set (lambda (symbol value)
247 (set symbol value)
248 (load "esh-cmd"))
249 :type 'boolean)
250
251(defcustom eshell-deferrable-commands 240(defcustom eshell-deferrable-commands
252 '(eshell-named-command 241 '(eshell-named-command
253 eshell-lisp-command 242 eshell-lisp-command
@@ -436,22 +425,9 @@ hooks should be run before and after the command."
436 (run-hooks 'eshell-post-command-hook))) 425 (run-hooks 'eshell-post-command-hook)))
437 (macroexp-progn commands)))) 426 (macroexp-progn commands))))
438 427
439(defun eshell-debug-command (tag subform)
440 "Output a debugging message to `*eshell last cmd*'."
441 (let ((buf (get-buffer-create "*eshell last cmd*"))
442 (text (eshell-stringify eshell-current-command)))
443 (with-current-buffer buf
444 (if (not tag)
445 (erase-buffer)
446 (insert "\n\C-l\n" tag "\n\n" text
447 (if subform
448 (concat "\n\n" (eshell-stringify subform)) ""))))))
449
450(defun eshell-debug-show-parsed-args (terms) 428(defun eshell-debug-show-parsed-args (terms)
451 "Display parsed arguments in the debug buffer." 429 "Display parsed arguments in the debug buffer."
452 (ignore 430 (ignore (eshell-debug-command 'form "parsed arguments" terms)))
453 (if eshell-debug-command
454 (eshell-debug-command "parsed arguments" terms))))
455 431
456(defun eshell-no-command-conversion (terms) 432(defun eshell-no-command-conversion (terms)
457 "Don't convert the command argument." 433 "Don't convert the command argument."
@@ -942,38 +918,6 @@ This avoids the need to use `let*'."
942;; finishes, it will resume the evaluation using the remainder of the 918;; finishes, it will resume the evaluation using the remainder of the
943;; command tree. 919;; command tree.
944 920
945(defun eshell/eshell-debug (&rest args)
946 "A command for toggling certain debug variables."
947 (ignore
948 (cond
949 ((not args)
950 (if eshell-handle-errors
951 (eshell-print "errors\n"))
952 (if eshell-debug-command
953 (eshell-print "commands\n")))
954 ((member (car args) '("-h" "--help"))
955 (eshell-print "usage: eshell-debug [kinds]
956
957This command is used to aid in debugging problems related to Eshell
958itself. It is not useful for anything else. The recognized `kinds'
959at the moment are:
960
961 errors stops Eshell from trapping errors
962 commands shows command execution progress in `*eshell last cmd*'
963"))
964 (t
965 (while args
966 (cond
967 ((string= (car args) "errors")
968 (setq eshell-handle-errors (not eshell-handle-errors)))
969 ((string= (car args) "commands")
970 (setq eshell-debug-command (not eshell-debug-command))))
971 (setq args (cdr args)))))))
972
973(defun pcomplete/eshell-mode/eshell-debug ()
974 "Completion for the `debug' command."
975 (while (pcomplete-here '("errors" "commands"))))
976
977(iter-defun eshell--find-subcommands (haystack) 921(iter-defun eshell--find-subcommands (haystack)
978 "Recursively search for subcommand forms in HAYSTACK. 922 "Recursively search for subcommand forms in HAYSTACK.
979This yields the SUBCOMMANDs when found in forms like 923This yields the SUBCOMMANDs when found in forms like
@@ -1049,10 +993,7 @@ process(es) in a cons cell like:
1049 (if here 993 (if here
1050 (eshell-update-markers here)) 994 (eshell-update-markers here))
1051 (eshell-do-eval ',command)))) 995 (eshell-do-eval ',command))))
1052 (and eshell-debug-command 996 (eshell-debug-command-start input)
1053 (with-current-buffer (get-buffer-create "*eshell last cmd*")
1054 (erase-buffer)
1055 (insert "command: \"" input "\"\n")))
1056 (setq eshell-current-command command) 997 (setq eshell-current-command command)
1057 (let* (result 998 (let* (result
1058 (delim (catch 'eshell-incomplete 999 (delim (catch 'eshell-incomplete
@@ -1088,17 +1029,17 @@ process(es) in a cons cell like:
1088 (error 1029 (error
1089 (error (error-message-string err))))) 1030 (error (error-message-string err)))))
1090 1031
1091(defmacro eshell-manipulate (tag &rest commands) 1032(defmacro eshell-manipulate (form tag &rest body)
1092 "Manipulate a COMMAND form, with TAG as a debug identifier." 1033 "Manipulate a command FORM with BODY, using TAG as a debug identifier."
1093 (declare (indent 1)) 1034 (declare (indent 2))
1094 ;; Check `bound'ness since at compile time the code until here has not 1035 (let ((tag-symbol (make-symbol "tag")))
1095 ;; executed yet. 1036 `(if (not (memq 'form eshell-debug-command))
1096 (if (not (and (boundp 'eshell-debug-command) eshell-debug-command)) 1037 (progn ,@body)
1097 `(progn ,@commands) 1038 (let ((,tag-symbol ,tag))
1098 `(progn 1039 (eshell-debug-command 'form ,tag-symbol ,form 'always)
1099 (eshell-debug-command ,(eval tag) form) 1040 ,@body
1100 ,@commands 1041 (eshell-debug-command 'form (concat "done " ,tag-symbol) ,form
1101 (eshell-debug-command ,(concat "done " (eval tag)) form)))) 1042 'always)))))
1102 1043
1103(defun eshell-do-eval (form &optional synchronous-p) 1044(defun eshell-do-eval (form &optional synchronous-p)
1104 "Evaluate FORM, simplifying it as we go. 1045 "Evaluate FORM, simplifying it as we go.
@@ -1125,8 +1066,8 @@ have been replaced by constants."
1125 ;; we can modify any `let' forms to evaluate only once. 1066 ;; we can modify any `let' forms to evaluate only once.
1126 (if (macrop (car form)) 1067 (if (macrop (car form))
1127 (let ((exp (copy-tree (macroexpand form)))) 1068 (let ((exp (copy-tree (macroexpand form))))
1128 (eshell-manipulate (format-message "expanding macro `%s'" 1069 (eshell-manipulate form
1129 (symbol-name (car form))) 1070 (format-message "expanding macro `%s'" (symbol-name (car form)))
1130 (setcar form (car exp)) 1071 (setcar form (car exp))
1131 (setcdr form (cdr exp))))) 1072 (setcdr form (cdr exp)))))
1132 (let ((args (cdr form))) 1073 (let ((args (cdr form)))
@@ -1138,7 +1079,7 @@ have been replaced by constants."
1138 (let ((new-form (copy-tree `(let ((eshell--command-body nil) 1079 (let ((new-form (copy-tree `(let ((eshell--command-body nil)
1139 (eshell--test-body nil)) 1080 (eshell--test-body nil))
1140 (eshell--wrapped-while ,@args))))) 1081 (eshell--wrapped-while ,@args)))))
1141 (eshell-manipulate "modifying while form" 1082 (eshell-manipulate form "modifying while form"
1142 (setcar form (car new-form)) 1083 (setcar form (car new-form))
1143 (setcdr form (cdr new-form))) 1084 (setcdr form (cdr new-form)))
1144 (eshell-do-eval form synchronous-p))) 1085 (eshell-do-eval form synchronous-p)))
@@ -1161,7 +1102,7 @@ have been replaced by constants."
1161 (setq eshell--command-body nil 1102 (setq eshell--command-body nil
1162 eshell--test-body (copy-tree (car args))))) 1103 eshell--test-body (copy-tree (car args)))))
1163 ((eq (car form) 'if) 1104 ((eq (car form) 'if)
1164 (eshell-manipulate "evaluating if condition" 1105 (eshell-manipulate form "evaluating if condition"
1165 (setcar args (eshell-do-eval (car args) synchronous-p))) 1106 (setcar args (eshell-do-eval (car args) synchronous-p)))
1166 (eshell-do-eval 1107 (eshell-do-eval
1167 (cond 1108 (cond
@@ -1180,7 +1121,7 @@ have been replaced by constants."
1180 (eval form)) 1121 (eval form))
1181 ((eq (car form) 'let) 1122 ((eq (car form) 'let)
1182 (unless (eq (car-safe (cadr args)) 'eshell-do-eval) 1123 (unless (eq (car-safe (cadr args)) 'eshell-do-eval)
1183 (eshell-manipulate "evaluating let args" 1124 (eshell-manipulate form "evaluating let args"
1184 (dolist (letarg (car args)) 1125 (dolist (letarg (car args))
1185 (when (and (listp letarg) 1126 (when (and (listp letarg)
1186 (not (eq (cadr letarg) 'quote))) 1127 (not (eq (cadr letarg) 'quote)))
@@ -1207,7 +1148,7 @@ have been replaced by constants."
1207 ;; the let-bindings' values so that those values are 1148 ;; the let-bindings' values so that those values are
1208 ;; correct when we resume evaluation of this form. 1149 ;; correct when we resume evaluation of this form.
1209 (when deferred 1150 (when deferred
1210 (eshell-manipulate "rebinding let args after `eshell-defer'" 1151 (eshell-manipulate form "rebinding let args after `eshell-defer'"
1211 (let ((bindings (car args))) 1152 (let ((bindings (car args)))
1212 (while bindings 1153 (while bindings
1213 (let ((binding (if (consp (car bindings)) 1154 (let ((binding (if (consp (car bindings))
@@ -1232,7 +1173,7 @@ have been replaced by constants."
1232 (unless (eq (car form) 'unwind-protect) 1173 (unless (eq (car form) 'unwind-protect)
1233 (setq args (cdr args))) 1174 (setq args (cdr args)))
1234 (unless (eq (caar args) 'eshell-do-eval) 1175 (unless (eq (caar args) 'eshell-do-eval)
1235 (eshell-manipulate "handling special form" 1176 (eshell-manipulate form "handling special form"
1236 (setcar args `(eshell-do-eval ',(car args) ,synchronous-p)))) 1177 (setcar args `(eshell-do-eval ',(car args) ,synchronous-p))))
1237 (eval form)) 1178 (eval form))
1238 ((eq (car form) 'setq) 1179 ((eq (car form) 'setq)
@@ -1242,7 +1183,7 @@ have been replaced by constants."
1242 (list 'quote (eval form))) 1183 (list 'quote (eval form)))
1243 (t 1184 (t
1244 (if (and args (not (memq (car form) '(run-hooks)))) 1185 (if (and args (not (memq (car form) '(run-hooks))))
1245 (eshell-manipulate 1186 (eshell-manipulate form
1246 (format-message "evaluating arguments to `%s'" 1187 (format-message "evaluating arguments to `%s'"
1247 (symbol-name (car form))) 1188 (symbol-name (car form)))
1248 (while args 1189 (while args
@@ -1283,7 +1224,7 @@ have been replaced by constants."
1283 (setq result (eval form)))))) 1224 (setq result (eval form))))))
1284 (if new-form 1225 (if new-form
1285 (progn 1226 (progn
1286 (eshell-manipulate "substituting replacement form" 1227 (eshell-manipulate form "substituting replacement form"
1287 (setcar form (car new-form)) 1228 (setcar form (car new-form))
1288 (setcdr form (cdr new-form))) 1229 (setcdr form (cdr new-form)))
1289 (eshell-do-eval form synchronous-p)) 1230 (eshell-do-eval form synchronous-p))
@@ -1292,7 +1233,7 @@ have been replaced by constants."
1292 (procs (eshell-make-process-pair result))) 1233 (procs (eshell-make-process-pair result)))
1293 (if synchronous-p 1234 (if synchronous-p
1294 (eshell/wait (cdr procs)) 1235 (eshell/wait (cdr procs))
1295 (eshell-manipulate "inserting ignore form" 1236 (eshell-manipulate form "inserting ignore form"
1296 (setcar form 'ignore) 1237 (setcar form 'ignore)
1297 (setcdr form nil)) 1238 (setcdr form nil))
1298 (throw 'eshell-defer procs)) 1239 (throw 'eshell-defer procs))
diff --git a/lisp/eshell/esh-util.el b/lisp/eshell/esh-util.el
index 87cd1f5dcb2..8be4536cff7 100644
--- a/lisp/eshell/esh-util.el
+++ b/lisp/eshell/esh-util.el
@@ -102,6 +102,15 @@ argument matches `eshell-number-regexp'."
102 (string :tag "Username") 102 (string :tag "Username")
103 (repeat :tag "UIDs" string)))))) 103 (repeat :tag "UIDs" string))))))
104 104
105(defcustom eshell-debug-command nil
106 "A list of debug features to enable when running Eshell commands.
107Possible entries are `form', to log the manipulation of Eshell
108command forms.
109
110If nil, don't debug commands at all."
111 :version "30.1"
112 :type '(set (const :tag "Form manipulation" form)))
113
105;;; Internal Variables: 114;;; Internal Variables:
106 115
107(defvar eshell-number-regexp 116(defvar eshell-number-regexp
@@ -145,6 +154,9 @@ function `string-to-number'.")
145 ,#'eshell--mark-yanked-as-output)) 154 ,#'eshell--mark-yanked-as-output))
146 "A list of text properties to apply to command output.") 155 "A list of text properties to apply to command output.")
147 156
157(defvar eshell-debug-command-buffer "*eshell last cmd*"
158 "The name of the buffer to log debug messages about command invocation.")
159
148;;; Obsolete variables: 160;;; Obsolete variables:
149 161
150(define-obsolete-variable-alias 'eshell-host-names 162(define-obsolete-variable-alias 'eshell-host-names
@@ -164,11 +176,33 @@ function `string-to-number'.")
164 "If `eshell-handle-errors' is non-nil, this is `condition-case'. 176 "If `eshell-handle-errors' is non-nil, this is `condition-case'.
165Otherwise, evaluates FORM with no error handling." 177Otherwise, evaluates FORM with no error handling."
166 (declare (indent 2) (debug (sexp form &rest form))) 178 (declare (indent 2) (debug (sexp form &rest form)))
167 (if eshell-handle-errors 179 `(if eshell-handle-errors
168 `(condition-case-unless-debug ,tag 180 (condition-case-unless-debug ,tag
169 ,form 181 ,form
170 ,@handlers) 182 ,@handlers)
171 form)) 183 ,form))
184
185(defun eshell-debug-command-start (command)
186 "Start debugging output for the command string COMMAND.
187If debugging is enabled (see `eshell-debug-command'), this will
188start logging to `*eshell last cmd*'."
189 (when eshell-debug-command
190 (with-current-buffer (get-buffer-create eshell-debug-command-buffer)
191 (erase-buffer)
192 (insert "command: \"" command "\"\n"))))
193
194(defmacro eshell-debug-command (kind message &optional form always)
195 "Output a debugging message to `*eshell last cmd*' if debugging is enabled.
196KIND is the kind of message to log (either `form' or `io'). If
197present in `eshell-debug-command' (or if ALWAYS is non-nil),
198output this message; otherwise, ignore it."
199 (let ((kind-sym (make-symbol "kind")))
200 `(let ((,kind-sym ,kind))
201 (when ,(or always `(memq ,kind-sym eshell-debug-command))
202 (with-current-buffer (get-buffer-create eshell-debug-command-buffer)
203 (insert "\n\C-l\n[" (symbol-name ,kind-sym) "] " ,message)
204 (when-let ((form ,form))
205 (insert "\n\n" (eshell-stringify form))))))))
172 206
173(defun eshell--mark-as-output (start end &optional object) 207(defun eshell--mark-as-output (start end &optional object)
174 "Mark the text from START to END as Eshell output. 208 "Mark the text from START to END as Eshell output.
diff --git a/lisp/eshell/eshell.el b/lisp/eshell/eshell.el
index 15fc2ae6310..cbd0de3c093 100644
--- a/lisp/eshell/eshell.el
+++ b/lisp/eshell/eshell.el
@@ -301,7 +301,8 @@ argument), then insert output into the current buffer at point."
301 `(let ((eshell-current-handles 301 `(let ((eshell-current-handles
302 (eshell-create-handles ,stdout 'insert)) 302 (eshell-create-handles ,stdout 'insert))
303 (eshell-current-subjob-p)) 303 (eshell-current-subjob-p))
304 ,(eshell-parse-command command)))) 304 ,(eshell-parse-command command))
305 command))
305 intr 306 intr
306 (bufname (if (eq (car-safe proc) :eshell-background) 307 (bufname (if (eq (car-safe proc) :eshell-background)
307 "*Eshell Async Command Output*" 308 "*Eshell Async Command Output*"