[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master ccb62321d23 1/2: Fix handling of Eshell debug modes
From: |
Jim Porter |
Subject: |
master ccb62321d23 1/2: Fix handling of Eshell debug modes |
Date: |
Thu, 31 Aug 2023 21:53:33 -0400 (EDT) |
branch: master
commit ccb62321d234993a66287c4e1a3cfdea63d140ff
Author: Jim Porter <jporterbugs@gmail.com>
Commit: Jim Porter <jporterbugs@gmail.com>
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'.
---
doc/misc/eshell.texi | 17 ++++++--
lisp/eshell/em-basic.el | 31 ++++++++++++++
lisp/eshell/esh-cmd.el | 105 +++++++++++-------------------------------------
lisp/eshell/esh-util.el | 44 +++++++++++++++++---
lisp/eshell/eshell.el | 3 +-
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.
@item eshell-debug
@cmindex eshell-debug
Toggle debugging information for Eshell itself. You can pass this
-command the argument @code{errors} to enable/disable Eshell trapping
-errors when evaluating commands, or the argument @code{commands} to
-show/hide command execution progress in the buffer @code{*eshell last
-cmd*}.
+command one or more of the following arguments:
+
+@itemize @bullet
+
+@item
+@code{error}, to enable/disable Eshell trapping errors when
+evaluating commands; or
+
+@item
+@code{form}, to show/hide Eshell command form manipulation in the
+buffer @code{*eshell last cmd*}.
+
+@end itemize
@item exit
@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."
(put 'eshell/umask 'eshell-no-numeric-conversions t)
+(defun eshell/eshell-debug (&rest args)
+ "A command for toggling certain debug variables."
+ (eshell-eval-using-options
+ "eshell-debug" args
+ '((?h "help" nil nil "display this usage message")
+ :usage "[KIND]...
+This command is used to aid in debugging problems related to Eshell
+itself. It is not useful for anything else. The recognized `kinds'
+are:
+
+ error stops Eshell from trapping errors
+ form shows command form manipulation in `*eshell last cmd*'")
+ (if args
+ (dolist (kind args)
+ (if (equal kind "error")
+ (setq eshell-handle-errors (not eshell-handle-errors))
+ (let ((kind-sym (intern kind)))
+ (if (memq kind-sym eshell-debug-command)
+ (setq eshell-debug-command
+ (delq kind-sym eshell-debug-command))
+ (push kind-sym eshell-debug-command)))))
+ ;; Output the currently-enabled debug kinds.
+ (unless eshell-handle-errors
+ (eshell-print "errors\n"))
+ (dolist (kind eshell-debug-command)
+ (eshell-printn (symbol-name kind))))))
+
+(defun pcomplete/eshell-mode/eshell-debug ()
+ "Completion for the `debug' command."
+ (while (pcomplete-here '("error" "form"))))
+
(provide 'em-basic)
;; 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."
:version "24.1" ; removed eshell-cmd-initialize
:type 'hook)
-(defcustom eshell-debug-command nil
- "If non-nil, enable Eshell debugging code.
-This is slow, and only useful for debugging problems with Eshell.
-If you change this without using customize after Eshell has loaded,
-you must re-load `esh-cmd.el'."
- :initialize 'custom-initialize-default
- :set (lambda (symbol value)
- (set symbol value)
- (load "esh-cmd"))
- :type 'boolean)
-
(defcustom eshell-deferrable-commands
'(eshell-named-command
eshell-lisp-command
@@ -436,22 +425,9 @@ hooks should be run before and after the command."
(run-hooks 'eshell-post-command-hook)))
(macroexp-progn commands))))
-(defun eshell-debug-command (tag subform)
- "Output a debugging message to `*eshell last cmd*'."
- (let ((buf (get-buffer-create "*eshell last cmd*"))
- (text (eshell-stringify eshell-current-command)))
- (with-current-buffer buf
- (if (not tag)
- (erase-buffer)
- (insert "\n\C-l\n" tag "\n\n" text
- (if subform
- (concat "\n\n" (eshell-stringify subform)) ""))))))
-
(defun eshell-debug-show-parsed-args (terms)
"Display parsed arguments in the debug buffer."
- (ignore
- (if eshell-debug-command
- (eshell-debug-command "parsed arguments" terms))))
+ (ignore (eshell-debug-command 'form "parsed arguments" terms)))
(defun eshell-no-command-conversion (terms)
"Don't convert the command argument."
@@ -942,38 +918,6 @@ This avoids the need to use `let*'."
;; finishes, it will resume the evaluation using the remainder of the
;; command tree.
-(defun eshell/eshell-debug (&rest args)
- "A command for toggling certain debug variables."
- (ignore
- (cond
- ((not args)
- (if eshell-handle-errors
- (eshell-print "errors\n"))
- (if eshell-debug-command
- (eshell-print "commands\n")))
- ((member (car args) '("-h" "--help"))
- (eshell-print "usage: eshell-debug [kinds]
-
-This command is used to aid in debugging problems related to Eshell
-itself. It is not useful for anything else. The recognized `kinds'
-at the moment are:
-
- errors stops Eshell from trapping errors
- commands shows command execution progress in `*eshell last cmd*'
-"))
- (t
- (while args
- (cond
- ((string= (car args) "errors")
- (setq eshell-handle-errors (not eshell-handle-errors)))
- ((string= (car args) "commands")
- (setq eshell-debug-command (not eshell-debug-command))))
- (setq args (cdr args)))))))
-
-(defun pcomplete/eshell-mode/eshell-debug ()
- "Completion for the `debug' command."
- (while (pcomplete-here '("errors" "commands"))))
-
(iter-defun eshell--find-subcommands (haystack)
"Recursively search for subcommand forms in HAYSTACK.
This yields the SUBCOMMANDs when found in forms like
@@ -1049,10 +993,7 @@ process(es) in a cons cell like:
(if here
(eshell-update-markers here))
(eshell-do-eval ',command))))
- (and eshell-debug-command
- (with-current-buffer (get-buffer-create "*eshell last cmd*")
- (erase-buffer)
- (insert "command: \"" input "\"\n")))
+ (eshell-debug-command-start input)
(setq eshell-current-command command)
(let* (result
(delim (catch 'eshell-incomplete
@@ -1088,17 +1029,17 @@ process(es) in a cons cell like:
(error
(error (error-message-string err)))))
-(defmacro eshell-manipulate (tag &rest commands)
- "Manipulate a COMMAND form, with TAG as a debug identifier."
- (declare (indent 1))
- ;; Check `bound'ness since at compile time the code until here has not
- ;; executed yet.
- (if (not (and (boundp 'eshell-debug-command) eshell-debug-command))
- `(progn ,@commands)
- `(progn
- (eshell-debug-command ,(eval tag) form)
- ,@commands
- (eshell-debug-command ,(concat "done " (eval tag)) form))))
+(defmacro eshell-manipulate (form tag &rest body)
+ "Manipulate a command FORM with BODY, using TAG as a debug identifier."
+ (declare (indent 2))
+ (let ((tag-symbol (make-symbol "tag")))
+ `(if (not (memq 'form eshell-debug-command))
+ (progn ,@body)
+ (let ((,tag-symbol ,tag))
+ (eshell-debug-command 'form ,tag-symbol ,form 'always)
+ ,@body
+ (eshell-debug-command 'form (concat "done " ,tag-symbol) ,form
+ 'always)))))
(defun eshell-do-eval (form &optional synchronous-p)
"Evaluate FORM, simplifying it as we go.
@@ -1125,8 +1066,8 @@ have been replaced by constants."
;; we can modify any `let' forms to evaluate only once.
(if (macrop (car form))
(let ((exp (copy-tree (macroexpand form))))
- (eshell-manipulate (format-message "expanding macro `%s'"
- (symbol-name (car form)))
+ (eshell-manipulate form
+ (format-message "expanding macro `%s'" (symbol-name (car form)))
(setcar form (car exp))
(setcdr form (cdr exp)))))
(let ((args (cdr form)))
@@ -1138,7 +1079,7 @@ have been replaced by constants."
(let ((new-form (copy-tree `(let ((eshell--command-body nil)
(eshell--test-body nil))
(eshell--wrapped-while ,@args)))))
- (eshell-manipulate "modifying while form"
+ (eshell-manipulate form "modifying while form"
(setcar form (car new-form))
(setcdr form (cdr new-form)))
(eshell-do-eval form synchronous-p)))
@@ -1161,7 +1102,7 @@ have been replaced by constants."
(setq eshell--command-body nil
eshell--test-body (copy-tree (car args)))))
((eq (car form) 'if)
- (eshell-manipulate "evaluating if condition"
+ (eshell-manipulate form "evaluating if condition"
(setcar args (eshell-do-eval (car args) synchronous-p)))
(eshell-do-eval
(cond
@@ -1180,7 +1121,7 @@ have been replaced by constants."
(eval form))
((eq (car form) 'let)
(unless (eq (car-safe (cadr args)) 'eshell-do-eval)
- (eshell-manipulate "evaluating let args"
+ (eshell-manipulate form "evaluating let args"
(dolist (letarg (car args))
(when (and (listp letarg)
(not (eq (cadr letarg) 'quote)))
@@ -1207,7 +1148,7 @@ have been replaced by constants."
;; the let-bindings' values so that those values are
;; correct when we resume evaluation of this form.
(when deferred
- (eshell-manipulate "rebinding let args after `eshell-defer'"
+ (eshell-manipulate form "rebinding let args after `eshell-defer'"
(let ((bindings (car args)))
(while bindings
(let ((binding (if (consp (car bindings))
@@ -1232,7 +1173,7 @@ have been replaced by constants."
(unless (eq (car form) 'unwind-protect)
(setq args (cdr args)))
(unless (eq (caar args) 'eshell-do-eval)
- (eshell-manipulate "handling special form"
+ (eshell-manipulate form "handling special form"
(setcar args `(eshell-do-eval ',(car args) ,synchronous-p))))
(eval form))
((eq (car form) 'setq)
@@ -1242,7 +1183,7 @@ have been replaced by constants."
(list 'quote (eval form)))
(t
(if (and args (not (memq (car form) '(run-hooks))))
- (eshell-manipulate
+ (eshell-manipulate form
(format-message "evaluating arguments to `%s'"
(symbol-name (car form)))
(while args
@@ -1283,7 +1224,7 @@ have been replaced by constants."
(setq result (eval form))))))
(if new-form
(progn
- (eshell-manipulate "substituting replacement form"
+ (eshell-manipulate form "substituting replacement form"
(setcar form (car new-form))
(setcdr form (cdr new-form)))
(eshell-do-eval form synchronous-p))
@@ -1292,7 +1233,7 @@ have been replaced by constants."
(procs (eshell-make-process-pair result)))
(if synchronous-p
(eshell/wait (cdr procs))
- (eshell-manipulate "inserting ignore form"
+ (eshell-manipulate form "inserting ignore form"
(setcar form 'ignore)
(setcdr form nil))
(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'."
(string :tag "Username")
(repeat :tag "UIDs" string))))))
+(defcustom eshell-debug-command nil
+ "A list of debug features to enable when running Eshell commands.
+Possible entries are `form', to log the manipulation of Eshell
+command forms.
+
+If nil, don't debug commands at all."
+ :version "30.1"
+ :type '(set (const :tag "Form manipulation" form)))
+
;;; Internal Variables:
(defvar eshell-number-regexp
@@ -145,6 +154,9 @@ function `string-to-number'.")
,#'eshell--mark-yanked-as-output))
"A list of text properties to apply to command output.")
+(defvar eshell-debug-command-buffer "*eshell last cmd*"
+ "The name of the buffer to log debug messages about command invocation.")
+
;;; Obsolete variables:
(define-obsolete-variable-alias 'eshell-host-names
@@ -164,11 +176,33 @@ function `string-to-number'.")
"If `eshell-handle-errors' is non-nil, this is `condition-case'.
Otherwise, evaluates FORM with no error handling."
(declare (indent 2) (debug (sexp form &rest form)))
- (if eshell-handle-errors
- `(condition-case-unless-debug ,tag
- ,form
- ,@handlers)
- form))
+ `(if eshell-handle-errors
+ (condition-case-unless-debug ,tag
+ ,form
+ ,@handlers)
+ ,form))
+
+(defun eshell-debug-command-start (command)
+ "Start debugging output for the command string COMMAND.
+If debugging is enabled (see `eshell-debug-command'), this will
+start logging to `*eshell last cmd*'."
+ (when eshell-debug-command
+ (with-current-buffer (get-buffer-create eshell-debug-command-buffer)
+ (erase-buffer)
+ (insert "command: \"" command "\"\n"))))
+
+(defmacro eshell-debug-command (kind message &optional form always)
+ "Output a debugging message to `*eshell last cmd*' if debugging is enabled.
+KIND is the kind of message to log (either `form' or `io'). If
+present in `eshell-debug-command' (or if ALWAYS is non-nil),
+output this message; otherwise, ignore it."
+ (let ((kind-sym (make-symbol "kind")))
+ `(let ((,kind-sym ,kind))
+ (when ,(or always `(memq ,kind-sym eshell-debug-command))
+ (with-current-buffer (get-buffer-create eshell-debug-command-buffer)
+ (insert "\n\C-l\n[" (symbol-name ,kind-sym) "] " ,message)
+ (when-let ((form ,form))
+ (insert "\n\n" (eshell-stringify form))))))))
(defun eshell--mark-as-output (start end &optional object)
"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."
`(let ((eshell-current-handles
(eshell-create-handles ,stdout 'insert))
(eshell-current-subjob-p))
- ,(eshell-parse-command command))))
+ ,(eshell-parse-command command))
+ command))
intr
(bufname (if (eq (car-safe proc) :eshell-background)
"*Eshell Async Command Output*"