diff options
| author | Dave Love | 2000-02-20 18:25:57 +0000 |
|---|---|---|
| committer | Dave Love | 2000-02-20 18:25:57 +0000 |
| commit | 2505742bda6f24068d16e7cf02329e15049fd2ea (patch) | |
| tree | e653fceba6f7ee483b25ebddded9a5ece87b7f13 /lisp | |
| parent | 329eed9f6e44972161dd9cce7a62ca2e68e5c700 (diff) | |
| download | emacs-2505742bda6f24068d16e7cf02329e15049fd2ea.tar.gz emacs-2505742bda6f24068d16e7cf02329e15049fd2ea.zip | |
Don't require emacsbug at top level.
(lm-get-header-re): Defun, not defsubst.
(lm-get-package-name): Defun, not defsubst. Simplify.
(lm-version): Doc fix. Simplify.
(lm-header, lm-header-multiline, lm-header-multiline, lm-summary)
(lm-crack-address, lm-last-modified-date, lm-commentary)
(lm-verify, lm-synopsis): Simplify.
(lm-report-bug): Require emacsbug. Use compose-mail.
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/emacs-lisp/lisp-mnt.el | 298 |
1 files changed, 133 insertions, 165 deletions
diff --git a/lisp/emacs-lisp/lisp-mnt.el b/lisp/emacs-lisp/lisp-mnt.el index 3e15384d028..0fac9d944ae 100644 --- a/lisp/emacs-lisp/lisp-mnt.el +++ b/lisp/emacs-lisp/lisp-mnt.el | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | ;;; lisp-mnt.el --- minor mode for Emacs Lisp maintainers | 1 | ;;; lisp-mnt.el --- minor mode for Emacs Lisp maintainers |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 1992, 1994, 1997 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 1992, 1994, 1997, 2000 Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | ;; Author: Eric S. Raymond <esr@snark.thyrsus.com> | 5 | ;; Author: Eric S. Raymond <esr@snark.thyrsus.com> |
| 6 | ;; Maintainer: Eric S. Raymond <esr@snark.thyrsus.com> | 6 | ;; Maintainer: Eric S. Raymond <esr@snark.thyrsus.com> |
| @@ -113,8 +113,6 @@ | |||
| 113 | 113 | ||
| 114 | ;;; Code: | 114 | ;;; Code: |
| 115 | 115 | ||
| 116 | (require 'emacsbug) | ||
| 117 | |||
| 118 | ;;; Variables: | 116 | ;;; Variables: |
| 119 | 117 | ||
| 120 | (defgroup lisp-mnt nil | 118 | (defgroup lisp-mnt nil |
| @@ -155,7 +153,7 @@ then $identifier: doc string $ is used by GNU ident(1)" | |||
| 155 | 153 | ||
| 156 | ;; These functions all parse the headers of the current buffer | 154 | ;; These functions all parse the headers of the current buffer |
| 157 | 155 | ||
| 158 | (defsubst lm-get-header-re (header &optional mode) | 156 | (defun lm-get-header-re (header &optional mode) |
| 159 | "Return regexp for matching HEADER. | 157 | "Return regexp for matching HEADER. |
| 160 | If called with optional MODE and with value `section', | 158 | If called with optional MODE and with value `section', |
| 161 | return section regexp instead." | 159 | return section regexp instead." |
| @@ -164,7 +162,7 @@ return section regexp instead." | |||
| 164 | (t | 162 | (t |
| 165 | (concat lm-header-prefix header ":[ \t]*")))) | 163 | (concat lm-header-prefix header ":[ \t]*")))) |
| 166 | 164 | ||
| 167 | (defsubst lm-get-package-name () | 165 | (defun lm-get-package-name () |
| 168 | "Return package name by looking at the first line." | 166 | "Return package name by looking at the first line." |
| 169 | (save-excursion | 167 | (save-excursion |
| 170 | (goto-char (point-min)) | 168 | (goto-char (point-min)) |
| @@ -172,8 +170,7 @@ return section regexp instead." | |||
| 172 | (progn (goto-char (match-end 0)) | 170 | (progn (goto-char (match-end 0)) |
| 173 | (looking-at "\\([^\t ]+\\)") | 171 | (looking-at "\\([^\t ]+\\)") |
| 174 | (match-end 1))) | 172 | (match-end 1))) |
| 175 | (buffer-substring-no-properties (match-beginning 1) (match-end 1)) | 173 | (match-string-no-properties 1)))) |
| 176 | ))) | ||
| 177 | 174 | ||
| 178 | (defun lm-section-mark (header &optional after) | 175 | (defun lm-section-mark (header &optional after) |
| 179 | "Return the buffer location of a given section start marker. | 176 | "Return the buffer location of a given section start marker. |
| @@ -186,8 +183,7 @@ If AFTER is non-nil, return the location of the next line." | |||
| 186 | (progn | 183 | (progn |
| 187 | (beginning-of-line) | 184 | (beginning-of-line) |
| 188 | (if after (forward-line 1)) | 185 | (if after (forward-line 1)) |
| 189 | (point)) | 186 | (point)))))) |
| 190 | nil)))) | ||
| 191 | 187 | ||
| 192 | (defsubst lm-code-mark () | 188 | (defsubst lm-code-mark () |
| 193 | "Return the buffer location of the `Code' start marker." | 189 | "Return the buffer location of the `Code' start marker." |
| @@ -209,8 +205,7 @@ If AFTER is non-nil, return the location of the next line." | |||
| 209 | ;; RCS ident likes format "$identifier: data$" | 205 | ;; RCS ident likes format "$identifier: data$" |
| 210 | (looking-at "\\([^$\n]+\\)") | 206 | (looking-at "\\([^$\n]+\\)") |
| 211 | (match-end 1)) | 207 | (match-end 1)) |
| 212 | (buffer-substring-no-properties (match-beginning 1) (match-end 1)) | 208 | (match-string-no-properties 1)))) |
| 213 | nil))) | ||
| 214 | 209 | ||
| 215 | (defun lm-header-multiline (header) | 210 | (defun lm-header-multiline (header) |
| 216 | "Return the contents of the header named HEADER, with continuation lines. | 211 | "Return the contents of the header named HEADER, with continuation lines. |
| @@ -221,20 +216,14 @@ The returned value is a list of strings, one per line." | |||
| 221 | (when res | 216 | (when res |
| 222 | (setq res (list res)) | 217 | (setq res (list res)) |
| 223 | (forward-line 1) | 218 | (forward-line 1) |
| 224 | |||
| 225 | (while (and (looking-at (concat lm-header-prefix "[\t ]+")) | 219 | (while (and (looking-at (concat lm-header-prefix "[\t ]+")) |
| 226 | (progn | 220 | (progn |
| 227 | (goto-char (match-end 0)) | 221 | (goto-char (match-end 0)) |
| 228 | (looking-at "\\(.*\\)")) | 222 | (looking-at "\\(.*\\)")) |
| 229 | (match-end 1)) | 223 | (match-end 1)) |
| 230 | (setq res (cons (buffer-substring-no-properties | 224 | (setq res (cons (match-string-no-properties 1) res)) |
| 231 | (match-beginning 1) | 225 | (forward-line 1))) |
| 232 | (match-end 1)) | 226 | res))) |
| 233 | res)) | ||
| 234 | (forward-line 1)) | ||
| 235 | ) | ||
| 236 | res | ||
| 237 | ))) | ||
| 238 | 227 | ||
| 239 | ;; These give us smart access to the header fields and commentary | 228 | ;; These give us smart access to the header fields and commentary |
| 240 | 229 | ||
| @@ -253,12 +242,10 @@ The returned value is a list of strings, one per line." | |||
| 253 | "Return the one-line summary of file FILE, or current buffer if FILE is nil." | 242 | "Return the one-line summary of file FILE, or current buffer if FILE is nil." |
| 254 | (lm-with-file file | 243 | (lm-with-file file |
| 255 | (goto-char (point-min)) | 244 | (goto-char (point-min)) |
| 256 | (if (and | 245 | (if (and (looking-at lm-header-prefix) |
| 257 | (looking-at lm-header-prefix) | 246 | (progn (goto-char (match-end 0)) |
| 258 | (progn (goto-char (match-end 0)) | 247 | (looking-at "[^ ]+[ \t]+--+[ \t]+\\(.*\\)"))) |
| 259 | (looking-at "[^ ]+[ \t]+--+[ \t]+\\(.*\\)"))) | 248 | (let ((summary (match-string-no-properties 1))) |
| 260 | (let ((summary (buffer-substring-no-properties (match-beginning 1) | ||
| 261 | (match-end 1)))) | ||
| 262 | ;; Strip off -*- specifications. | 249 | ;; Strip off -*- specifications. |
| 263 | (if (string-match "[ \t]*-\\*-.*-\\*-" summary) | 250 | (if (string-match "[ \t]*-\\*-.*-\\*-" summary) |
| 264 | (substring summary 0 (match-beginning 0)) | 251 | (substring summary 0 (match-beginning 0)) |
| @@ -268,11 +255,11 @@ The returned value is a list of strings, one per line." | |||
| 268 | "Split up an email address X into full name and real email address. | 255 | "Split up an email address X into full name and real email address. |
| 269 | The value is a cons of the form (FULLNAME . ADDRESS)." | 256 | The value is a cons of the form (FULLNAME . ADDRESS)." |
| 270 | (cond ((string-match "\\(.+\\) [(<]\\(\\S-+@\\S-+\\)[>)]" x) | 257 | (cond ((string-match "\\(.+\\) [(<]\\(\\S-+@\\S-+\\)[>)]" x) |
| 271 | (cons (substring x (match-beginning 1) (match-end 1)) | 258 | (cons (match-string 1 x) |
| 272 | (substring x (match-beginning 2) (match-end 2)))) | 259 | (match-string 2 x))) |
| 273 | ((string-match "\\(\\S-+@\\S-+\\) [(<]\\(.*\\)[>)]" x) | 260 | ((string-match "\\(\\S-+@\\S-+\\) [(<]\\(.*\\)[>)]" x) |
| 274 | (cons (substring x (match-beginning 2) (match-end 2)) | 261 | (cons (match-string 2 x) |
| 275 | (substring x (match-beginning 1) (match-end 1)))) | 262 | (match-string 1 x))) |
| 276 | ((string-match "\\S-+@\\S-+" x) | 263 | ((string-match "\\S-+@\\S-+" x) |
| 277 | (cons nil x)) | 264 | (cons nil x)) |
| 278 | (t | 265 | (t |
| @@ -300,45 +287,43 @@ The return value has the form (NAME . ADDRESS)." | |||
| 300 | (lm-with-file file | 287 | (lm-with-file file |
| 301 | (lm-header "created"))) | 288 | (lm-header "created"))) |
| 302 | 289 | ||
| 303 | |||
| 304 | (defun lm-last-modified-date (&optional file) | 290 | (defun lm-last-modified-date (&optional file) |
| 305 | "Return the modify-date given in file FILE, or current buffer if FILE is nil." | 291 | "Return the modify-date given in file FILE, or current buffer if FILE is nil." |
| 306 | (lm-with-file file | 292 | (lm-with-file file |
| 307 | (goto-char (point-min)) | 293 | (if (progn |
| 308 | (when (re-search-forward | 294 | (goto-char (point-min)) |
| 295 | (re-search-forward | ||
| 309 | "\\$[I]d: [^ ]+ [^ ]+ \\([^/]+\\)/\\([^/]+\\)/\\([^ ]+\\) " | 296 | "\\$[I]d: [^ ]+ [^ ]+ \\([^/]+\\)/\\([^/]+\\)/\\([^ ]+\\) " |
| 310 | (lm-code-mark) t) | 297 | (lm-code-mark) t)) |
| 311 | (format "%s %s %s" | 298 | (format "%s %s %s" |
| 312 | (buffer-substring (match-beginning 3) (match-end 3)) | 299 | (match-string 3) |
| 313 | (nth (string-to-int | 300 | (nth (string-to-int |
| 314 | (buffer-substring (match-beginning 2) (match-end 2))) | 301 | (match-string 2)) |
| 315 | '("" "Jan" "Feb" "Mar" "Apr" "May" "Jun" | 302 | '("" "Jan" "Feb" "Mar" "Apr" "May" "Jun" |
| 316 | "Jul" "Aug" "Sep" "Oct" "Nov" "Dec")) | 303 | "Jul" "Aug" "Sep" "Oct" "Nov" "Dec")) |
| 317 | (buffer-substring (match-beginning 1) (match-end 1)))))) | 304 | (match-string 1))))) |
| 318 | 305 | ||
| 319 | (defun lm-version (&optional file) | 306 | (defun lm-version (&optional file) |
| 320 | "Return the version listed in file FILE, or current buffer if FILE is nil. | 307 | "Return the version listed in file FILE, or current buffer if FILE is nil. |
| 321 | This can befound in an RCS or SCCS header to crack it out of." | 308 | This can be found in an RCS or SCCS header." |
| 322 | (lm-with-file file | 309 | (lm-with-file file |
| 323 | (or | 310 | (or (lm-header "version") |
| 324 | (lm-header "version") | 311 | (let ((header-max (lm-code-mark))) |
| 325 | (let ((header-max (lm-code-mark))) | 312 | (goto-char (point-min)) |
| 326 | (goto-char (point-min)) | 313 | (cond |
| 327 | (cond | 314 | ;; Look for an RCS header |
| 328 | ;; Look for an RCS header | 315 | ((re-search-forward "\\$[I]d: [^ ]+ \\([^ ]+\\) " header-max t) |
| 329 | ((re-search-forward "\\$[I]d: [^ ]+ \\([^ ]+\\) " header-max t) | 316 | (match-string-no-properties 1)) |
| 330 | (buffer-substring-no-properties (match-beginning 1) (match-end 1))) | 317 | ((re-search-forward "\\$Revision: +\\([^ ]+\\) " header-max t) |
| 331 | 318 | (match-string-no-properties 1)) | |
| 332 | ;; Look for an SCCS header | 319 | ;; Look for an SCCS header |
| 333 | ((re-search-forward | 320 | ((re-search-forward |
| 334 | (concat | 321 | (concat |
| 335 | (regexp-quote "@(#)") | 322 | (regexp-quote "@(#)") |
| 336 | (regexp-quote (file-name-nondirectory (buffer-file-name))) | 323 | (regexp-quote (file-name-nondirectory (buffer-file-name))) |
| 337 | "\t\\([012345679.]*\\)") | 324 | "\t\\([012345679.]*\\)") |
| 338 | header-max t) | 325 | header-max t) |
| 339 | (buffer-substring-no-properties (match-beginning 1) (match-end 1))) | 326 | (match-string-no-properties 1))))))) |
| 340 | |||
| 341 | (t nil)))))) | ||
| 342 | 327 | ||
| 343 | (defun lm-keywords (&optional file) | 328 | (defun lm-keywords (&optional file) |
| 344 | "Return the keywords given in file FILE, or current buffer if FILE is nil." | 329 | "Return the keywords given in file FILE, or current buffer if FILE is nil." |
| @@ -359,12 +344,14 @@ The value is returned as a string. In the file, the commentary starts | |||
| 359 | with the tag `Commentary' or `Documentation' and ends with one of the | 344 | with the tag `Commentary' or `Documentation' and ends with one of the |
| 360 | tags `Code', `Change Log' or `History'." | 345 | tags `Code', `Change Log' or `History'." |
| 361 | (lm-with-file file | 346 | (lm-with-file file |
| 362 | (let ((commentary (lm-commentary-mark)) | 347 | (let ((commentary (lm-commentary-mark)) |
| 363 | (change-log (lm-history-mark)) | 348 | (change-log (lm-history-mark)) |
| 364 | (code (lm-code-mark))) | 349 | (code (lm-code-mark))) |
| 365 | (when (and commentary (or change-log code)) | 350 | (cond |
| 366 | (buffer-substring-no-properties | 351 | ((and commentary change-log) |
| 367 | commentary (min (or code (point-max)) (or change-log (point-max)))))))) | 352 | (buffer-substring-no-properties commentary change-log)) |
| 353 | ((and commentary code) | ||
| 354 | (buffer-substring-no-properties commentary code)))))) | ||
| 368 | 355 | ||
| 369 | ;;; Verification and synopses | 356 | ;;; Verification and synopses |
| 370 | 357 | ||
| @@ -379,79 +366,57 @@ tags `Code', `Change Log' or `History'." | |||
| 379 | If FILE is a directory, recurse on its files and generate a report in | 366 | If FILE is a directory, recurse on its files and generate a report in |
| 380 | a temporary buffer." | 367 | a temporary buffer." |
| 381 | (interactive) | 368 | (interactive) |
| 382 | (let* ((verb (or verb (interactive-p))) | 369 | (let* ((verb (or verb (interactive-p))) |
| 383 | ret | 370 | (ret (and verb "Ok.")) |
| 384 | name | 371 | name) |
| 385 | ) | ||
| 386 | (if verb | ||
| 387 | (setq ret "Ok.")) ;init value | ||
| 388 | |||
| 389 | (if (and file (file-directory-p file)) | 372 | (if (and file (file-directory-p file)) |
| 390 | (setq | 373 | (setq ret |
| 391 | ret | 374 | (with-temp-buffer |
| 392 | (progn | 375 | (mapcar |
| 393 | (switch-to-buffer (get-buffer-create "*lm-verify*")) | 376 | (lambda (f) |
| 394 | (erase-buffer) | 377 | (if (string-match ".*\\.el\\'" f) |
| 395 | (mapcar | 378 | (let ((status (lm-verify f))) |
| 396 | '(lambda (f) | 379 | (insert f ":") |
| 397 | (if (string-match ".*\\.el$" f) | 380 | (if status |
| 398 | (let ((status (lm-verify f))) | 381 | (lm-insert-at-column lm-comment-column status |
| 399 | (if status | 382 | "\n") |
| 400 | (progn | 383 | (if showok |
| 401 | (insert f ":") | 384 | (lm-insert-at-column lm-comment-column |
| 402 | (lm-insert-at-column lm-comment-column status "\n")) | 385 | "OK\n")))))) |
| 403 | (and showok | 386 | (directory-files file)))) |
| 404 | (progn | ||
| 405 | (insert f ":") | ||
| 406 | (lm-insert-at-column lm-comment-column "OK\n"))))))) | ||
| 407 | (directory-files file)) | ||
| 408 | )) | ||
| 409 | (lm-with-file file | 387 | (lm-with-file file |
| 410 | (setq name (lm-get-package-name)) | 388 | (setq name (lm-get-package-name)) |
| 411 | 389 | (setq ret | |
| 412 | (setq | 390 | (cond |
| 413 | ret | 391 | ((null name) |
| 414 | (cond | 392 | "Can't find a package NAME") |
| 415 | ((null name) | 393 | ((not (lm-authors)) |
| 416 | "Can't find a package NAME") | 394 | "Author: tag missing.") |
| 417 | 395 | ((not (lm-maintainer)) | |
| 418 | ((not (lm-authors)) | 396 | "Maintainer: tag missing.") |
| 419 | "Author: tag missing.") | 397 | ((not (lm-summary)) |
| 420 | 398 | "Can't find a one-line 'Summary' description") | |
| 421 | ((not (lm-maintainer)) | 399 | ((not (lm-keywords)) |
| 422 | "Maintainer: tag missing.") | 400 | "Keywords: tag missing.") |
| 423 | 401 | ((not (lm-commentary-mark)) | |
| 424 | ((not (lm-summary)) | 402 | "Can't find a 'Commentary' section marker.") |
| 425 | "Can't find a one-line 'Summary' description") | 403 | ((not (lm-history-mark)) |
| 426 | 404 | "Can't find a 'History' section marker.") | |
| 427 | ((not (lm-keywords)) | 405 | ((not (lm-code-mark)) |
| 428 | "Keywords: tag missing.") | 406 | "Can't find a 'Code' section marker") |
| 429 | 407 | ((progn | |
| 430 | ((not (lm-commentary-mark)) | 408 | (goto-char (point-max)) |
| 431 | "Can't find a 'Commentary' section marker.") | 409 | (not |
| 432 | 410 | (re-search-backward | |
| 433 | ((not (lm-history-mark)) | 411 | (concat "^;;;[ \t]+" name "[ \t]+ends here[ \t]*$" |
| 434 | "Can't find a 'History' section marker.") | 412 | "\\|^;;;[ \t]+ End of file[ \t]+" name) |
| 435 | 413 | nil t))) | |
| 436 | ((not (lm-code-mark)) | 414 | (format "Can't find a footer line for [%s]" name)) |
| 437 | "Can't find a 'Code' section marker") | 415 | (t |
| 438 | 416 | ret))))) | |
| 439 | ((progn | ||
| 440 | (goto-char (point-max)) | ||
| 441 | (not | ||
| 442 | (re-search-backward | ||
| 443 | (concat "^;;;[ \t]+" name "[ \t]+ends here[ \t]*$" | ||
| 444 | "\\|^;;;[ \t]+ End of file[ \t]+" name) | ||
| 445 | nil t | ||
| 446 | ))) | ||
| 447 | (format "Can't find a footer line for [%s]" name)) | ||
| 448 | (t | ||
| 449 | ret)) | ||
| 450 | ))) | ||
| 451 | (if verb | 417 | (if verb |
| 452 | (message ret)) | 418 | (message ret)) |
| 453 | ret | 419 | ret)) |
| 454 | )) | ||
| 455 | 420 | ||
| 456 | (defun lm-synopsis (&optional file showall) | 421 | (defun lm-synopsis (&optional file showall) |
| 457 | "Generate a synopsis listing for the buffer or the given FILE if given. | 422 | "Generate a synopsis listing for the buffer or the given FILE if given. |
| @@ -463,43 +428,46 @@ which do not include a recognizable synopsis." | |||
| 463 | (read-file-name "Synopsis for (file or dir): "))) | 428 | (read-file-name "Synopsis for (file or dir): "))) |
| 464 | 429 | ||
| 465 | (if (and file (file-directory-p file)) | 430 | (if (and file (file-directory-p file)) |
| 466 | (progn | 431 | (with-temp-buffer |
| 467 | (switch-to-buffer (get-buffer-create "*lm-verify*")) | ||
| 468 | (erase-buffer) | ||
| 469 | (mapcar | 432 | (mapcar |
| 470 | '(lambda (f) | 433 | (lambda (f) |
| 471 | (if (string-match ".*\\.el$" f) | 434 | (if (string-match "\\.el\\'" f) |
| 472 | (let ((syn (lm-synopsis f))) | 435 | (let ((syn (lm-synopsis f))) |
| 473 | (if syn | 436 | (if syn |
| 474 | (progn | 437 | (progn |
| 475 | (insert f ":") | 438 | (insert f ":") |
| 476 | (lm-insert-at-column lm-comment-column syn "\n")) | 439 | (lm-insert-at-column lm-comment-column syn "\n")) |
| 477 | (and showall | 440 | (when showall |
| 478 | (progn | 441 | (insert f ":") |
| 479 | (insert f ":") | 442 | (lm-insert-at-column lm-comment-column "NA\n")))))) |
| 480 | (lm-insert-at-column lm-comment-column "NA\n"))))))) | 443 | (directory-files file))) |
| 481 | (directory-files file)) | 444 | (save-excursion |
| 482 | ) | 445 | (if file |
| 483 | (lm-with-file file | 446 | (find-file file)) |
| 484 | (lm-summary)))) | 447 | (prog1 |
| 448 | (lm-summary) | ||
| 449 | (if file | ||
| 450 | (kill-buffer (current-buffer))))))) | ||
| 451 | |||
| 452 | (eval-when-compile (defvar report-emacs-bug-address)) | ||
| 485 | 453 | ||
| 486 | (defun lm-report-bug (topic) | 454 | (defun lm-report-bug (topic) |
| 487 | "Report a bug in the package currently being visited to its maintainer. | 455 | "Report a bug in the package currently being visited to its maintainer. |
| 488 | Prompts for bug subject TOPIC. Leaves you in a mail buffer." | 456 | Prompts for bug subject TOPIC. Leaves you in a mail buffer." |
| 489 | (interactive "sBug Subject: ") | 457 | (interactive "sBug Subject: ") |
| 490 | (let ((package (lm-get-package-name)) | 458 | (require 'emacsbug) |
| 491 | (addr (lm-maintainer)) | 459 | (let ((package (lm-get-package-name)) |
| 492 | (version (lm-version))) | 460 | (addr (lm-maintainer)) |
| 493 | (mail nil | 461 | (version (lm-version))) |
| 494 | (if addr | 462 | (compose-mail (if addr |
| 495 | (concat (car addr) " <" (cdr addr) ">") | 463 | (concat (car addr) " <" (cdr addr) ">") |
| 496 | report-emacs-bug-address) | 464 | report-emacs-bug-address) |
| 497 | topic) | 465 | topic) |
| 498 | (goto-char (point-max)) | 466 | (goto-char (point-max)) |
| 499 | (insert "\nIn " | 467 | (insert "\nIn " package) |
| 500 | package | 468 | (if version |
| 501 | (if version (concat " version " version) "") | 469 | (insert " version " version)) |
| 502 | "\n\n") | 470 | (newline 2) |
| 503 | (message | 471 | (message |
| 504 | (substitute-command-keys "Type \\[mail-send] to send bug report.")))) | 472 | (substitute-command-keys "Type \\[mail-send] to send bug report.")))) |
| 505 | 473 | ||