aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman1994-07-18 18:49:25 +0000
committerRichard M. Stallman1994-07-18 18:49:25 +0000
commit4f40f16981682294af80203ca7223dbbdbca7839 (patch)
tree8602da788626eb5411b6d78c9a7509082dff5bcc
parent847e150a1858ab6cab44779c1ea60e2236c8bbd0 (diff)
downloademacs-4f40f16981682294af80203ca7223dbbdbca7839.tar.gz
emacs-4f40f16981682294af80203ca7223dbbdbca7839.zip
(reporter-dump-state, reporter-submit-bug-report):
Don't print package name if pkgname is nil. Don't dump state if varlist is nil. (reporter-bug-hook, reporter-submit-bug-report) (reporter-calculate-separator, reporter-initial-text): New or modified functions and variables attempting to prohibit submission of empty bug reporters. (reporter-prompt-for-summary-p): Default value now nil. (reporter-dump-state): Make sure there's a final newline after the setq sexp. Pass mail buffer as second arg to print fcn. Use symbol-value to get varsym's value. (reporter-dump-variable): Handle long sexp's even after entering newline. Done by filling current line. Much better pretty printing of long lists!! Handle void variables. (reporter-version): New variable. (reporter-submit-bug-report-internal): Leave point after the salutation. (reporter-submit-bug-report): Prompt for a subject.
-rw-r--r--lisp/mail/reporter.el355
1 files changed, 251 insertions, 104 deletions
diff --git a/lisp/mail/reporter.el b/lisp/mail/reporter.el
index e1251bcb89d..bc321bb69ad 100644
--- a/lisp/mail/reporter.el
+++ b/lisp/mail/reporter.el
@@ -3,11 +3,12 @@
3;; Author: 1993 Barry A. Warsaw, Century Computing Inc. <bwarsaw@cen.com> 3;; Author: 1993 Barry A. Warsaw, Century Computing Inc. <bwarsaw@cen.com>
4;; Maintainer: bwarsaw@cen.com 4;; Maintainer: bwarsaw@cen.com
5;; Created: 19-Apr-1993 5;; Created: 19-Apr-1993
6;; Version: 1.23 6;; Version: 2.12
7;; Last Modified: 1993/09/02 20:28:36 7;; Last Modified: 1994/07/06 14:55:39
8;; Keywords: tools, mail, lisp, extensions 8;; Keywords: bug reports lisp
9 9
10;; Copyright (C) 1993 Free Software Foundation, Inc. 10;; Copyright (C) 1993 1994 Barry A. Warsaw
11;; Copyright (C) 1993 1994 Free Software Foundation, Inc.
11 12
12;; This file is part of GNU Emacs. 13;; This file is part of GNU Emacs.
13 14
@@ -25,34 +26,42 @@
25;; along with GNU Emacs; see the file COPYING. If not, write to 26;; along with GNU Emacs; see the file COPYING. If not, write to
26;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 27;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
27 28
29;;; Commentary:
30;;
28;; Introduction 31;; Introduction
29;; ============ 32;; ============
30;; This program is for lisp package authors and is used to ease 33;; This program is for lisp package authors and can be used to ease
31;; reporting of bugs. When invoked, reporter-submit-bug-report will 34;; reporting of bugs. When invoked, reporter-submit-bug-report will
32;; set up a mail buffer with the appropriate bug report address, 35;; set up a mail buffer with the appropriate bug report address,
33;; including a lisp expression the maintainer of the package can use 36;; including a lisp expression the maintainer of the package can eval
34;; to completely reproduce the environment in which the bug was 37;; to completely reproduce the environment in which the bug was
35;; observed (e.g. by using eval-last-sexp). This package is especially 38;; observed (e.g. by using eval-last-sexp). This package proved especially
36;; useful for my development of c++-mode.el, which is highly dependent 39;; useful during my development of cc-mode.el, which is highly dependent
37;; on its configuration variables. 40;; on its configuration variables.
38;; 41;;
39;; Do a "C-h f reporter-submit-bug-report" for more information. 42;; Do a "C-h f reporter-submit-bug-report" for more information.
40;; Here's an example usage: 43;; Here's an example usage:
41;; 44;;
42;; (defconst mypkg-version "9.801") 45;;(defconst mypkg-version "9.801")
43;; (defconst mypkg-maintainer-address "mypkg-help@foo.com") 46;;(defconst mypkg-maintainer-address "mypkg-help@foo.com")
44;; (defun mypkg-submit-bug-report () 47;;(defun mypkg-submit-bug-report ()
45;; "Submit via mail a bug report on mypkg" 48;; "Submit via mail a bug report on mypkg"
46;; (interactive) 49;; (interactive)
47;; (require 'reporter) 50;; (require 'reporter)
48;; (and (y-or-n-p "Do you really want to submit a report on mypkg? ") 51;; (reporter-submit-bug-report
49;; (reporter-submit-bug-report 52;; mypkg-maintainer-address
50;; mypkg-maintainer-address 53;; (concat "mypkg.el " mypkg-version)
51;; (concat "mypkg.el " mypkg-version) 54;; (list 'mypkg-variable-1
52;; (list 'mypkg-variable-1 55;; 'mypkg-variable-2
53;; 'mypkg-variable-2 56;; ;; ...
54;; ;; ... 57;; 'mypkg-variable-last)))
55;; 'mypkg-variable-last)))) 58
59;; Major differences since version 1:
60;; ==================================
61;; * More robust in the face of void variables
62;; * New interface controlling variable reporter-prompt-for-summary-p
63;; * pretty-printing of lists!
64
56 65
57;; Mailing List 66;; Mailing List
58;; ============ 67;; ============
@@ -67,7 +76,7 @@
67;; LCD Archive Entry: 76;; LCD Archive Entry:
68;; reporter|Barry A. Warsaw|bwarsaw@cen.com| 77;; reporter|Barry A. Warsaw|bwarsaw@cen.com|
69;; Customizable bug reporting of lisp programs.| 78;; Customizable bug reporting of lisp programs.|
70;; 1993/09/02 20:28:36|1.23|~/misc/reporter.el.Z| 79;; 1994/07/06 14:55:39|2.12|~/misc/reporter.el.Z|
71 80
72;;; Code: 81;;; Code:
73 82
@@ -81,6 +90,17 @@ This can either be a function symbol or a list of function symbols.
81If a list, it tries to use each specified mailer in order until an 90If a list, it tries to use each specified mailer in order until an
82existing one is found.") 91existing one is found.")
83 92
93(defvar reporter-prompt-for-summary-p nil
94 "Interface variable controlling prompting for problem summary.
95When non-nil, `reporter-submit-bug-report' prompts the user for a
96brief summary of the problem, and puts this summary on the Subject:
97line.
98
99Default behavior is to not prompt (i.e. nil). If you want reporter to
100prompt, you should `let' bind this variable to t before calling
101`reporter-submit-bug-report'. Note that this variable is not
102buffer-local so you should never just `setq' it.")
103
84 104
85;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 105;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
86;; end of user defined variables 106;; end of user defined variables
@@ -91,77 +111,176 @@ This is necessary to properly support the printing of buffer-local
91variables. Current buffer will always be the mail buffer being 111variables. Current buffer will always be the mail buffer being
92composed.") 112composed.")
93 113
114(defconst reporter-version "2.12"
115 "Reporter version number.")
116
117(defvar reporter-initial-text nil
118 "The automatically created initial text of a bug report.")
119(make-variable-buffer-local 'reporter-initial-text)
120
121
94 122
95(defun reporter-dump-variable (varsym) 123(defun reporter-dump-variable (varsym mailbuf)
96 "Pretty-print the value of the variable in symbol VARSYM." 124 ;; Pretty-print the value of the variable in symbol VARSYM. MAILBUF
97 (let ((val (save-excursion 125 ;; is the mail buffer being composed
98 (set-buffer reporter-eval-buffer) 126 (condition-case nil
99 (eval varsym))) 127 (let ((val (save-excursion
100 (sym (symbol-name varsym)) 128 (set-buffer reporter-eval-buffer)
101 (print-escape-newlines t)) 129 (symbol-value varsym)))
102 (insert " " sym " " 130 (sym (symbol-name varsym))
103 (cond 131 (print-escape-newlines t)
104 ((memq val '(t nil)) "") 132 (here (point)))
105 ((listp val) "'") 133 (insert " " sym " "
106 ((symbolp val) "'") 134 (cond
107 (t "")) 135 ((memq val '(t nil)) "")
108 (prin1-to-string val) 136 ((listp val) "'")
109 "\n"))) 137 ((symbolp val) "'")
138 (t ""))
139 (prin1-to-string val))
140 ;; clean up lists, but only if the line as printed was long
141 ;; enough to wrap
142 (if (and (listp val)
143 (< (window-width) (current-column)))
144 (save-excursion
145 (goto-char here)
146 ;; skip past the symbol name
147 (down-list 1)
148 (condition-case nil ; actual loop exit
149 (while t
150 (forward-sexp 1)
151 (insert "\n")
152 ;; if the sexp is longer than a single line then
153 ;; fill it to fill-column
154 (if (< (window-width)
155 (save-excursion
156 (forward-char -1)
157 (current-column)))
158 (let (stop)
159 (unwind-protect
160 (setq stop (point-marker))
161 (forward-line -1)
162 (fill-region (point) (progn (end-of-line)
163 (point)))
164 ;; consume extra newline left by fill-region
165 (delete-char 1)
166 (goto-char stop))
167 (set-marker stop nil)))
168 (lisp-indent-line))
169 (error nil))))
170 (insert "\n"))
171 (void-variable
172 (save-excursion
173 (set-buffer mailbuf)
174 (mail-position-on-field "X-Reporter-Void-Vars-Found")
175 (end-of-line)
176 (insert (symbol-name varsym) " ")))
177 (error (error))))
110 178
111(defun reporter-dump-state (pkgname varlist pre-hooks post-hooks) 179(defun reporter-dump-state (pkgname varlist pre-hooks post-hooks)
112 "Dump the state of the mode specific variables. 180 ;; Dump the state of the mode specific variables.
113PKGNAME contains the name of the mode as it will appear in the bug 181 ;; PKGNAME contains the name of the mode as it will appear in the bug
114report (you must explicitly concat any version numbers). 182 ;; report (you must explicitly concat any version numbers).
115 183
116VARLIST is the list of variables to dump. Each element in VARLIST can 184 ;; VARLIST is the list of variables to dump. Each element in
117be a variable symbol, or a cons cell. If a symbol, this will be 185 ;; VARLIST can be a variable symbol, or a cons cell. If a symbol,
118passed to `reporter-dump-variable' for insertion into the mail buffer. 186 ;; this will be passed to `reporter-dump-variable' for insertion
119If a cons cell, the car must be a variable symbol and the cdr must be 187 ;; into the mail buffer. If a cons cell, the car must be a variable
120a function which will be `funcall'd with the symbol. Use this to write 188 ;; symbol and the cdr must be a function which will be `funcall'd
121your own custom variable value printers for specific variables. 189 ;; with arguments the symbol and the mail buffer being composed. Use
122 190 ;; this to write your own custom variable value printers for
123Note that the global variable `reporter-eval-buffer' will be bound to 191 ;; specific variables.
124the buffer in which `reporter-submit-bug-report' was invoked. If you 192
125want to print the value of a buffer local variable, you should wrap 193 ;; Note that the global variable `reporter-eval-buffer' will be bound to
126the `eval' call in your custom printer inside a `set-buffer' (and 194 ;; the buffer in which `reporter-submit-bug-report' was invoked. If you
127probably a `save-excursion'). `reporter-dump-variable' handles this 195 ;; want to print the value of a buffer local variable, you should wrap
128properly. 196 ;; the `eval' call in your custom printer inside a `set-buffer' (and
129 197 ;; probably a `save-excursion'). `reporter-dump-variable' handles this
130PRE-HOOKS is run after the emacs-version and PKGNAME are inserted, but 198 ;; properly.
131before the VARLIST is dumped. POST-HOOKS is run after the VARLIST is 199
132dumped." 200 ;; PRE-HOOKS is run after the emacs-version and PKGNAME are inserted, but
201 ;; before the VARLIST is dumped. POST-HOOKS is run after the VARLIST is
202 ;; dumped.
133 (let ((buffer (current-buffer))) 203 (let ((buffer (current-buffer)))
134 (set-buffer buffer) 204 (set-buffer buffer)
135 (insert "Emacs : " (emacs-version) "\nPackage: " pkgname "\n") 205 (insert "Emacs : " (emacs-version) "\n")
206 (and pkgname
207 (insert "Package: " pkgname "\n"))
136 (run-hooks 'pre-hooks) 208 (run-hooks 'pre-hooks)
137 (insert "\ncurrent state:\n==============\n(setq\n") 209 (if (not varlist)
138 (mapcar 210 nil
139 (function 211 (insert "\ncurrent state:\n==============\n")
140 (lambda (varsym-or-cons-cell) 212 ;; create an emacs-lisp-mode buffer to contain the output, which
141 (let ((varsym (or (car-safe varsym-or-cons-cell) 213 ;; we'll later insert into the mail buffer
142 varsym-or-cons-cell)) 214 (condition-case fault
143 (printer (or (cdr-safe varsym-or-cons-cell) 215 (let ((mailbuf (current-buffer))
144 'reporter-dump-variable))) 216 (elbuf (get-buffer-create " *tmp-reporter-buffer*")))
145 (funcall printer varsym) 217 (save-excursion
146 ))) 218 (set-buffer elbuf)
147 varlist) 219 (emacs-lisp-mode)
148 (insert " )\n") 220 (erase-buffer)
221 (insert "(setq\n")
222 (lisp-indent-line)
223 (mapcar
224 (function
225 (lambda (varsym-or-cons-cell)
226 (let ((varsym (or (car-safe varsym-or-cons-cell)
227 varsym-or-cons-cell))
228 (printer (or (cdr-safe varsym-or-cons-cell)
229 'reporter-dump-variable)))
230 (funcall printer varsym mailbuf)
231 )))
232 varlist)
233 (insert ")\n")
234 (beginning-of-defun)
235 (indent-sexp))
236 (insert-buffer elbuf))
237 (error
238 (insert "State could not be dumped due to the following error:\n\n"
239 (format "%s" fault)
240 "\n\nYou should still send this bug report."))))
149 (run-hooks 'post-hooks) 241 (run-hooks 'post-hooks)
150 )) 242 ))
151 243
244
245(defun reporter-calculate-separator ()
246 ;; returns the string regexp matching the mail separator
247 (save-excursion
248 (re-search-forward
249 (concat
250 "^\\(" ;beginning of line
251 (mapconcat
252 'identity
253 (list "[\t ]*" ;simple SMTP form
254 "-+" ;mh-e form
255 (regexp-quote
256 mail-header-separator)) ;sendmail.el form
257 "\\|") ;or them together
258 "\\)$") ;end of line
259 nil
260 'move) ;search for and move
261 (buffer-substring (match-beginning 0) (match-end 0))))
262
263;;;###autoload
152(defun reporter-submit-bug-report 264(defun reporter-submit-bug-report
153 (address pkgname varlist &optional pre-hooks post-hooks salutation) 265 (address pkgname varlist &optional pre-hooks post-hooks salutation)
154 "Submit a bug report via mail. 266 ;; Submit a bug report via mail.
267
268 ;; ADDRESS is the email address for the package's maintainer. PKGNAME is
269 ;; the name of the mode (you must explicitly concat any version numbers).
270 ;; VARLIST is the list of variables to dump (see `reporter-dump-state'
271 ;; for details). Optional PRE-HOOKS and POST-HOOKS are passed to
272 ;; `reporter-dump-state'. Optional SALUTATION is inserted at the top of the
273 ;; mail buffer, and point is left after the salutation.
155 274
156ADDRESS is the email address for the package's maintainer. PKGNAME is 275 ;; This function will prompt for a summary if
157the name of the mode (you must explicitly concat any version numbers). 276 ;; reporter-prompt-for-summary-p is non-nil.
158VARLIST is the list of variables to dump (do a `\\[describe-function] reporter-dump-state'
159for details). Optional PRE-HOOKS and POST-HOOKS are passed to
160`reporter-dump-state'. Optional SALUTATION is inserted at the top of the
161mail buffer, and point is left after the saluation.
162 277
163The mailer used is described in the variable `reporter-mailer'." 278 ;; The mailer used is described in the variable `reporter-mailer'.
164 (let ((reporter-eval-buffer (current-buffer)) 279 (let ((reporter-eval-buffer (current-buffer))
280 final-resting-place
281 after-sep-pos
282 (problem (and reporter-prompt-for-summary-p
283 (read-string "(Very) brief summary of problem: ")))
165 (mailbuf 284 (mailbuf
166 (progn 285 (progn
167 (call-interactively 286 (call-interactively
@@ -186,34 +305,44 @@ The mailer used is described in the variable `reporter-mailer'."
186 (goto-char (point-min)) 305 (goto-char (point-min))
187 ;; different mailers use different separators, some may not even 306 ;; different mailers use different separators, some may not even
188 ;; use m-h-s, but sendmail.el stuff must have m-h-s bound. 307 ;; use m-h-s, but sendmail.el stuff must have m-h-s bound.
189 (let ((mail-header-separator 308 (let ((mail-header-separator (reporter-calculate-separator)))
190 (save-excursion
191 (re-search-forward
192 (concat
193 "^\\(" ;beginning of line
194 (mapconcat
195 'identity
196 (list "[\t ]*" ;simple SMTP form
197 "-+" ;mh-e form
198 (regexp-quote
199 mail-header-separator)) ;sendmail.el form
200 "\\|") ;or them together
201 "\\)$") ;end of line
202 nil
203 'move) ;search for and move
204 (buffer-substring (match-beginning 0) (match-end 0)))))
205 (mail-position-on-field "to") 309 (mail-position-on-field "to")
206 (insert address) 310 (insert address)
207 (mail-position-on-field "subject") 311 ;; insert problem summary if available
208 (insert "Report on package " pkgname) 312 (if (and reporter-prompt-for-summary-p problem pkgname)
313 (progn
314 (mail-position-on-field "subject")
315 (insert pkgname "; " problem)))
209 (re-search-forward mail-header-separator (point-max) 'move) 316 (re-search-forward mail-header-separator (point-max) 'move)
210 (forward-line 1) 317 (forward-line 1)
318 (setq after-sep-pos (point))
211 (and salutation (insert "\n" salutation "\n\n")) 319 (and salutation (insert "\n" salutation "\n\n"))
212 (set-mark (point)) ;user should see mark change 320 (unwind-protect
213 (insert "\n\n") 321 (progn
214 (reporter-dump-state pkgname varlist pre-hooks post-hooks) 322 (setq final-resting-place (point-marker))
215 (exchange-point-and-mark)) 323 (insert "\n\n")
216 (let* ((sendkey "C-c C-c") ;can this be generalized like below? 324 (reporter-dump-state pkgname varlist pre-hooks post-hooks)
325 (goto-char final-resting-place))
326 (set-marker final-resting-place nil)))
327
328 ;; save initial text and set up the `no-empty-submission' hook.
329 ;; This only works for mailers that support mail-send-hook,
330 ;; e.g. sendmail.el
331 (if (fboundp 'add-hook)
332 (progn
333 (save-excursion
334 (goto-char (point-max))
335 (skip-chars-backward " \t\n")
336 (setq reporter-initial-text
337 (buffer-substring after-sep-pos (point))))
338 (make-variable-buffer-local 'mail-send-hook)
339 (add-hook 'mail-send-hook 'reporter-bug-hook)))
340
341 ;; minibuf message
342 ;; C-c C-c can't be generalized because they don't always run
343 ;; mail-send-and-exit. E.g. vm-mail-send-and-exit. I don't want
344 ;; to hard code these.
345 (let* ((sendkey "C-c C-c")
217 (killkey-whereis (where-is-internal 'kill-buffer nil t)) 346 (killkey-whereis (where-is-internal 'kill-buffer nil t))
218 (killkey (if killkey-whereis 347 (killkey (if killkey-whereis
219 (key-description killkey-whereis) 348 (key-description killkey-whereis)
@@ -222,7 +351,25 @@ The mailer used is described in the variable `reporter-mailer'."
222 sendkey killkey)) 351 sendkey killkey))
223 )) 352 ))
224 353
225;; this is useful 354(defun reporter-bug-hook ()
355 ;; prohibit sending mail if empty bug report
356 (let ((after-sep-pos
357 (save-excursion
358 (beginning-of-buffer)
359 (re-search-forward (reporter-calculate-separator) (point-max) 'move)
360 (forward-line 1)
361 (point))))
362 (save-excursion
363 (goto-char (point-max))
364 (skip-chars-backward " \t\n")
365 (if (and (= (- (point) after-sep-pos)
366 (length reporter-initial-text))
367 (string= (buffer-substring after-sep-pos (point))
368 reporter-initial-text))
369 (error "Empty bug report cannot be sent."))
370 )))
371
372
226(provide 'reporter) 373(provide 'reporter)
227 374
228;;; reporter.el ends here 375;;; reporter.el ends here