Mercurial > emacs
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 |