comparison lisp/emacs-lisp/checkdoc.el @ 88155:d7ddb3e565de

sync with trunk
author Henrik Enberg <henrik.enberg@telia.com>
date Mon, 16 Jan 2006 00:03:54 +0000
parents 45cd70f39238
children
comparison
equal deleted inserted replaced
88154:8ce476d3ba36 88155:d7ddb3e565de
1 ;;; checkdoc.el --- check documentation strings for style requirements 1 ;;; checkdoc.el --- check documentation strings for style requirements
2 2
3 ;;; Copyright (C) 1997, 1998, 2001 Free Software Foundation 3 ;; Copyright (C) 1997, 1998, 2001, 2002, 2003, 2004,
4 ;; 2005 Free Software Foundation, Inc.
4 5
5 ;; Author: Eric M. Ludlam <zappo@gnu.org> 6 ;; Author: Eric M. Ludlam <zappo@gnu.org>
6 ;; Version: 0.6.2 7 ;; Version: 0.6.2
7 ;; Keywords: docs, maint, lisp 8 ;; Keywords: docs, maint, lisp
8 9
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 ;; GNU General Public License for more details. 20 ;; GNU General Public License for more details.
20 21
21 ;; You should have received a copy of the GNU General Public License 22 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING. If not, write to the 23 ;; along with GNU Emacs; see the file COPYING. If not, write to the
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, 24 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 ;; Boston, MA 02111-1307, USA. 25 ;; Boston, MA 02110-1301, USA.
25 26
26 ;;; Commentary: 27 ;;; Commentary:
27 ;; 28 ;;
28 ;; The Emacs Lisp manual has a nice chapter on how to write 29 ;; The Emacs Lisp manual has a nice chapter on how to write
29 ;; documentation strings. Many stylistic suggestions are fairly 30 ;; documentation strings. Many stylistic suggestions are fairly
187 (defmacro custom-add-option (&rest args) 188 (defmacro custom-add-option (&rest args)
188 nil) 189 nil)
189 (defmacro defcustom (var value doc &rest args) 190 (defmacro defcustom (var value doc &rest args)
190 `(defvar ,var ,value ,doc)))) 191 `(defvar ,var ,value ,doc))))
191 192
193 (defvar compilation-error-regexp-alist)
194 (defvar compilation-mode-font-lock-keywords)
195
192 (defcustom checkdoc-autofix-flag 'semiautomatic 196 (defcustom checkdoc-autofix-flag 'semiautomatic
193 "*Non-nil means attempt auto-fixing of doc strings. 197 "*Non-nil means attempt auto-fixing of doc strings.
194 If this value is the symbol `query', then the user is queried before 198 If this value is the symbol `query', then the user is queried before
195 any change is made. If the value is `automatic', then all changes are 199 any change is made. If the value is `automatic', then all changes are
196 made without asking unless the change is very-complex. If the value 200 made without asking unless the change is very-complex. If the value
315 (defvar checkdoc-proper-noun-list 319 (defvar checkdoc-proper-noun-list
316 '("ispell" "xemacs" "emacs" "lisp") 320 '("ispell" "xemacs" "emacs" "lisp")
317 "List of words (not capitalized) which should be capitalized.") 321 "List of words (not capitalized) which should be capitalized.")
318 322
319 (defvar checkdoc-proper-noun-regexp 323 (defvar checkdoc-proper-noun-regexp
320 (let ((expr "\\<\\(") 324 (let ((expr "\\_<\\(")
321 (l checkdoc-proper-noun-list)) 325 (l checkdoc-proper-noun-list))
322 (while l 326 (while l
323 (setq expr (concat expr (car l) (if (cdr l) "\\|" "")) 327 (setq expr (concat expr (car l) (if (cdr l) "\\|" ""))
324 l (cdr l))) 328 l (cdr l)))
325 (concat expr "\\)\\>")) 329 (concat expr "\\)\\_>"))
326 "Regular expression derived from `checkdoc-proper-noun-regexp'.") 330 "Regular expression derived from `checkdoc-proper-noun-regexp'.")
327 331
328 (defvar checkdoc-common-verbs-regexp nil 332 (defvar checkdoc-common-verbs-regexp nil
329 "Regular expression derived from `checkdoc-common-verbs-regexp'.") 333 "Regular expression derived from `checkdoc-common-verbs-regexp'.")
330 334
428 ) 432 )
429 433
430 434
431 ;;; Compatibility 435 ;;; Compatibility
432 ;; 436 ;;
433 (if (string-match "X[Ee]macs" emacs-version) 437 (defalias 'checkdoc-make-overlay
434 (progn 438 (if (featurep 'xemacs) 'make-extent 'make-overlay))
435 (defalias 'checkdoc-make-overlay 'make-extent) 439 (defalias 'checkdoc-overlay-put
436 (defalias 'checkdoc-overlay-put 'set-extent-property) 440 (if (featurep 'xemacs) 'set-extent-property 'overlay-put))
437 (defalias 'checkdoc-delete-overlay 'delete-extent) 441 (defalias 'checkdoc-delete-overlay
438 (defalias 'checkdoc-overlay-start 'extent-start) 442 (if (featurep 'xemacs) 'delete-extent 'delete-overlay))
439 (defalias 'checkdoc-overlay-end 'extent-end) 443 (defalias 'checkdoc-overlay-start
440 (defalias 'checkdoc-mode-line-update 'redraw-modeline) 444 (if (featurep 'xemacs) 'extent-start 'overlay-start))
441 (defalias 'checkdoc-call-eval-buffer 'eval-buffer) 445 (defalias 'checkdoc-overlay-end
442 ) 446 (if (featurep 'xemacs) 'extent-end 'overlay-end))
443 (defalias 'checkdoc-make-overlay 'make-overlay) 447 (defalias 'checkdoc-mode-line-update
444 (defalias 'checkdoc-overlay-put 'overlay-put) 448 (if (featurep 'xemacs) 'redraw-modeline 'force-mode-line-update))
445 (defalias 'checkdoc-delete-overlay 'delete-overlay) 449 (defalias 'checkdoc-char=
446 (defalias 'checkdoc-overlay-start 'overlay-start) 450 (if (featurep 'xemacs) 'char= '=))
447 (defalias 'checkdoc-overlay-end 'overlay-end)
448 (defalias 'checkdoc-mode-line-update 'force-mode-line-update)
449 (defalias 'checkdoc-call-eval-buffer 'eval-current-buffer)
450 )
451
452 ;; Emacs 20s have MULE characters which don't equate to numbers.
453 (if (fboundp 'char=)
454 (defalias 'checkdoc-char= 'char=)
455 (defalias 'checkdoc-char= '=))
456
457 ;; Read events, not characters
458 (defalias 'checkdoc-read-event 'read-event)
459 451
460 ;;; User level commands 452 ;;; User level commands
461 ;; 453 ;;
462 ;;;###autoload 454 ;;;###autoload
463 (defun checkdoc () 455 (defun checkdoc ()
507 (setcar (cdr (cdr (cdr status))) "Ok")) 499 (setcar (cdr (cdr (cdr status))) "Ok"))
508 (checkdoc-display-status-buffer status))) 500 (checkdoc-display-status-buffer status)))
509 501
510 (defun checkdoc-display-status-buffer (check) 502 (defun checkdoc-display-status-buffer (check)
511 "Display and update the status buffer for the current checkdoc mode. 503 "Display and update the status buffer for the current checkdoc mode.
512 CHECK is a vector stating the current status of each test as an 504 CHECK is a list of four strings stating the current status of each
513 element is the status of that level of test." 505 test; the nth string describes the status of the nth test."
514 (let (temp-buffer-setup-hook) 506 (let (temp-buffer-setup-hook)
515 (with-output-to-temp-buffer " *Checkdoc Status*" 507 (with-output-to-temp-buffer " *Checkdoc Status*"
516 (princ-list 508 (princ-list
517 "Buffer comments and tags: " (nth 0 check) "\n" 509 "Buffer comments and tags: " (nth 0 check) "\n"
518 "Documentation style: " (nth 1 check) "\n" 510 "Documentation style: " (nth 1 check) "\n"
535 checkdoc status window instead of the usual behavior." 527 checkdoc status window instead of the usual behavior."
536 (interactive "P") 528 (interactive "P")
537 (let ((checkdoc-spellcheck-documentation-flag 529 (let ((checkdoc-spellcheck-documentation-flag
538 (car (memq checkdoc-spellcheck-documentation-flag 530 (car (memq checkdoc-spellcheck-documentation-flag
539 '(interactive t))))) 531 '(interactive t)))))
540 (checkdoc-interactive-loop start-here showstatus 'checkdoc-next-error))) 532 (prog1
533 ;; Due to a design flaw, this will never spell check
534 ;; docstrings.
535 (checkdoc-interactive-loop start-here showstatus
536 'checkdoc-next-error)
537 ;; This is a workaround to perform spell checking.
538 (checkdoc-interactive-ispell-loop start-here))))
541 539
542 ;;;###autoload 540 ;;;###autoload
543 (defun checkdoc-message-interactive (&optional start-here showstatus) 541 (defun checkdoc-message-interactive (&optional start-here showstatus)
544 "Interactively check the current buffer for message string errors. 542 "Interactively check the current buffer for message string errors.
545 Prefix argument START-HERE will start the checking from the current 543 Prefix argument START-HERE will start the checking from the current
550 checkdoc status window instead of the usual behavior." 548 checkdoc status window instead of the usual behavior."
551 (interactive "P") 549 (interactive "P")
552 (let ((checkdoc-spellcheck-documentation-flag 550 (let ((checkdoc-spellcheck-documentation-flag
553 (car (memq checkdoc-spellcheck-documentation-flag 551 (car (memq checkdoc-spellcheck-documentation-flag
554 '(interactive t))))) 552 '(interactive t)))))
555 (checkdoc-interactive-loop start-here showstatus 553 (prog1
556 'checkdoc-next-message-error))) 554 ;; Due to a design flaw, this will never spell check messages.
555 (checkdoc-interactive-loop start-here showstatus
556 'checkdoc-next-message-error)
557 ;; This is a workaround to perform spell checking.
558 (checkdoc-message-interactive-ispell-loop start-here))))
557 559
558 (defun checkdoc-interactive-loop (start-here showstatus findfunc) 560 (defun checkdoc-interactive-loop (start-here showstatus findfunc)
559 "Interactively loop over all errors that can be found by a given method. 561 "Interactively loop over all errors that can be found by a given method.
560 Searching starts at START-HERE. SHOWSTATUS expresses the verbosity 562
561 of the search, and whether ending the search will auto-exit this function. 563 If START-HERE is nil, searching starts at the beginning of the current
564 buffer, otherwise searching starts at START-HERE. SHOWSTATUS
565 expresses the verbosity of the search, and whether ending the search
566 will auto-exit this function.
567
562 FINDFUNC is a symbol representing a function that will position the 568 FINDFUNC is a symbol representing a function that will position the
563 cursor, and return error message text to present to the user. It is 569 cursor, and return error message text to present to the user. It is
564 assumed that the cursor will stop just before a major sexp, which will 570 assumed that the cursor will stop just before a major sexp, which will
565 be highlighted to present the user with feedback as to the offending 571 be highlighted to present the user with feedback as to the offending
566 style." 572 style."
612 "" "f,")) 618 "" "f,"))
613 (save-excursion 619 (save-excursion
614 (goto-char (checkdoc-error-start (car (car err-list)))) 620 (goto-char (checkdoc-error-start (car (car err-list))))
615 (if (not (pos-visible-in-window-p)) 621 (if (not (pos-visible-in-window-p))
616 (recenter (- (window-height) 2))) 622 (recenter (- (window-height) 2)))
617 (setq c (checkdoc-read-event)))1 623 (setq c (read-event)))
618 (if (not (integerp c)) (setq c ??)) 624 (if (not (integerp c)) (setq c ??))
619 (cond 625 (cond
620 ;; Exit condition 626 ;; Exit condition
621 ((checkdoc-char= c ?\C-g) (signal 'quit nil)) 627 ((checkdoc-char= c ?\C-g) (signal 'quit nil))
622 ;; Request an auto-fix 628 ;; Request an auto-fix
624 (checkdoc-delete-overlay cdo) 630 (checkdoc-delete-overlay cdo)
625 (setq cdo nil) 631 (setq cdo nil)
626 (goto-char (cdr (car err-list))) 632 (goto-char (cdr (car err-list)))
627 ;; `automatic-then-never' tells the autofix function 633 ;; `automatic-then-never' tells the autofix function
628 ;; to only allow one fix to be automatic. The autofix 634 ;; to only allow one fix to be automatic. The autofix
629 ;; function will than set the flag to 'never, allowing 635 ;; function will then set the flag to 'never, allowing
630 ;; the checker to return a different error. 636 ;; the checker to return a different error.
631 (let ((checkdoc-autofix-flag 'automatic-then-never) 637 (let ((checkdoc-autofix-flag 'automatic-then-never)
632 (fixed nil)) 638 (fixed nil))
633 (funcall findfunc t) 639 (funcall findfunc t)
634 (setq fixed (not (eq checkdoc-autofix-flag 640 (setq fixed (not (eq checkdoc-autofix-flag
637 (progn 643 (progn
638 (message "A Fix was not available.") 644 (message "A Fix was not available.")
639 (sit-for 2)) 645 (sit-for 2))
640 (setq err-list (cdr err-list)))) 646 (setq err-list (cdr err-list))))
641 (beginning-of-defun) 647 (beginning-of-defun)
642 (let ((pe (car err-list)) 648 (let ((ne (funcall findfunc nil)))
643 (ne (funcall findfunc nil)))
644 (if ne 649 (if ne
645 (setq err-list (cons ne err-list)) 650 (setq err-list (cons ne err-list))
646 (cond ((not err-list) 651 (cond ((not err-list)
647 (message "No More Stylistic Errors.") 652 (message "No More Stylistic Errors.")
648 (sit-for 2)) 653 (sit-for 2))
649 (t 654 (t
650 (message 655 (message
651 "No Additional style errors. Continuing...") 656 "No Additional style errors. Continuing...")
652 (sit-for 2)))))) 657 (sit-for 2))))))
653 ;; Move to the next error (if available) 658 ;; Move to the next error (if available)
654 ((or (checkdoc-char= c ?n) (checkdoc-char= c ?\ )) 659 ((or (checkdoc-char= c ?n) (checkdoc-char= c ?\s))
655 (let ((ne (funcall findfunc nil))) 660 (let ((ne (funcall findfunc nil)))
656 (if (not ne) 661 (if (not ne)
657 (if showstatus 662 (if showstatus
658 (setq returnme err-list 663 (setq returnme err-list
659 err-list nil) 664 err-list nil)
689 ;; Quit checkdoc 694 ;; Quit checkdoc
690 ((checkdoc-char= c ?q) 695 ((checkdoc-char= c ?q)
691 (setq returnme err-list 696 (setq returnme err-list
692 err-list nil 697 err-list nil
693 begin (point))) 698 begin (point)))
694 ;; Goofy s tuff 699 ;; Goofy stuff
695 (t 700 (t
696 (if (get-buffer-window "*Checkdoc Help*") 701 (if (get-buffer-window "*Checkdoc Help*")
697 (progn 702 (progn
698 (delete-window (get-buffer-window "*Checkdoc Help*")) 703 (delete-window (get-buffer-window "*Checkdoc Help*"))
699 (kill-buffer "*Checkdoc Help*")) 704 (kill-buffer "*Checkdoc Help*"))
718 (goto-char begin) 723 (goto-char begin)
719 (if (get-buffer "*Checkdoc Help*") (kill-buffer "*Checkdoc Help*")) 724 (if (get-buffer "*Checkdoc Help*") (kill-buffer "*Checkdoc Help*"))
720 (message "Checkdoc: Done.") 725 (message "Checkdoc: Done.")
721 returnme)) 726 returnme))
722 727
728 (defun checkdoc-interactive-ispell-loop (start-here)
729 "Interactively spell check doc strings in the current buffer.
730 If START-HERE is nil, searching starts at the beginning of the current
731 buffer, otherwise searching starts at START-HERE."
732 (when checkdoc-spellcheck-documentation-flag
733 (save-excursion
734 ;; Move point to where we need to start.
735 (if start-here
736 ;; Include whatever function point is in for good measure.
737 (beginning-of-defun)
738 (goto-char (point-min)))
739 ;; Loop over docstrings.
740 (while (checkdoc-next-docstring)
741 (message "Searching for doc string spell error...%d%%"
742 (/ (* 100 (point)) (point-max)))
743 (if (looking-at "\"")
744 (checkdoc-ispell-docstring-engine
745 (save-excursion (forward-sexp 1) (point-marker)))))
746 (message "Checkdoc: Done."))))
747
748 (defun checkdoc-message-interactive-ispell-loop (start-here)
749 "Interactively spell check messages in the current buffer.
750 If START-HERE is nil, searching starts at the beginning of the current
751 buffer, otherwise searching starts at START-HERE."
752 (when checkdoc-spellcheck-documentation-flag
753 (save-excursion
754 ;; Move point to where we need to start.
755 (if start-here
756 ;; Include whatever function point is in for good measure.
757 (beginning-of-defun)
758 (goto-char (point-min)))
759 ;; Loop over message strings.
760 (while (checkdoc-message-text-next-string (point-max))
761 (message "Searching for message string spell error...%d%%"
762 (/ (* 100 (point)) (point-max)))
763 (if (looking-at "\"")
764 (checkdoc-ispell-docstring-engine
765 (save-excursion (forward-sexp 1) (point-marker)))))
766 (message "Checkdoc: Done."))))
767
768
723 (defun checkdoc-next-error (enable-fix) 769 (defun checkdoc-next-error (enable-fix)
724 "Find and return the next checkdoc error list, or nil. 770 "Find and return the next checkdoc error list, or nil.
725 Only documentation strings are checked. 771 Only documentation strings are checked.
726 Add error vector is of the form (WARNING . POSITION) where WARNING 772 An error list is of the form (WARNING . POSITION) where WARNING is the
727 is the warning text, and POSITION is the point in the buffer where the 773 warning text, and POSITION is the point in the buffer where the error
728 error was found. We can use points and not markers because we promise 774 was found. We can use points and not markers because we promise not
729 not to edit the buffer before point without re-executing this check. 775 to edit the buffer before point without re-executing this check.
730 Argument ENABLE-FIX will enable auto-fixing while looking for the next 776 Argument ENABLE-FIX will enable auto-fixing while looking for the next
731 error. This argument assumes that the cursor is already positioned to 777 error. This argument assumes that the cursor is already positioned to
732 perform the fix." 778 perform the fix."
733 (if enable-fix 779 (if enable-fix
734 (checkdoc-this-string-valid) 780 (checkdoc-this-string-valid)
788 "Evaluate and check documentation for the current buffer. 834 "Evaluate and check documentation for the current buffer.
789 Evaluation is done first because good documentation for something that 835 Evaluation is done first because good documentation for something that
790 doesn't work is just not useful. Comments, doc strings, and rogue 836 doesn't work is just not useful. Comments, doc strings, and rogue
791 spacing are all verified." 837 spacing are all verified."
792 (interactive) 838 (interactive)
793 (checkdoc-call-eval-buffer nil) 839 (eval-buffer nil)
794 (checkdoc-current-buffer t)) 840 (checkdoc-current-buffer t))
795 841
796 ;;;###autoload 842 ;;;###autoload
797 (defun checkdoc-current-buffer (&optional take-notes) 843 (defun checkdoc-current-buffer (&optional take-notes)
798 "Check current buffer for document, comment, error style, and rogue spaces. 844 "Check current buffer for document, comment, error style, and rogue spaces.
843 "Find the next doc string in the current buffer which has a style error. 889 "Find the next doc string in the current buffer which has a style error.
844 Prefix argument TAKE-NOTES means to continue through the whole buffer and 890 Prefix argument TAKE-NOTES means to continue through the whole buffer and
845 save warnings in a separate buffer. Second optional argument START-POINT 891 save warnings in a separate buffer. Second optional argument START-POINT
846 is the starting location. If this is nil, `point-min' is used instead." 892 is the starting location. If this is nil, `point-min' is used instead."
847 (interactive "P") 893 (interactive "P")
848 (let ((wrong nil) (msg nil) (errors nil) 894 (let ((wrong nil) (msg nil)
849 ;; Assign a flag to spellcheck flag 895 ;; Assign a flag to spellcheck flag
850 (checkdoc-spellcheck-documentation-flag 896 (checkdoc-spellcheck-documentation-flag
851 (car (memq checkdoc-spellcheck-documentation-flag 897 (car (memq checkdoc-spellcheck-documentation-flag
852 '(buffer t)))) 898 '(buffer t))))
853 (checkdoc-autofix-flag (if take-notes 'never 899 (checkdoc-autofix-flag (if take-notes 'never
863 (if msg (setq wrong (point))))) 909 (if msg (setq wrong (point)))))
864 (if wrong 910 (if wrong
865 (progn 911 (progn
866 (goto-char wrong) 912 (goto-char wrong)
867 (if (not take-notes) 913 (if (not take-notes)
868 (error (checkdoc-error-text msg))))) 914 (error "%s" (checkdoc-error-text msg)))))
869 (checkdoc-show-diagnostics) 915 (checkdoc-show-diagnostics)
870 (if (interactive-p) 916 (if (interactive-p)
871 (message "No style warnings.")))) 917 (message "No style warnings."))))
872 918
873 (defun checkdoc-next-docstring () 919 (defun checkdoc-next-docstring ()
896 '(buffer t)))) 942 '(buffer t))))
897 (checkdoc-autofix-flag (if take-notes 'never checkdoc-autofix-flag)) 943 (checkdoc-autofix-flag (if take-notes 'never checkdoc-autofix-flag))
898 (e (checkdoc-file-comments-engine)) 944 (e (checkdoc-file-comments-engine))
899 (checkdoc-generate-compile-warnings-flag 945 (checkdoc-generate-compile-warnings-flag
900 (or take-notes checkdoc-generate-compile-warnings-flag))) 946 (or take-notes checkdoc-generate-compile-warnings-flag)))
901 (if e (error (checkdoc-error-text e))) 947 (if e (error "%s" (checkdoc-error-text e)))
902 (checkdoc-show-diagnostics) 948 (checkdoc-show-diagnostics)
903 e)) 949 e))
904 950
905 ;;;###autoload 951 ;;;###autoload
906 (defun checkdoc-rogue-spaces (&optional take-notes interact) 952 (defun checkdoc-rogue-spaces (&optional take-notes interact)
934 (or take-notes checkdoc-generate-compile-warnings-flag))) 980 (or take-notes checkdoc-generate-compile-warnings-flag)))
935 (setq e (checkdoc-message-text-search)) 981 (setq e (checkdoc-message-text-search))
936 (if (not (interactive-p)) 982 (if (not (interactive-p))
937 e 983 e
938 (if e 984 (if e
939 (error (checkdoc-error-text e)) 985 (error "%s" (checkdoc-error-text e))
940 (checkdoc-show-diagnostics))) 986 (checkdoc-show-diagnostics)))
941 (goto-char p)) 987 (goto-char p))
942 (if (interactive-p) (message "Checking interactive message text...done."))) 988 (if (interactive-p) (message "Checking interactive message text...done.")))
943 989
944 ;;;###autoload 990 ;;;###autoload
977 (beg (save-excursion (beginning-of-defun) (point))) 1023 (beg (save-excursion (beginning-of-defun) (point)))
978 (end (save-excursion (end-of-defun) (point))) 1024 (end (save-excursion (end-of-defun) (point)))
979 (msg (checkdoc-this-string-valid))) 1025 (msg (checkdoc-this-string-valid)))
980 (if msg (if no-error 1026 (if msg (if no-error
981 (message (checkdoc-error-text msg)) 1027 (message (checkdoc-error-text msg))
982 (error (checkdoc-error-text msg))) 1028 (error "%s" (checkdoc-error-text msg)))
983 (setq msg (checkdoc-message-text-search beg end)) 1029 (setq msg (checkdoc-message-text-search beg end))
984 (if msg (if no-error 1030 (if msg (if no-error
985 (message (checkdoc-error-text msg)) 1031 (message (checkdoc-error-text msg))
986 (error (checkdoc-error-text msg))) 1032 (error "%s" (checkdoc-error-text msg)))
987 (setq msg (checkdoc-rogue-space-check-engine beg end)) 1033 (setq msg (checkdoc-rogue-space-check-engine beg end))
988 (if msg (if no-error 1034 (if msg (if no-error
989 (message (checkdoc-error-text msg)) 1035 (message (checkdoc-error-text msg))
990 (error (checkdoc-error-text msg)))))) 1036 (error "%s" (checkdoc-error-text msg))))))
991 (if (interactive-p) (message "Checkdoc: done.")))))) 1037 (if (interactive-p) (message "Checkdoc: done."))))))
992 1038
993 ;;; Ispell interface for forcing a spell check 1039 ;;; Ispell interface for forcing a spell check
994 ;; 1040 ;;
995 1041
1190 (define-minor-mode checkdoc-minor-mode 1236 (define-minor-mode checkdoc-minor-mode
1191 "Toggle Checkdoc minor mode, a mode for checking Lisp doc strings. 1237 "Toggle Checkdoc minor mode, a mode for checking Lisp doc strings.
1192 With prefix ARG, turn Checkdoc minor mode on iff ARG is positive. 1238 With prefix ARG, turn Checkdoc minor mode on iff ARG is positive.
1193 1239
1194 In Checkdoc minor mode, the usual bindings for `eval-defun' which is 1240 In Checkdoc minor mode, the usual bindings for `eval-defun' which is
1195 bound to \\<checkdoc-minor-mode-map> \\[checkdoc-eval-defun] and `checkdoc-eval-current-buffer' are overridden to include 1241 bound to \\<checkdoc-minor-mode-map>\\[checkdoc-eval-defun] and `checkdoc-eval-current-buffer' are overridden to include
1196 checking of documentation strings. 1242 checking of documentation strings.
1197 1243
1198 \\{checkdoc-minor-mode-map}" 1244 \\{checkdoc-minor-mode-map}"
1199 nil " CDoc" nil 1245 nil " CDoc" nil
1200 :group 'checkdoc) 1246 :group 'checkdoc)
1505 ;; It is not practical to use `\\[...]' very many times, because 1551 ;; It is not practical to use `\\[...]' very many times, because
1506 ;; display of the documentation string will become slow. So use this 1552 ;; display of the documentation string will become slow. So use this
1507 ;; to describe the most important commands in your major mode, and 1553 ;; to describe the most important commands in your major mode, and
1508 ;; then use `\\{...}' to display the rest of the mode's keymap. 1554 ;; then use `\\{...}' to display the rest of the mode's keymap.
1509 (save-excursion 1555 (save-excursion
1510 (if (re-search-forward "\\\\\\\\\\[\\w+" e t 1556 (if (and (re-search-forward "\\\\\\\\\\[\\w+" e t
1511 (1+ checkdoc-max-keyref-before-warn)) 1557 (1+ checkdoc-max-keyref-before-warn))
1558 (not (re-search-forward "\\\\\\\\{\\w+}" e t)))
1512 (checkdoc-create-error 1559 (checkdoc-create-error
1513 "Too many occurrences of \\[function]. Use \\{keymap} instead" 1560 "Too many occurrences of \\[function]. Use \\{keymap} instead"
1514 s (marker-position e)))) 1561 s (marker-position e))))
1515 ;; Ambiguous quoted symbol. When a symbol is both bound and fbound, 1562 ;; Ambiguous quoted symbol. When a symbol is both bound and fbound,
1516 ;; and is referred to in documentation, it should be prefixed with 1563 ;; and is referred to in documentation, it should be prefixed with
1536 ;; We didn't actually replace anything. Here we find 1583 ;; We didn't actually replace anything. Here we find
1537 ;; out what special word form they wish to use as 1584 ;; out what special word form they wish to use as
1538 ;; a prefix. 1585 ;; a prefix.
1539 (let ((disambiguate 1586 (let ((disambiguate
1540 (completing-read 1587 (completing-read
1541 "Disambiguating Keyword (default: variable): " 1588 "Disambiguating Keyword (default variable): "
1542 '(("function") ("command") ("variable") 1589 '(("function") ("command") ("variable")
1543 ("option") ("symbol")) 1590 ("option") ("symbol"))
1544 nil t nil nil "variable"))) 1591 nil t nil nil "variable")))
1545 (goto-char (1- mb)) 1592 (goto-char (1- mb))
1546 (insert disambiguate " ") 1593 (insert disambiguate " ")
1705 ;; 1752 ;;
1706 ;; This is the least important of the above tests. Make sure 1753 ;; This is the least important of the above tests. Make sure
1707 ;; it occurs last. 1754 ;; it occurs last.
1708 (and checkdoc-verb-check-experimental-flag 1755 (and checkdoc-verb-check-experimental-flag
1709 (save-excursion 1756 (save-excursion
1710 ;; Maybe rebuild the monster-regex 1757 ;; Maybe rebuild the monster-regexp
1711 (checkdoc-create-common-verbs-regexp) 1758 (checkdoc-create-common-verbs-regexp)
1712 (let ((lim (save-excursion 1759 (let ((lim (save-excursion
1713 (end-of-line) 1760 (end-of-line)
1714 ;; check string-continuation 1761 ;; check string-continuation
1715 (if (checkdoc-char= (preceding-char) ?\\) 1762 (if (checkdoc-char= (preceding-char) ?\\)
2053 Since Ispell isn't Lisp-smart, we must pre-process the doc string 2100 Since Ispell isn't Lisp-smart, we must pre-process the doc string
2054 before using the Ispell engine on it." 2101 before using the Ispell engine on it."
2055 (if (or (not checkdoc-spellcheck-documentation-flag) 2102 (if (or (not checkdoc-spellcheck-documentation-flag)
2056 ;; If the user wants no questions or fixing, then we must 2103 ;; If the user wants no questions or fixing, then we must
2057 ;; disable spell checking as not useful. 2104 ;; disable spell checking as not useful.
2058 ;; FIXME: Somehow, `checkdoc-autofix-flag' is always nil 2105 (not checkdoc-autofix-flag)
2059 ;; when `checkdoc-ispell-docstring-engine' is called to be
2060 ;; used on a docstring. As a workround, I commented out the
2061 ;; next line.
2062 ;; (not checkdoc-autofix-flag)
2063 (eq checkdoc-autofix-flag 'never)) 2106 (eq checkdoc-autofix-flag 'never))
2064 nil 2107 nil
2065 (checkdoc-ispell-init) 2108 (checkdoc-ispell-init)
2066 (save-excursion 2109 (save-excursion
2067 (skip-chars-forward "^a-zA-Z") 2110 (skip-chars-forward "^a-zA-Z")
2273 ;; * A footer. Not compartmentalized from lm-verify: too bad. 2316 ;; * A footer. Not compartmentalized from lm-verify: too bad.
2274 ;; The following is partially clipped from lm-verify 2317 ;; The following is partially clipped from lm-verify
2275 (save-excursion 2318 (save-excursion
2276 (goto-char (point-max)) 2319 (goto-char (point-max))
2277 (if (not (re-search-backward 2320 (if (not (re-search-backward
2278 (concat "^;;;[ \t]+" fn "\\(" (regexp-quote fe) 2321 (concat "^;;;[ \t]+" (regexp-quote fn) "\\(" (regexp-quote fe)
2279 "\\)?[ \t]+ends here[ \t]*$" 2322 "\\)?[ \t]+ends here[ \t]*$"
2280 "\\|^;;;[ \t]+ End of file[ \t]+" 2323 "\\|^;;;[ \t]+ End of file[ \t]+"
2281 fn "\\(" (regexp-quote fe) "\\)?") 2324 (regexp-quote fn) "\\(" (regexp-quote fe) "\\)?")
2282 nil t)) 2325 nil t))
2283 (if (checkdoc-y-or-n-p "No identifiable footer! Add one? ") 2326 (if (checkdoc-y-or-n-p "No identifiable footer! Add one? ")
2284 (progn 2327 (progn
2285 (goto-char (point-max)) 2328 (goto-char (point-max))
2286 (insert "\n(provide '" fn ")\n\n;;; " fn fe " ends here\n")) 2329 (insert "\n(provide '" fn ")\n\n;;; " fn fe " ends here\n"))
2293 2336
2294 ;; Let's spellcheck the commentary section. This is the only 2337 ;; Let's spellcheck the commentary section. This is the only
2295 ;; section that is easy to pick out, and it is also the most 2338 ;; section that is easy to pick out, and it is also the most
2296 ;; visible section (with the finder). 2339 ;; visible section (with the finder).
2297 (let ((cm (lm-commentary-mark))) 2340 (let ((cm (lm-commentary-mark)))
2298 (if cm 2341 (when cm
2299 (save-excursion 2342 (save-excursion
2300 (goto-char (lm-commentary-mark)) 2343 (goto-char cm)
2301 ;; Spellcheck between the commentary, and the first 2344 (let ((e (copy-marker (lm-commentary-end))))
2302 ;; non-comment line. We could use lm-commentary, but that 2345 ;; Since the comments talk about Lisp, use the
2303 ;; returns a string, and Ispell wants to talk to a buffer. 2346 ;; specialized spell-checker we also used for doc
2304 ;; Since the comments talk about Lisp, use the specialized 2347 ;; strings.
2305 ;; spell-checker we also used for doc strings. 2348 (checkdoc-sentencespace-region-engine (point) e)
2306 (let ((e (save-excursion (re-search-forward "^[^;]" nil t) 2349 (checkdoc-proper-noun-region-engine (point) e)
2307 (point)))) 2350 (checkdoc-ispell-docstring-engine e)))))
2308 (checkdoc-sentencespace-region-engine (point) e)
2309 (checkdoc-proper-noun-region-engine (point) e)
2310 (checkdoc-ispell-docstring-engine e)))))
2311 ;;; test comment out code
2312 ;;; (foo 1 3)
2313 ;;; (bar 5 7)
2314 (setq 2351 (setq
2315 err 2352 err
2316 (or 2353 (or
2317 ;; Generic Full-file checks (should be comment related) 2354 ;; Generic Full-file checks (should be comment related)
2318 (checkdoc-run-hooks 'checkdoc-comment-style-hooks) 2355 (checkdoc-run-hooks 'checkdoc-comment-style-hooks)
2533 ret))) 2570 ret)))
2534 2571
2535 ;;; Warning management 2572 ;;; Warning management
2536 ;; 2573 ;;
2537 (defvar checkdoc-output-font-lock-keywords 2574 (defvar checkdoc-output-font-lock-keywords
2538 '(("\\(\\w+\\.el\\): \\(\\w+\\)" 2575 '(("^\\*\\*\\* \\(.+\\.el\\): \\([^ \n]+\\)"
2539 (1 font-lock-function-name-face) 2576 (1 font-lock-function-name-face)
2540 (2 font-lock-comment-face)) 2577 (2 font-lock-comment-face)))
2541 ("^\\(\\w+\\.el\\):" 1 font-lock-function-name-face)
2542 (":\\([0-9]+\\):" 1 font-lock-constant-face))
2543 "Keywords used to highlight a checkdoc diagnostic buffer.") 2578 "Keywords used to highlight a checkdoc diagnostic buffer.")
2544 2579
2545 (defvar checkdoc-output-mode-map nil 2580 (defvar checkdoc-output-error-regex-alist
2546 "Keymap used in `checkdoc-output-mode'.") 2581 '(("^\\(.+\\.el\\):\\([0-9]+\\): " 1 2)))
2547 2582
2548 (defvar checkdoc-pending-errors nil 2583 (defvar checkdoc-pending-errors nil
2549 "Non-nil when there are errors that have not been displayed yet.") 2584 "Non-nil when there are errors that have not been displayed yet.")
2550 2585
2551 (if checkdoc-output-mode-map 2586 (define-derived-mode checkdoc-output-mode compilation-mode "Checkdoc"
2552 nil 2587 "Set up the major mode for the buffer containing the list of errors."
2553 (setq checkdoc-output-mode-map (make-sparse-keymap)) 2588 (set (make-local-variable 'compilation-error-regexp-alist)
2554 (if (not (string-match "XEmacs" emacs-version)) 2589 checkdoc-output-error-regex-alist)
2555 (define-key checkdoc-output-mode-map [mouse-2] 2590 (set (make-local-variable 'compilation-mode-font-lock-keywords)
2556 'checkdoc-find-error-mouse)) 2591 checkdoc-output-font-lock-keywords))
2557 (define-key checkdoc-output-mode-map "\C-c\C-c" 'checkdoc-find-error)
2558 (define-key checkdoc-output-mode-map "\C-m" 'checkdoc-find-error))
2559
2560 (defun checkdoc-output-mode ()
2561 "Create and setup the buffer used to maintain checkdoc warnings.
2562 \\<checkdoc-output-mode-map>\\[checkdoc-find-error] - Go to this error location
2563 \\[checkdoc-find-error-mouse] - Goto the error clicked on."
2564 (if (get-buffer checkdoc-diagnostic-buffer)
2565 (get-buffer checkdoc-diagnostic-buffer)
2566 (save-excursion
2567 (set-buffer (get-buffer-create checkdoc-diagnostic-buffer))
2568 (kill-all-local-variables)
2569 (setq mode-name "Checkdoc"
2570 major-mode 'checkdoc-output-mode)
2571 (set (make-local-variable 'font-lock-defaults)
2572 '((checkdoc-output-font-lock-keywords) t t ((?- . "w") (?_ . "w"))))
2573 (use-local-map checkdoc-output-mode-map)
2574 (run-hooks 'checkdoc-output-mode-hook)
2575 (current-buffer))))
2576
2577 (defun checkdoc-find-error-mouse (e)
2578 ;; checkdoc-params: (e)
2579 "Call `checkdoc-find-error' where the user clicks the mouse."
2580 (interactive "e")
2581 (mouse-set-point e)
2582 (checkdoc-find-error))
2583
2584 (defun checkdoc-find-error ()
2585 "In a checkdoc diagnostic buffer, find the error under point."
2586 (interactive)
2587 (beginning-of-line)
2588 (if (looking-at "\\(\\(\\w+\\|\\s_\\)+\\.el\\):\\([0-9]+\\):")
2589 (let ((l (string-to-int (match-string 3)))
2590 (f (match-string 1)))
2591 (if (not (get-file-buffer f))
2592 (error "Can't find buffer %s" f))
2593 (switch-to-buffer-other-window (get-file-buffer f))
2594 (goto-line l))))
2595 2592
2596 (defun checkdoc-buffer-label () 2593 (defun checkdoc-buffer-label ()
2597 "The name to use for a checkdoc buffer in the error list." 2594 "The name to use for a checkdoc buffer in the error list."
2598 (if (buffer-file-name) 2595 (if (buffer-file-name)
2599 (file-name-nondirectory (buffer-file-name)) 2596 (file-relative-name (buffer-file-name))
2600 (concat "#<buffer "(buffer-name) ">"))) 2597 (concat "#<buffer "(buffer-name) ">")))
2601 2598
2602 (defun checkdoc-start-section (check-type) 2599 (defun checkdoc-start-section (check-type)
2603 "Initialize the checkdoc diagnostic buffer for a pass. 2600 "Initialize the checkdoc diagnostic buffer for a pass.
2604 Create the header so that the string CHECK-TYPE is displayed as the 2601 Create the header so that the string CHECK-TYPE is displayed as the
2605 function called to create the messages." 2602 function called to create the messages."
2606 (checkdoc-output-to-error-buffer 2603 (let ((dir default-directory)
2607 "\n\n\C-l\n*** " 2604 (label (checkdoc-buffer-label)))
2608 (checkdoc-buffer-label) ": " check-type " V " checkdoc-version)) 2605 (with-current-buffer (get-buffer-create checkdoc-diagnostic-buffer)
2606 (checkdoc-output-mode)
2607 (setq default-directory dir)
2608 (goto-char (point-max))
2609 (insert "\n\n\C-l\n*** " label ": " check-type " V " checkdoc-version))))
2609 2610
2610 (defun checkdoc-error (point msg) 2611 (defun checkdoc-error (point msg)
2611 "Store POINT and MSG as errors in the checkdoc diagnostic buffer." 2612 "Store POINT and MSG as errors in the checkdoc diagnostic buffer."
2612 (setq checkdoc-pending-errors t) 2613 (setq checkdoc-pending-errors t)
2613 (checkdoc-output-to-error-buffer 2614 (let ((text (list "\n" (checkdoc-buffer-label) ":"
2614 "\n" (checkdoc-buffer-label) ":" 2615 (int-to-string
2615 (int-to-string (count-lines (point-min) (or point 1))) ": " 2616 (count-lines (point-min) (or point (point-min))))
2616 msg)) 2617 ": " msg)))
2617 2618 (with-current-buffer (get-buffer checkdoc-diagnostic-buffer)
2618 (defun checkdoc-output-to-error-buffer (&rest text) 2619 (goto-char (point-max))
2619 "Place TEXT into the checkdoc diagnostic buffer." 2620 (apply 'insert text))))
2620 (save-excursion
2621 (set-buffer (checkdoc-output-mode))
2622 (goto-char (point-max))
2623 (apply 'insert text)))
2624 2621
2625 (defun checkdoc-show-diagnostics () 2622 (defun checkdoc-show-diagnostics ()
2626 "Display the checkdoc diagnostic buffer in a temporary window." 2623 "Display the checkdoc diagnostic buffer in a temporary window."
2627 (if checkdoc-pending-errors 2624 (if checkdoc-pending-errors
2628 (let ((b (get-buffer checkdoc-diagnostic-buffer))) 2625 (let ((b (get-buffer checkdoc-diagnostic-buffer)))
2645 (custom-add-option 'emacs-lisp-mode-hook 2642 (custom-add-option 'emacs-lisp-mode-hook
2646 (lambda () (checkdoc-minor-mode 1))) 2643 (lambda () (checkdoc-minor-mode 1)))
2647 2644
2648 (add-to-list 'debug-ignored-errors 2645 (add-to-list 'debug-ignored-errors
2649 "Argument `.*' should appear (as .*) in the doc string") 2646 "Argument `.*' should appear (as .*) in the doc string")
2647 (add-to-list 'debug-ignored-errors
2648 "Lisp symbol `.*' should appear in quotes")
2650 (add-to-list 'debug-ignored-errors "Disambiguate .* by preceding .*") 2649 (add-to-list 'debug-ignored-errors "Disambiguate .* by preceding .*")
2651 2650
2652 (provide 'checkdoc) 2651 (provide 'checkdoc)
2653 2652
2653 ;;; arch-tag: c49a7ec8-3bb7-46f2-bfbc-d5f26e033b26
2654 ;;; checkdoc.el ends here 2654 ;;; checkdoc.el ends here