@item
@code{error}, to enable/disable Eshell trapping errors when
-evaluating commands; or
+evaluating commands;
@item
@code{form}, to show/hide Eshell command form manipulation in the
-buffer @code{*eshell last cmd*}.
+buffer @code{*eshell last cmd*}; or
+
+@item
+@code{process}, to show/hide external process events in the buffer
+@code{*eshell last cmd*}.
@end itemize
are:
error stops Eshell from trapping errors
- form shows command form manipulation in `*eshell last cmd*'")
+ form shows command form manipulation in `*eshell last cmd*'
+ process shows process events in `*eshell last cmd*'")
(if args
(dolist (kind args)
(if (equal kind "error")
(defun pcomplete/eshell-mode/eshell-debug ()
"Completion for the `debug' command."
- (while (pcomplete-here '("error" "form"))))
+ (while (pcomplete-here '("error" "form" "process"))))
(provide 'em-basic)
:connection-type conn-type
:stderr stderr-proc
:file-handler t)))
+ (eshell-debug-command
+ 'process (format-message "started external process `%s'" proc))
(eshell-record-process-object proc)
(eshell-record-process-properties proc)
(run-hook-with-args 'eshell-exec-hook proc)
"Send the output from PROCESS (STRING) to the interactive display.
This is done after all necessary filtering has been done."
(when string
+ (eshell-debug-command
+ 'process (format-message "received output from process `%s'\n\n%s"
+ process string))
(eshell--mark-as-output 0 (length string) string)
(require 'esh-mode)
(declare-function eshell-interactive-filter "esh-mode" (buffer string))
(data (process-get proc :eshell-pending)))
(process-put proc :eshell-pending nil)
(process-put proc :eshell-busy t)
+ (eshell-debug-command
+ 'process (format-message "received output from process `%s'\n\n%s"
+ proc string))
(unwind-protect
(condition-case nil
(eshell-output-object data index handles)
(defun eshell-sentinel (proc string)
"Generic sentinel for command processes. Reports only signals.
PROC is the process that's exiting. STRING is the exit message."
+ (eshell-debug-command
+ 'process (format-message "sentinel for external process `%s': %S"
+ proc string))
(when (buffer-live-p (process-buffer proc))
(with-current-buffer (process-buffer proc)
(unwind-protect
status
(when status (list 'quote (= status 0)))
handles)
- (eshell-kill-process-function proc string)))))
+ (eshell-kill-process-function proc string)
+ (eshell-debug-command
+ 'process
+ (format-message
+ "finished external process `%s'" proc))))))
(funcall finish-io))))
(when-let ((entry (assq proc eshell-process-list)))
(eshell-remove-process-entry entry))))))
(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.
+command forms, and `process', to log external process operations.
If nil, don't debug commands at all."
:version "30.1"
- :type '(set (const :tag "Form manipulation" form)))
+ :type '(set (const :tag "Form manipulation" form)
+ (const :tag "Process operations" process)))
;;; Internal Variables:
(let* (;; We want no history file, so prevent Eshell from falling
;; back on $HISTFILE.
(process-environment (cons "HISTFILE" process-environment))
+ ;; Enable process debug instrumentation. We may be able
+ ;; to remove this eventually once we're confident that
+ ;; all the process bugs have been worked out. (At that
+ ;; point, we can just enable this selectively when
+ ;; needed.)
+ (eshell-debug-command (cons 'process eshell-debug-command))
(eshell-history-file-name nil)
(eshell-last-dir-ring-file-name nil)
(eshell-buffer (eshell t)))
(lambda ()
(not (if all eshell-process-list (eshell-interactive-process-p))))))
+(defun eshell-get-debug-logs ()
+ "Get debug command logs for displaying on test failures."
+ (when (get-buffer eshell-debug-command-buffer)
+ (let ((separator (make-string 40 ?-)))
+ (with-current-buffer eshell-debug-command-buffer
+ (string-replace "\f" separator (buffer-string))))))
+
(defun eshell-insert-command (command &optional func)
"Insert a COMMAND at the end of the buffer.
After inserting, call FUNC. If FUNC is nil, instead call
If IGNORE-ERRORS is non-nil, ignore any errors signaled when
inserting the command."
- (let ((debug-on-error (and (not ignore-errors) debug-on-error)))
- (eshell-insert-command command func))
- (eshell-wait-for-subprocess)
- (should (eshell-match-output regexp)))
+ (ert-info (#'eshell-get-debug-logs :prefix "Command logs: ")
+ (let ((debug-on-error (and (not ignore-errors) debug-on-error)))
+ (eshell-insert-command command func))
+ (eshell-wait-for-subprocess)
+ (should (eshell-match-output regexp))))
(defvar eshell-history-file-name)
(defun eshell-command-result-equal (command result)
"Execute COMMAND non-interactively and compare it to RESULT."
- (should (eshell-command-result--equal
- command
- (eshell-test-command-result command)
- result)))
+ (ert-info (#'eshell-get-debug-logs :prefix "Command logs: ")
+ (should (eshell-command-result--equal
+ command
+ (eshell-test-command-result command)
+ result))))
(provide 'eshell-tests-helpers)