;;; emchat-report.el --- Generate a bug report -*-Emacs-Lisp-*- ;; Copyright (C) 2001 - 2011 Steve Youngs ;; Author: Steve Youngs ;; Maintainer: Steve Youngs ;; Keywords: bug-report ;; This file is part of EMchat. ;; Redistribution and use in source and binary forms, with or without ;; modification, are permitted provided that the following conditions ;; are met: ;; ;; 1. Redistributions of source code must retain the above copyright ;; notice, this list of conditions and the following disclaimer. ;; ;; 2. Redistributions in binary form must reproduce the above copyright ;; notice, this list of conditions and the following disclaimer in the ;; documentation and/or other materials provided with the distribution. ;; ;; 3. Neither the name of the author nor the names of any contributors ;; may be used to endorse or promote products derived from this ;; software without specific prior written permission. ;; ;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR ;; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ;; DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ;; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR ;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF ;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE ;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN ;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ;;; Commentary: ;; To submit a bug report use: M-x emchat-report-bug ;; To send general comments/questions use: M-x emchat-email-author ;;; Code: (autoload 'emchat-version "emchat" "Version of emchat you are currently using." t nil) (eval-when-compile (setq message-send-mail-function 'message-send-mail-with-sendmail)) (require 'sendmail) (require 'shadow) (require 'gnus-msg) (require 'gnus-util) (require 'message) ;; To keep the byte-compiler from spewing out warnings. (eval-when-compile (defvar after-sep-pos) (defvar final-resting-place) (defvar emchat-version) (require 'font-lock) (require 'yow) (require 'pp)) ;;; Variables (defcustom emchat-report-bug-send-init nil "*If non-nil, include the user's init.el file in the bug report." :group 'emchat-option :type 'boolean) ;;; Internal variables (defconst emchat-report-salutations ["Dear bug team:" "Ciao bug team:" "Salut bug team:" "Guten Tag bug team:" "To whom it may concern:" "Fellow EMchat'ers:" "Yo bug team:" "G'day bug team:" "Greetings Earthlings:"] "A list of salutations used for `emchat-report-bug'.") (defvar emchat-bug-address "EMchat Bugs " "The address used for submitting bug reports.") (defvar emchat-report-blurb nil) ;;; Functions (defun emchat-report-pre-hook () "Pre hook run by report-submit-bug-report." (message-goto-subject) (insert "EMchat bug: ") (if emchat-report-blurb (progn (mail-text) (insert "\n" emchat-report-blurb "\n")))) (defun emchat-report-post-hook () "Post hook run by report-submit-bug-report." (save-excursion (message-goto-subject) (font-lock-fontify-buffer) (let ((subj (read-string "Subject header: "))) (if (string-equal subj "") (subst-char-in-region (point) (progn (insert (if (or (fboundp 'yow) (load "yow" t t)) (yow) "")) (point)) ?\n ?\ ) (insert subj))))) ;; Stolen from Gnus. (defun emchat-report-debug () "Go through the EMchat source files and report what variables have been changed. The source file has to be in the load path." (let ((files '("emchat-buddy.el" "emchat-comm.el" "emchat-curl.el" "emchat-doctor.el" "emchat-emphasis.el" "emchat-log.el" "emchat-meta.el" "emchat-report.el" "emchat-status.el" "emchat-toolbar.el" "emchat-track.el" "emchat-wharf.el" "emchat-world.el" "emchat-xwem.el" "emchat.el")) (point (point)) file expr olist sym) (message "Please wait while we snoop your variables...") (sit-for 0) ;; Go through all the files looking for non-default values for variables. (save-excursion (set-buffer (get-buffer-create " *emchat bug info*")) (while files (erase-buffer) (when (and (setq file (locate-library (pop files))) (file-exists-p file)) (insert-file-contents file) (goto-char (point-min)) (if (not (re-search-forward "^;;* *Internal variables" nil t)) (message "Malformed sources in file %s" file) (narrow-to-region (point-min) (point)) (goto-char (point-min)) (while (setq expr (ignore-errors (read (current-buffer)))) (ignore-errors (and (or (eq (car expr) 'defvar) (eq (car expr) 'defcustom)) (stringp (nth 3 expr)) (or (not (boundp (nth 1 expr))) (not (equal (eval (nth 2 expr)) (symbol-value (nth 1 expr))))) (push (nth 1 expr) olist))))))) (kill-buffer (current-buffer))) (when (setq olist (nreverse olist)) (insert "\n")) (while olist (when (boundp (car olist)) (condition-case () (pp `(setq ,(car olist) ,(if (or (consp (setq sym (symbol-value (car olist)))) (and (symbolp sym) (not (or (eq sym nil) (eq sym t))))) (list 'quote (symbol-value (car olist))) (symbol-value (car olist)))) (current-buffer)) (error (format "(setq %s 'whatever)\n" (car olist))))) ;(insert ";; (makeunbound '" (symbol-name (car olist)) ")\n")) (setq olist (cdr olist))) ;; Remove any control chars - they seem to cause trouble for some ;; mailers. (Byte-compiled output from the stuff above.) (goto-char point) (while (re-search-forward "[\000-\010\013-\037\200-\237]" nil t) (replace-match (format "\\%03o" (string-to-char (match-string 0))) t t)))) (defun emchat-prepare-report () "Grabs the variables, features to include in bug report. Then put it all into a mail buffer, nicely formatted." (message-goto-to) (insert emchat-bug-address) (message-goto-body) (forward-line 1) (setq after-sep-pos (point)) (setq final-resting-place (point-marker)) (insert "\n\n" "===============================================================\n" "System info to help the EMchat boys and girls try to fix your bug:\n" "===============================================================" "\n\n") (emchat-version 1) ;; Insert all the EMchat vars that have been changed from default. ;; The actual work for this is done in `emchat-bug-debug', but it ;; needs to be called toward the end of this function. (insert "\n\nEMchat variables of note:\n----------------------\n") ;; Insert the output of 'describe-installation'. (insert "\n\n" (symbol-value 'Installation-string)) ;; Load-path shadows can cause some grief. (flet ((append-message (&rest args) ()) (clear-message (&optional label frame stdout-p no-restore) ())) (insert "\n\nLoad-Path Lisp Shadows:\n" "----------------------\n") (let ((before-shadows (point))) (insert (format "%s" (find-emacs-lisp-shadows load-path))) (save-restriction (narrow-to-region before-shadows (point)) (fill-paragraph t) (insert "\n")))) ;; Insert a list of installed packages. (insert "\n\nInstalled XEmacs Packages:\n" "-------------------------\n") (cl-prettyprint (symbol-value 'packages-package-list)) (insert "\n") ;; Insert a list of loaded features (let ((before-features (point))) (insert (format "\n\nFeatures:\n--------\n\n%s" (symbol-value 'features))) (save-restriction (narrow-to-region before-features (point)) (fill-paragraph t) (insert "\n\n"))) ;; Insert the contents of the user's init file if it exists ;; and the user wants it sent. (if emchat-report-bug-send-init (if (file-readable-p user-init-file) (save-excursion (message-goto-signature) (forward-line -3) (beginning-of-line) (insert "\n\nUser Init File:\n--------------\n\n") (insert-file-contents user-init-file)))) (emchat-report-pre-hook) (emchat-report-post-hook) (mail-text) (insert (aref emchat-report-salutations (% (+ (% (random) 1000) 1000) (length emchat-report-salutations))) "\n") (re-search-forward "EMchat variables of note:" nil t) (forward-line 2) (emchat-report-debug) (goto-char final-resting-place) (set-marker final-resting-place nil) (message "Please enter your report. Type C-c C-c to send, C-x k to abort.")) ;;;###autoload (defun emchat-report-bug (&optional blurb no-confirm) "Submit a bug report for emchat. Optional argument BLURB is a string that adds a preamble to the bug report. Optional argument NO-CONFIRM if 't' will not ask for confirmation. If you have Gnus it will be used, otherwise the standard XEmacs mail command is used. Yes, it's all part of a secret plot to make more people use the MUA of Gods. Bwahahaha." (interactive) (if (or no-confirm (y-or-n-p "Do you want to submit a bug report on EMchat? ")) (progn (setq emchat-report-blurb blurb) (if (featurep 'gnus) (progn (unless (gnus-alive-p) (gnus)) (gnus-group-mail 1) (emchat-prepare-report)) (mail) (emchat-prepare-report))))) ;;; email-author code (defconst emchat-email-salutations ["Dear Steve," "Ciao Steve," "Guten Tag Steve," "To whom it may concern:" "Bonjour Steve," "Yo! EMchat Dude!" "G'day Steve," "Hey Man," "Greetings Earthling:"] "A list of salutations used for `emchat-email-author'.") (defun emchat-prepare-email-author () "Prepare the mail buffer for `emchat-email-author'." (message-goto-to) (insert "Steve Youngs ") (message-goto-cc) (insert "EMchat Users ") (message-goto-subject) (let ((subj (read-string "Subject header: "))) (if (string-equal subj "") (subst-char-in-region (point) (progn (insert (if (or (fboundp 'yow) (load "yow" t t)) (yow) "")) (point)) ?\n ?\ ) (insert subj))) (message-goto-body) (emchat-version 1) (insert "\n\n" (aref emchat-email-salutations (% (+ (% (random) 1000) 1000) (length emchat-email-salutations))) "\n\n\n") (forward-line -1)) ;;;###autoload (defun emchat-email-author () "Email comments or money to author. Uses Gnus if available, otherwise standard mail command." (interactive) (if (y-or-n-p "Do you want to send comments to the EMchat author? ") (progn (if (featurep 'gnus) (progn (unless (gnus-alive-p) (gnus)) (gnus-group-mail 1) (emchat-prepare-email-author)) (mail) (emchat-prepare-email-author))))) (provide 'emchat-report) ;;; emchat-report.el ends here