Add an overview of the tools bundle
[latex2e.git] / base / latexbug.el
blobb29766385d9a1cfb69be139e38d64d2d048879ed
1 ;;; latexbug.el
2 ;;;
3 ;;; Version 0: `test of concept'
4 ;;; Don't look to closely at my lisp coding style...
5 ;;;
6 ;;; David Carlisle
7 ;;; Version 0.1 1994/11/23
8 ;;; Version 0.2 1994/12/12
9 ;;; Version 0.3 1995/03/17
10 ;;; Version 0.4 1995/09/21
11 ;;; Version 0.5 1995/10/17
12 ;;; Version 0.6 1997/07/16
13 ;;; Version 0.7 1997/12/17
14 ;;; Version 0.8 1999/01/07
15 ;;;
16 ;;;
17 ;;; LOADING
18 ;;;;;;;;;;;
19 ;;;
20 ;;; To use this code, place the file in a directory searched by lisp
21 ;;; Add
22 ;;;
23 ;;; (autoload 'report-latex-bug "latexbug"
24 ;;; "LaTeX bug report generator" t)
25 ;;;
26 ;;; to your .emacs file (without the ;;;).
27 ;;;
28 ;;; Then if the impossible happens and you discover a bug in LaTeX,
29 ;;; or wish to suggest a change to LaTeX, type
30 ;;; M-x report-latex-bug
31 ;;;
32 ;;; and follow the instructions.
33 ;;;
34 ;;; A file latexbug.cfg can be used to customise
35 ;;; latexbug.tex as described in the comments in latexbug.tex.
36 ;;; or you can customise in your .emacs, as shown below.
37 ;;;
38 ;;; CUSTOMISATION
39 ;;;;;;;;;;;;;;;;;;
40 ;;;
41 ;;; The following variables may be set in your .emacs to customise this
42 ;;; file.
43 ;;;
44 ;;; (setq ltxbug-name "David Carlisle") ; your name
45 ;;; (setq ltxbug-address "dpc@,,,") ; your email address
46 ;;; If these two are not set here, or in the latexbug.cfg
47 ;;; file. emacs will prompt for the values. The prompt
48 ;;; will suggest default values based on standard emacs variables
49 ;;; user-full-name and user-mail-address.
50 ;;;
51 ;;; (setq ltxbug-mail-headers "...") ; additional mail headers.
52 ;;; For example (setq ltxbug-mail-headers "FCC: ~/Mail/sent")
53 ;;; To log outgoing mail in a `sent' file.
54 ;;;
55 ;;; (setq ltxbug-latex-command "...") ; latex command
56 ;;; Set this if LaTeX is not called latex, eg it may be latex2e.
57 ;;;
58 ;;;
59 ;;; Perhaps I should have based this on gnat's send-pr.el but it seemed
60 ;;; easier to write it from scratch to work in latexbug.tex at the
61 ;;; required points.
62 ;;;
63 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
65 (require 'sendmail)
67 (defvar ltxbug-latex-command "latex"
68 "Command name for Standard LaTeX (LaTeX2e)")
70 (defvar ltxbug-directory nil
71 "Directory in which to run LaTeX, should end with slash.
72 Default, nil, means inherit directory from current buffer.")
74 (defvar user-full-name nil); just needed on ancient emacs
75 (defvar ltxbug-name nil
76 "Your name.
77 If this is nil, will be prompted if not set in latexbug.cfg.")
79 (defvar user-mail-address nil); just needed on ancient emacs
80 (defvar ltxbug-address nil
81 "Your email-address.
82 If this is nil, will be prompted if not set in latexbug.cfg.")
84 (defvar ltxbug-mail-headers ""
85 "Extra mail headers that will be added to the mail message.
86 This is in addition to `To' and `Subject'.")
88 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
90 (defvar ltxbug-categories
91 '(("latex") ("tools") ("graphics")
92 ("mfnfss") ("psnfss") ("amslatex") ("babel") ("expl3") ("cyrillic"))
93 "Valid GNATS categories")
96 (defun report-latex-bug ()
97 "LaTeX bug report generator"
98 (interactive)
100 ;; Locally turn off transient mark mode.
101 (let ((transient-mark-mode nil)
102 (current-default-directory default-directory))
104 ;; First produce one large window for the main message
105 ;; and a smaller help window below.
106 (delete-other-windows)
107 ;; (setq ltxbug-msg (switch-to-buffer "*latex-bugs*")); not emacs18
108 (switch-to-buffer
109 (setq ltxbug-msg (get-buffer-create "*latex-bugs*")))
110 (erase-buffer)
111 (setq default-directory
112 (or ltxbug-directory current-default-directory))
113 (setq major-mode 'ltxbug)
114 (setq mode-name "LaTeX Bug Report")
115 (use-local-map ltxbug-map)
116 (message "Running latex on latexbug.tex ....")
117 (split-window-vertically
118 ;; -13 ;; old emacs's can't do this
119 (- (window-height) 13))
120 (switch-to-buffer-other-window
121 (setq ltxbug-help (get-buffer-create "latexbugs help")))
123 ;; Initially fill the message buffer with the output from running
124 ;; latexbug.tex.
125 (erase-buffer)
127 ;; Use shell-command not start-process here so shell variables are
128 ;; initialised before calling LaTeX.
129 ;; Hope that is enough \\ to keep all the different shells happy...
130 ;; {} replaced by \\{\\} in version 0.4 (fix for latex/1675)
131 ;; Use \@@input (v0.5)
132 (shell-command (concat
133 ltxbug-latex-command
134 " \\\\nonstopmode\\\\makeatletter\
135 \\\\def\\\\batch\\{\\}\\\\@@input latexbug ") t)
136 (switch-to-buffer-other-window ltxbug-msg)
137 (goto-char (point-min))
139 ;; Change header to mention this latexbug.el file.
140 (if (re-search-forward "!" (point-max) t)
141 (ltxbug-error)
142 ;; else
143 (ltxbug-do-report))))
147 (defun ltxbug-do-report ()
148 (erase-buffer)
150 ;; Grab the template produced by latexbug.tex
151 (insert-file "latexbug.msg")
153 ;; Change header to mention this latexbug.el file.
154 (goto-char (point-min))
155 (re-search-forward "\\(by latexbug.\\)\\(tex\\)" (point-max) t)
156 (replace-match "\\1el")
158 ;; Grab email address into mail field.
159 (re-search-forward "Re.*email to \\(.*\\)[^Z]*=$" (point-max) t)
161 ;; Put the synopsis template into the Subject field.
162 ;; Add the delimiter used by the mail-send function.
163 (goto-char (point-min))
164 (let ((temp
165 (concat "To: "
166 (buffer-substring (match-beginning 1) (match-end 1)) "
167 Subject: < SYNOPSIS >
169 ltxbug-mail-headers
170 (if (not (equal "" ltxbug-mail-headers)) "
172 "--text follows this line--
173 " )))
175 ;; Remove the rest of the banner from latexbug.tex
176 (goto-char (point-min))
177 (delete-region (match-beginning 0) (match-end 0))
179 ;; insert the mail headers
180 (insert temp))
183 ;; Get the required category using minibuffer completion.
184 (set-buffer ltxbug-help)
185 (erase-buffer)
186 (insert "
187 Several categories of files are supported,
188 corresponding to directories in the standard LaTeX distribution:
190 latex: The `base' format, and standard classes only (base).
191 tools: Packages supported by the LaTeX3 project team (tools).
192 graphics: The color and graphics packages (graphics).
193 mfnfss: Packages for using some MetaFont fonts (mfnfss).
194 psnfss: Packages for using PostScript fonts LaTeX (psnfss).
195 amslatex: AMS supported Classes and Packages (amsfonts and amslatex).
196 babel: Packages supporting many different languages (babel).
197 expl3: Experimental packages for TeX programmers (expl3).
198 cyrillic: Packages for using Cyrillic fonts (cyrillic).
200 (let* ((completion-ignore-case t)
201 (cat (completing-read "Which Category ? "
202 ltxbug-categories nil t )))
203 (set-buffer "*latex-bugs*")
204 (ltxbug-replace "< CATEGORY >" (if (equal cat "") "latex" cat)))
206 ;; Get the synopsis, make sure it is non empty, and not too long.
207 (set-buffer ltxbug-help)
208 (erase-buffer)
209 (insert "
210 Please enter a One line Synopsis of the report.
211 This should be < 50 characters.
213 This text will be used as the mail header on all
214 subsequent correspondence. Please use informative strings.
215 For example: \\mathit generates error in foobar environment
216 rather than just `LaTeX Bug' or similar strings.
218 (set-buffer ltxbug-msg)
219 (let ((syn (read-from-minibuffer "Synopsis ? " )))
220 (while (or (equal syn "") (> (length syn) 50))
221 (setq syn
222 (read-from-minibuffer "Synopsis (0 < length < 50) ? " syn)))
223 (set-buffer "*latex-bugs*")
224 (ltxbug-replace "< SYNOPSIS >" syn))
226 ;; If latexbug.cfg has not already defined the name
227 ;; grab it from minibuffer
228 (goto-char (point-min))
229 (if (re-search-forward "< ENTER YOUR NAME >" (point-max) t)
230 (if ltxbug-name
231 (ltxbug-replace "< ENTER YOUR NAME >" ltxbug-name)
232 ;; else
233 (set-buffer ltxbug-help)
234 (erase-buffer)
235 (insert "
236 Please enter Your Name
238 (set-buffer ltxbug-msg)
239 (let ((temp (read-from-minibuffer "Your Name ? " user-full-name)))
240 (set-buffer "*latex-bugs*")
241 (ltxbug-replace "< ENTER YOUR NAME >" temp))))
243 ;; If latexbug.cfg has not already defined the email address
244 ;; grab it from minibuffer
245 (goto-char (point-min))
246 (if (re-search-forward "< ENTER YOUR EMAIL ADDRESS >" (point-max) t)
247 (if ltxbug-address
248 (ltxbug-replace "< ENTER YOUR EMAIL ADDRESS >" ltxbug-address)
249 ;; else
250 (set-buffer ltxbug-help)
251 (erase-buffer)
252 (insert "
253 Please enter Your email address.
255 (set-buffer ltxbug-msg)
256 (let ((temp (read-from-minibuffer "Your email address ? "
257 user-mail-address)))
258 (set-buffer "*latex-bugs*")
259 (ltxbug-replace "< ENTER YOUR EMAIL ADDRESS >" temp))))
261 ;; Grab file name.
262 ;; If this is empty, suggest changing the >Class
263 (set-buffer ltxbug-help)
264 (erase-buffer)
265 (insert "
266 A bug report should be accompanied by a test file
267 and a the log that the test generates.
269 If a test file is not appropriate for this report
270 Just hit <return>
272 Otherwise please specify the file to include.
274 (set-buffer ltxbug-msg)
275 (let ((temp (read-file-name "Test file ? " nil "" t)))
276 (if (equal temp "")
277 (progn
278 (ltxbug-update-field
279 "Class"
280 '(("sw-bug")("doc-bug")("change-request"))
282 You have not offered a test file.
284 Perhaps that this is not a bug report.
285 The default class for messages is sw-bug.
287 Possible classes of messages are:
288 sw-bug: Message reporting a Bug in the software.
289 doc-bug: Message reporting an error in the documentation.
290 change-request: Message requesting a change to some LaTeX feature.")
291 (re-search-forward ">How-to-repeat")
292 (delete-region (match-beginning 0) (point-max)))
293 ;; else
294 (set-buffer ltxbug-msg)
295 (ltxbug-replace " < TEST FILE HERE " "")
296 (insert-file temp)
297 (let ((lines 0))
298 (while (re-search-forward "\n" (mark) t)
299 (setq lines (+ lines 1)))
300 (if (> lines 60)
301 (progn
302 (set-buffer ltxbug-help)
303 (erase-buffer)
304 (insert
305 (format "%s%d%s" "
306 !!!!
307 Your test file is " lines " lines long!!!
309 Test files should be as short as possible, while still showing
310 the behaviour. Please try to keep the file below 60 lines.
312 (set-buffer ltxbug-msg))))
313 (let* ((log1
314 (concat
315 (substring temp 0 (string-match "\\.[^\\.]*$" temp))
316 ".log"))
317 (log (read-file-name "Log file ? " "" log1 t log1)))
318 (if (equal log "")
319 (message "WHY NO LOG ???")
320 (ltxbug-replace " < LOG FROM TEST FILE HERE >" "")
321 (insert-file log)))))
323 ;; Prompt for the message text.
324 (set-buffer ltxbug-help)
325 (erase-buffer)
326 (insert "
327 Complete your bug report by giving the full description
328 below the `Description of bug:' header.
330 There are other database fields you may wish to add,
331 type C-c C-f to change or add an additional field.
333 Once the report is complete, type C-c C-c to send the message.
335 A saved copy of the report will be in the file
336 latexbug.msg.
338 (switch-to-buffer ltxbug-msg)
339 (ltxbug-replace " < ENTER BUG REPORT HERE >" "")
340 (auto-fill-mode 1)
341 (setq fill-column 72))
344 (defun ltxbug-error ()
345 (set-buffer ltxbug-help)
346 (erase-buffer)
347 (insert "
348 LaTeX did not succesfully produce a bug report template."))
350 (defun ltxbug-save-and-send ()
351 (interactive)
352 (write-file "latexbug.msg")
353 (mail-send-and-exit nil))
356 (defun ltxbug-replace (a b)
357 "Replace the regexp a by the string b everywhere in the current buffer"
358 (goto-char (point-min))
359 (while (re-search-forward a (point-max) t)
360 (replace-match b t t)))
362 (defvar ltxbug-map (make-sparse-keymap)
363 "Local keymap used in LaTeX bug buffer.")
365 (define-key ltxbug-map "\C-c\C-c" 'ltxbug-save-and-send)
366 (define-key ltxbug-map "\C-c\C-f" 'ltxbug-oneline-field)
369 (defun ltxbug-update-field (field values help)
370 "Update FIELD using completion list VALUES and help text HELP.
371 First entry in VALUES is the default."
372 (interactive)
373 (set-buffer ltxbug-help)
374 (erase-buffer)
375 (insert help)
376 (goto-char (point-min))
377 (set-buffer ltxbug-msg)
378 (goto-char (point-min))
379 (let ((temp ""))
380 (if (re-search-forward
381 (concat"\n>" field ":\\( *\\)\\(.*\\)$") (point-max) t)
382 ;; if field already there
383 (progn
384 (setq temp (buffer-substring (match-beginning 2) (match-end 2)))
385 (delete-region (match-beginning 1) (match-end 2)))
386 ;; else
387 (re-search-forward ">Category:.*$")
388 (insert (concat "\n>" field ":")))
389 (insert " ")
390 (let ((temp2
391 (completing-read (concat field " ? ") values nil t temp)))
392 (insert (if (equal temp2 "")
393 (car(car values)) temp2)))))
396 (defun ltxbug-responsible ()
397 (interactive)
398 (ltxbug-update-field
399 "Responsible"
400 ;; Alphabetical order, which makes Alan the default...
401 '(("alan")("chris")("david")("frank")("johannes")
402 ("michael")("rainer"))
404 You may set the >Responsible field to a particular person.
405 **Do not do this unless you have very good reason.**
406 We may not appreciate having jobs allocated to us in this way:-)
407 The possible values are:
408 alan (Alan Jeffrey)
409 chris (Chris Rowley)
410 david (David Carlisle)
411 frank (Frank Mittelbach)
412 johannes (Johannes Braams)
413 michael (Michael Downes)
414 rainer (Rainer Schoepf)
417 (defun ltxbug-confidential ()
418 (interactive)
419 (ltxbug-update-field
420 "Confidential"
421 '(("no")("yes"))
423 You may set the >Confidential field to yes.
425 The report database is publicly searchable.
426 See bugs.txt for details.
427 Reports marked Confidential will not be made public.
428 Possible values:
429 no The default. Report may be made public.
430 yes Report should only be seen by LaTeX maintainers.
434 (defun ltxbug-priority ()
435 (interactive)
436 (ltxbug-update-field
437 "Priority"
438 '(("low")("medium")("high"))
440 Change the priority of the report from `high'
441 Possible values:
443 medium
444 high
447 (defun ltxbug-severity ()
448 (interactive)
449 (ltxbug-update-field
450 "Severity"
451 '(("non-critical")("serious")("critical"))
453 Classify the severity of the problem.'
454 Possible values:
455 non-critical
456 serious
457 critical
460 (defun ltxbug-class ()
461 (interactive)
462 (ltxbug-update-field
463 "Class"
464 '(("sw-bug")("doc-bug")("change-request"))
466 Classify the type of report.
467 Possible values:
468 sw-bug: Message reporting a bug in the software.
469 doc-bug: Message reporting an error in the documentation.
470 change-request: Message requesting a change to some LaTeX feature.
473 (defun ltxbug-window-setup ()
474 (interactive)
475 (delete-other-windows)
476 (split-window-vertically -13)
477 (switch-to-buffer-other-window ltxbug-help))
479 (defun ltxbug-oneline-field ()
480 (interactive)
481 (ltxbug-window-setup)
482 (erase-buffer)
483 (insert "
484 You may wish to add or alter the following fields:
485 Class Class of this report.
486 Confidential Confidential (or not).
487 Responsible Assign to a member of the LaTeX maintenance team
488 Severity Severity of the bug.
489 Priority Priority of the report.
491 (set-buffer ltxbug-msg)
492 (let* ((completion-ignore-case t)
493 (field (completing-read "Which field ? "
494 '(("Class")("Confidential")("Priority")("Severity")
495 ("Responsible"))
496 nil t)))
497 (cond
498 ((equal field "Class") (ltxbug-class))
499 ((equal field "Confidential") (ltxbug-confidential))
500 ((equal field "Responsible") (ltxbug-responsible))
501 ((equal field "Severity") (ltxbug-severity))
502 ((equal field "Priority") (ltxbug-priority)))))