+;; status feedback to the user
+(defvar reporter-status-message nil)
+(defvar reporter-status-count nil)
+
+(defun reporter-update-status ()
+ "Periodically output a status message."
+ (if (zerop (% reporter-status-count 10))
+ (progn
+ (message reporter-status-message)
+ (setq reporter-status-message (concat reporter-status-message "."))))
+ (setq reporter-status-count (1+ reporter-status-count)))
+
+\f
+;; dumping/pretty printing of values
+(defun reporter-beautify-list (maxwidth compact-p)
+ "Pretty print a list."
+ (reporter-update-status)
+ (let ((move t)
+ linebreak indent-enclosing-p indent-p here)
+ (condition-case nil ;loop exit
+ (progn
+ (down-list 1)
+ (setq indent-enclosing-p t)
+ (while move
+ (setq here (point))
+ ;; The following line is how we break out of the while
+ ;; loop, in one of two ways. Either we've hit the end of
+ ;; the buffer, in which case scan-sexps returns nil, or
+ ;; we've crossed unbalanced parens and it will raise an
+ ;; error we're expecting to catch.
+ (setq move (scan-sexps (point) 1))
+ (goto-char move)
+ (if (<= maxwidth (current-column))
+ (if linebreak
+ (progn
+ (goto-char linebreak)
+ (newline-and-indent)
+ (setq linebreak nil))
+ (goto-char here)
+ (setq indent-p (reporter-beautify-list maxwidth compact-p))
+ (goto-char here)
+ (forward-sexp 1)
+ (if indent-p
+ (newline-and-indent))
+ t)
+ (if compact-p
+ (setq linebreak (point))
+ (newline-and-indent))
+ ))
+ t)
+ (error indent-enclosing-p))))
+
+(defun reporter-lisp-indent (indent-point state)
+ "A better lisp indentation style for bug reporting."
+ (save-excursion
+ (goto-char (1+ (nth 1 state)))
+ (current-column)))
+
+(defun reporter-dump-variable (varsym mailbuf)
+ "Pretty-print the value of the variable in symbol VARSYM.
+MAILBUF is the mail buffer being composed."
+ (reporter-update-status)
+ (condition-case nil
+ (let ((val (save-excursion
+ (set-buffer reporter-eval-buffer)
+ (symbol-value varsym)))
+ (sym (symbol-name varsym))
+ (print-escape-newlines t)
+ (maxwidth (1- (window-width)))
+ (here (point)))
+ (insert " " sym " "
+ (cond
+ ((memq val '(t nil)) "")
+ ((listp val) "'")
+ ((symbolp val) "'")
+ (t ""))
+ (prin1-to-string val))
+ (lisp-indent-line)
+ ;; clean up lists, but only if the line as printed was long
+ ;; enough to wrap
+ (if (and val ;nil is a list, but short
+ (listp val)
+ (<= maxwidth (current-column)))
+ (save-excursion
+ (let ((compact-p (not (memq varsym reporter-dont-compact-list)))
+ (lisp-indent-function 'reporter-lisp-indent))
+ (goto-char here)
+ (reporter-beautify-list maxwidth compact-p))))
+ (insert "\n"))
+ (void-variable
+ (save-excursion
+ (set-buffer mailbuf)
+ (mail-position-on-field "X-Reporter-Void-Vars-Found")
+ (end-of-line)
+ (insert (symbol-name varsym) " ")))
+ (error
+ (error ""))))