: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
(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."
;; 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
(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
(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.
;; 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)))
(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)))
(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
(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)))
;; 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))
(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)
(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
(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))
(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))
(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
,#'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
"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.