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