diff options
| author | Eric M. Ludlam | 1998-05-17 13:20:26 +0000 |
|---|---|---|
| committer | Eric M. Ludlam | 1998-05-17 13:20:26 +0000 |
| commit | a4370a7744b1b5c15b16795e8a22cb26a32eb8c3 (patch) | |
| tree | e5db407a3b7fa060b88dfa8ffb71ae1142f7e8cc /lisp | |
| parent | 10714c98bf986bbb93e81b075148a2fba19f8eda (diff) | |
| download | emacs-a4370a7744b1b5c15b16795e8a22cb26a32eb8c3.tar.gz emacs-a4370a7744b1b5c15b16795e8a22cb26a32eb8c3.zip | |
Updated with latest version. Changes include:
Added checks for basics in messages using `error'.
Added check for symbols that are both functions and symbols.
These references are ambiguous and should be prefixed with
"function", or "variable". Added auto-fix for this also.
Added auto fix for args that do not occur in the doc string.
Fixed question about putting a symbol in `quotes'.
Added spaces to the end of all y/n questions.
Added checks for y/n question endings to require "? "
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/emacs-lisp/checkdoc.el | 260 |
1 files changed, 226 insertions, 34 deletions
diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el index fcc589cc929..88b3d0d231f 100644 --- a/lisp/emacs-lisp/checkdoc.el +++ b/lisp/emacs-lisp/checkdoc.el | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | ;;; Copyright (C) 1997, 1998 Free Software Foundation | 3 | ;;; Copyright (C) 1997, 1998 Free Software Foundation |
| 4 | 4 | ||
| 5 | ;; Author: Eric M. Ludlam <zappo@gnu.org> | 5 | ;; Author: Eric M. Ludlam <zappo@gnu.org> |
| 6 | ;; Version: 0.4.3 | 6 | ;; Version: 0.5.1 |
| 7 | ;; Keywords: docs, maint, lisp | 7 | ;; Keywords: docs, maint, lisp |
| 8 | 8 | ||
| 9 | ;; This file is part of GNU Emacs. | 9 | ;; This file is part of GNU Emacs. |
| @@ -87,6 +87,14 @@ | |||
| 87 | ;; skip looking for it by putting the following comment just in front | 87 | ;; skip looking for it by putting the following comment just in front |
| 88 | ;; of the documentation string: "; checkdoc-params: (args go here)" | 88 | ;; of the documentation string: "; checkdoc-params: (args go here)" |
| 89 | ;; | 89 | ;; |
| 90 | ;; Checking message strings | ||
| 91 | ;; | ||
| 92 | ;; The text that follows the `error', and `y-or-n-p' commands is | ||
| 93 | ;; also checked. The documentation for `error' clearly states some | ||
| 94 | ;; simple style rules to follow which checkdoc will auto-fix for you. | ||
| 95 | ;; `y-or-n-p' also states that it should end in a space. I added that | ||
| 96 | ;; it should end in "? " since that is almost always used. | ||
| 97 | ;; | ||
| 90 | ;; Adding your own checks: | 98 | ;; Adding your own checks: |
| 91 | ;; | 99 | ;; |
| 92 | ;; You can experiment with adding your own checks by setting the | 100 | ;; You can experiment with adding your own checks by setting the |
| @@ -173,6 +181,14 @@ | |||
| 173 | ;; have comments before the doc-string. | 181 | ;; have comments before the doc-string. |
| 174 | ;; Fixed bug where keystrokes were identified from a variable name | 182 | ;; Fixed bug where keystrokes were identified from a variable name |
| 175 | ;; like ASSOC-P. | 183 | ;; like ASSOC-P. |
| 184 | ;; 0.5 Added checks for basics in messages using `error'. | ||
| 185 | ;; Added check for symbols that are both functions and symbols. | ||
| 186 | ;; These references are ambiguous and should be prefixed with | ||
| 187 | ;; "function", or "variable". Added auto-fix for this also. | ||
| 188 | ;; Added auto fix for args that do not occur in the doc string. | ||
| 189 | ;; 0.5.1 Fixed question about putting a symbol in `quotes'. | ||
| 190 | ;; Added spaces to the end of all y/n questions. | ||
| 191 | ;; Added checks for y/n question endings to require "? " | ||
| 176 | 192 | ||
| 177 | ;;; TO DO: | 193 | ;;; TO DO: |
| 178 | ;; Hook into the byte compiler on a defun/defver level to generate | 194 | ;; Hook into the byte compiler on a defun/defver level to generate |
| @@ -186,7 +202,7 @@ | |||
| 186 | ;; not specifically docstring related. Would this even be useful? | 202 | ;; not specifically docstring related. Would this even be useful? |
| 187 | 203 | ||
| 188 | ;;; Code: | 204 | ;;; Code: |
| 189 | (defvar checkdoc-version "0.4.3" | 205 | (defvar checkdoc-version "0.5.1" |
| 190 | "Release version of checkdoc you are currently running.") | 206 | "Release version of checkdoc you are currently running.") |
| 191 | 207 | ||
| 192 | ;; From custom web page for compatibility between versions of custom: | 208 | ;; From custom web page for compatibility between versions of custom: |
| @@ -463,7 +479,7 @@ be re-created.") | |||
| 463 | (defun checkdoc-eval-current-buffer () | 479 | (defun checkdoc-eval-current-buffer () |
| 464 | "Evaluate and check documentation for the current buffer. | 480 | "Evaluate and check documentation for the current buffer. |
| 465 | Evaluation is done first because good documentation for something that | 481 | Evaluation is done first because good documentation for something that |
| 466 | doesn't work is just not useful. Comments, Doc-strings, and rogue | 482 | doesn't work is just not useful. Comments, doc-strings, and rogue |
| 467 | spacing are all verified." | 483 | spacing are all verified." |
| 468 | (interactive) | 484 | (interactive) |
| 469 | (checkdoc-call-eval-buffer nil) | 485 | (checkdoc-call-eval-buffer nil) |
| @@ -471,7 +487,7 @@ spacing are all verified." | |||
| 471 | 487 | ||
| 472 | ;;;###autoload | 488 | ;;;###autoload |
| 473 | (defun checkdoc-current-buffer (&optional take-notes) | 489 | (defun checkdoc-current-buffer (&optional take-notes) |
| 474 | "Check the current buffer for document style, comment style, and rogue spaces. | 490 | "Check current buffer for document, comment, error style, and rogue spaces. |
| 475 | Optional argument TAKE-NOTES non-nil will store all found errors in a | 491 | Optional argument TAKE-NOTES non-nil will store all found errors in a |
| 476 | warnings buffer, otherwise it stops after the first error." | 492 | warnings buffer, otherwise it stops after the first error." |
| 477 | (interactive "P") | 493 | (interactive "P") |
| @@ -483,6 +499,7 @@ warnings buffer, otherwise it stops after the first error." | |||
| 483 | (or (and buffer-file-name ;; only check comments in a file | 499 | (or (and buffer-file-name ;; only check comments in a file |
| 484 | (checkdoc-comments take-notes)) | 500 | (checkdoc-comments take-notes)) |
| 485 | (checkdoc take-notes) | 501 | (checkdoc take-notes) |
| 502 | (checkdoc-message-text take-notes) | ||
| 486 | (checkdoc-rogue-spaces take-notes) | 503 | (checkdoc-rogue-spaces take-notes) |
| 487 | (not (interactive-p)) | 504 | (not (interactive-p)) |
| 488 | (message "Checking buffer for style...Done.")))) | 505 | (message "Checking buffer for style...Done.")))) |
| @@ -651,7 +668,7 @@ if there is one." | |||
| 651 | (interactive "P") | 668 | (interactive "P") |
| 652 | (if take-notes (checkdoc-start-section "checkdoc-comments")) | 669 | (if take-notes (checkdoc-start-section "checkdoc-comments")) |
| 653 | (if (not buffer-file-name) | 670 | (if (not buffer-file-name) |
| 654 | (error "Can only check comments for a file buffer.")) | 671 | (error "Can only check comments for a file buffer")) |
| 655 | (let* ((checkdoc-spellcheck-documentation-flag | 672 | (let* ((checkdoc-spellcheck-documentation-flag |
| 656 | (member checkdoc-spellcheck-documentation-flag | 673 | (member checkdoc-spellcheck-documentation-flag |
| 657 | '(buffer t))) | 674 | '(buffer t))) |
| @@ -717,13 +734,15 @@ space at the end of each line." | |||
| 717 | (let* ((checkdoc-spellcheck-documentation-flag | 734 | (let* ((checkdoc-spellcheck-documentation-flag |
| 718 | (member checkdoc-spellcheck-documentation-flag | 735 | (member checkdoc-spellcheck-documentation-flag |
| 719 | '(defun t))) | 736 | '(defun t))) |
| 737 | (beg (save-excursion (beginning-of-defun) (point))) | ||
| 738 | (end (save-excursion (end-of-defun) (point))) | ||
| 720 | (msg (checkdoc-this-string-valid))) | 739 | (msg (checkdoc-this-string-valid))) |
| 721 | (if msg (if no-error (message msg) (error msg)) | 740 | (if msg (if no-error (message msg) (error msg)) |
| 722 | (setq msg (checkdoc-rogue-space-check-engine | 741 | (setq msg (checkdoc-message-text-search beg end)) |
| 723 | (save-excursion (beginning-of-defun) (point)) | ||
| 724 | (save-excursion (end-of-defun) (point)))) | ||
| 725 | (if msg (if no-error (message msg) (error msg)) | 742 | (if msg (if no-error (message msg) (error msg)) |
| 726 | (if (interactive-p) (message "Checkdoc: done.")))))))) | 743 | (setq msg (checkdoc-rogue-space-check-engine beg end)) |
| 744 | (if msg (if no-error (message msg) (error msg))))) | ||
| 745 | (if (interactive-p) (message "Checkdoc: done.")))))) | ||
| 727 | 746 | ||
| 728 | ;;; Ispell interface for forcing a spell check | 747 | ;;; Ispell interface for forcing a spell check |
| 729 | ;; | 748 | ;; |
| @@ -809,6 +828,7 @@ Prefix argument TAKE-NOTES is the same as for `checkdoc-defun'" | |||
| 809 | (define-key pmap "b" 'checkdoc-current-buffer) | 828 | (define-key pmap "b" 'checkdoc-current-buffer) |
| 810 | (define-key pmap "B" 'checkdoc-ispell-current-buffer) | 829 | (define-key pmap "B" 'checkdoc-ispell-current-buffer) |
| 811 | (define-key pmap "e" 'checkdoc-eval-current-buffer) | 830 | (define-key pmap "e" 'checkdoc-eval-current-buffer) |
| 831 | (define-key pmap "m" 'checkdoc-message-text) | ||
| 812 | (define-key pmap "c" 'checkdoc-comments) | 832 | (define-key pmap "c" 'checkdoc-comments) |
| 813 | (define-key pmap "C" 'checkdoc-ispell-comments) | 833 | (define-key pmap "C" 'checkdoc-ispell-comments) |
| 814 | (define-key pmap " " 'checkdoc-rogue-spaces) | 834 | (define-key pmap " " 'checkdoc-rogue-spaces) |
| @@ -839,6 +859,7 @@ Prefix argument TAKE-NOTES is the same as for `checkdoc-defun'" | |||
| 839 | ["Check Comment Style" checkdoc-comments buffer-file-name] | 859 | ["Check Comment Style" checkdoc-comments buffer-file-name] |
| 840 | ["Check Comment Style and Spelling" checkdoc-ispell-comments | 860 | ["Check Comment Style and Spelling" checkdoc-ispell-comments |
| 841 | buffer-file-name] | 861 | buffer-file-name] |
| 862 | ["Check message text" checkdoc-message-text t] | ||
| 842 | ["Check for Rogue Spaces" checkdoc-rogue-spaces t] | 863 | ["Check for Rogue Spaces" checkdoc-rogue-spaces t] |
| 843 | ))) | 864 | ))) |
| 844 | ;; XEmacs requires some weird stuff to add this menu in a minor mode. | 865 | ;; XEmacs requires some weird stuff to add this menu in a minor mode. |
| @@ -950,7 +971,7 @@ regexp short cuts work." | |||
| 950 | (looking-at "\\([ \t]+\\)[^ \t\n]")) | 971 | (looking-at "\\([ \t]+\\)[^ \t\n]")) |
| 951 | (if (checkdoc-autofix-ask-replace (match-beginning 1) | 972 | (if (checkdoc-autofix-ask-replace (match-beginning 1) |
| 952 | (match-end 1) | 973 | (match-end 1) |
| 953 | "Remove this whitespace?" | 974 | "Remove this whitespace? " |
| 954 | "") | 975 | "") |
| 955 | nil | 976 | nil |
| 956 | "Second line should not have indentation"))) | 977 | "Second line should not have indentation"))) |
| @@ -966,7 +987,7 @@ regexp short cuts work." | |||
| 966 | (setq start (point) | 987 | (setq start (point) |
| 967 | end (1- e))))) | 988 | end (1- e))))) |
| 968 | (if (checkdoc-autofix-ask-replace | 989 | (if (checkdoc-autofix-ask-replace |
| 969 | start end "Remove this whitespace?" "") | 990 | start end "Remove this whitespace? " "") |
| 970 | nil | 991 | nil |
| 971 | "Documentation strings should not start or end with whitespace"))) | 992 | "Documentation strings should not start or end with whitespace"))) |
| 972 | ;; * Every command, function, or variable intended for users to know | 993 | ;; * Every command, function, or variable intended for users to know |
| @@ -1004,7 +1025,7 @@ documentation string")) | |||
| 1004 | nil | 1025 | nil |
| 1005 | (forward-char 1) | 1026 | (forward-char 1) |
| 1006 | (if (checkdoc-autofix-ask-replace | 1027 | (if (checkdoc-autofix-ask-replace |
| 1007 | (point) (1+ (point)) "Add period to sentence?" | 1028 | (point) (1+ (point)) "Add period to sentence? " |
| 1008 | ".\"" t) | 1029 | ".\"" t) |
| 1009 | nil | 1030 | nil |
| 1010 | "First sentence should end with punctuation."))) | 1031 | "First sentence should end with punctuation."))) |
| @@ -1021,7 +1042,7 @@ documentation string")) | |||
| 1021 | ;; Here we have found a complete sentence, but no break. | 1042 | ;; Here we have found a complete sentence, but no break. |
| 1022 | (if (checkdoc-autofix-ask-replace | 1043 | (if (checkdoc-autofix-ask-replace |
| 1023 | (1+ (match-beginning 0)) (match-end 0) | 1044 | (1+ (match-beginning 0)) (match-end 0) |
| 1024 | "First line not a complete sentence. Add CR here?" | 1045 | "First line not a complete sentence. Add RET here? " |
| 1025 | "\n" t) | 1046 | "\n" t) |
| 1026 | (let (l1 l2) | 1047 | (let (l1 l2) |
| 1027 | (forward-line 1) | 1048 | (forward-line 1) |
| @@ -1033,7 +1054,7 @@ documentation string")) | |||
| 1033 | (current-column))) | 1054 | (current-column))) |
| 1034 | (if (> (+ l1 l2 1) 80) | 1055 | (if (> (+ l1 l2 1) 80) |
| 1035 | (setq msg "Incomplete auto-fix. Doc-string \ | 1056 | (setq msg "Incomplete auto-fix. Doc-string \ |
| 1036 | may require more formatting.") | 1057 | may require more formatting") |
| 1037 | ;; We can merge these lines! Replace this CR | 1058 | ;; We can merge these lines! Replace this CR |
| 1038 | ;; with a space. | 1059 | ;; with a space. |
| 1039 | (delete-char 1) (insert " ") | 1060 | (delete-char 1) (insert " ") |
| @@ -1052,7 +1073,7 @@ may require more formatting.") | |||
| 1052 | (< (current-column) numc)) | 1073 | (< (current-column) numc)) |
| 1053 | (if (checkdoc-autofix-ask-replace | 1074 | (if (checkdoc-autofix-ask-replace |
| 1054 | p (1+ p) | 1075 | p (1+ p) |
| 1055 | "1st line not a complete sentence. Join these lines?" | 1076 | "1st line not a complete sentence. Join these lines? " |
| 1056 | " " t) | 1077 | " " t) |
| 1057 | (progn | 1078 | (progn |
| 1058 | ;; They said yes. We have more fill work to do... | 1079 | ;; They said yes. We have more fill work to do... |
| @@ -1066,10 +1087,10 @@ may require more formatting.") | |||
| 1066 | (if (looking-at "[a-z]") | 1087 | (if (looking-at "[a-z]") |
| 1067 | (if (checkdoc-autofix-ask-replace | 1088 | (if (checkdoc-autofix-ask-replace |
| 1068 | (match-beginning 0) (match-end 0) | 1089 | (match-beginning 0) (match-end 0) |
| 1069 | "Capitalize your sentence?" (upcase (match-string 0)) | 1090 | "Capitalize your sentence? " (upcase (match-string 0)) |
| 1070 | t) | 1091 | t) |
| 1071 | nil | 1092 | nil |
| 1072 | "First line should be capitalized.") | 1093 | "First line should be capitalized") |
| 1073 | nil)) | 1094 | nil)) |
| 1074 | ;; * For consistency, phrase the verb in the first sentence of a | 1095 | ;; * For consistency, phrase the verb in the first sentence of a |
| 1075 | ;; documentation string as an infinitive with "to" omitted. For | 1096 | ;; documentation string as an infinitive with "to" omitted. For |
| @@ -1100,7 +1121,7 @@ may require more formatting.") | |||
| 1100 | (match-beginning 1) (match-end 1)) | 1121 | (match-beginning 1) (match-end 1)) |
| 1101 | rs (assoc (downcase original) | 1122 | rs (assoc (downcase original) |
| 1102 | checkdoc-common-verbs-wrong-voice)) | 1123 | checkdoc-common-verbs-wrong-voice)) |
| 1103 | (if (not rs) (error "Verb voice alist corrupted.")) | 1124 | (if (not rs) (error "Verb voice alist corrupted")) |
| 1104 | (setq replace (let ((case-fold-search nil)) | 1125 | (setq replace (let ((case-fold-search nil)) |
| 1105 | (save-match-data | 1126 | (save-match-data |
| 1106 | (if (string-match "^[A-Z]" original) | 1127 | (if (string-match "^[A-Z]" original) |
| @@ -1108,14 +1129,14 @@ may require more formatting.") | |||
| 1108 | (cdr rs))))) | 1129 | (cdr rs))))) |
| 1109 | (if (checkdoc-autofix-ask-replace | 1130 | (if (checkdoc-autofix-ask-replace |
| 1110 | (match-beginning 1) (match-end 1) | 1131 | (match-beginning 1) (match-end 1) |
| 1111 | (format "Wrong voice for verb `%s'. Replace with `%s'?" | 1132 | (format "Wrong voice for verb `%s'. Replace with `%s'? " |
| 1112 | original replace) | 1133 | original replace) |
| 1113 | replace t) | 1134 | replace t) |
| 1114 | (setq rs nil))) | 1135 | (setq rs nil))) |
| 1115 | (if rs | 1136 | (if rs |
| 1116 | ;; there was a match, but no replace | 1137 | ;; there was a match, but no replace |
| 1117 | (format | 1138 | (format |
| 1118 | "Incorrect voice in sentence. Use `%s' instead of `%s'." | 1139 | "Incorrect voice in sentence. Use `%s' instead of `%s'" |
| 1119 | replace original))))) | 1140 | replace original))))) |
| 1120 | ;; * Don't write key sequences directly in documentation strings. | 1141 | ;; * Don't write key sequences directly in documentation strings. |
| 1121 | ;; Instead, use the `\\[...]' construct to stand for them. | 1142 | ;; Instead, use the `\\[...]' construct to stand for them. |
| @@ -1139,6 +1160,40 @@ mouse-[0-3]\\)\\)\\>")) | |||
| 1139 | (if (re-search-forward "\\\\\\\\\\[\\w+" e t | 1160 | (if (re-search-forward "\\\\\\\\\\[\\w+" e t |
| 1140 | (1+ checkdoc-max-keyref-before-warn)) | 1161 | (1+ checkdoc-max-keyref-before-warn)) |
| 1141 | "Too many occurrences of \\[function]. Use \\{keymap} instead")) | 1162 | "Too many occurrences of \\[function]. Use \\{keymap} instead")) |
| 1163 | ;; Ambiguous quoted symbol. When a symbol is both bound and fbound, | ||
| 1164 | ;; and is referred to in documentation, it should be prefixed with | ||
| 1165 | ;; something to disambiguate it. This check must be before the | ||
| 1166 | ;; 80 column check because it will probably break that. | ||
| 1167 | (save-excursion | ||
| 1168 | (let ((case-fold-search t) | ||
| 1169 | (ret nil)) | ||
| 1170 | (while (and | ||
| 1171 | (re-search-forward | ||
| 1172 | "\\(\\<\\(variable\\|option\\|function\\|command\\|symbol\\)\ | ||
| 1173 | \\s-+\\)?`\\(\\sw\\(\\sw\\|\\s_\\)+\\)'" e t) | ||
| 1174 | (not ret)) | ||
| 1175 | (let ((sym (intern-soft (match-string 3))) | ||
| 1176 | (mb (match-beginning 3))) | ||
| 1177 | (if (and sym (boundp sym) (fboundp sym) (not (match-string 1))) | ||
| 1178 | (if (checkdoc-autofix-ask-replace | ||
| 1179 | mb (match-end 3) "Prefix this ambiguous symbol? " | ||
| 1180 | (match-string 3) t) | ||
| 1181 | ;; We didn't actuall replace anything. Here we find | ||
| 1182 | ;; out what special word form they wish to use as | ||
| 1183 | ;; a prefix. | ||
| 1184 | (let ((disambiguate | ||
| 1185 | (completing-read | ||
| 1186 | "Disambiguating Keyword (default: variable): " | ||
| 1187 | '(("function") ("command") ("variable") | ||
| 1188 | ("option") ("symbol")) | ||
| 1189 | nil t nil nil "variable"))) | ||
| 1190 | (goto-char (1- mb)) | ||
| 1191 | (insert disambiguate " ") | ||
| 1192 | (forward-word 1)) | ||
| 1193 | (setq ret | ||
| 1194 | (format "Disambiguate %s by preceeding w/ \ | ||
| 1195 | function,command,variable,option or symbol." (match-string 3))))))) | ||
| 1196 | ret)) | ||
| 1142 | ;; * Format the documentation string so that it fits in an | 1197 | ;; * Format the documentation string so that it fits in an |
| 1143 | ;; Emacs window on an 80-column screen. It is a good idea | 1198 | ;; Emacs window on an 80-column screen. It is a good idea |
| 1144 | ;; for most lines to be no wider than 60 characters. The | 1199 | ;; for most lines to be no wider than 60 characters. The |
| @@ -1179,7 +1234,7 @@ mouse-[0-3]\\)\\)\\>")) | |||
| 1179 | (setq found (intern-soft ms)) | 1234 | (setq found (intern-soft ms)) |
| 1180 | (or (boundp found) (fboundp found))) | 1235 | (or (boundp found) (fboundp found))) |
| 1181 | (progn | 1236 | (progn |
| 1182 | (setq msg (format "Lisp symbol %s should appear in `quotes'" | 1237 | (setq msg (format "Add quotes around lisp symbol `%s'? " |
| 1183 | ms)) | 1238 | ms)) |
| 1184 | (if (checkdoc-autofix-ask-replace | 1239 | (if (checkdoc-autofix-ask-replace |
| 1185 | (match-beginning 1) (+ (match-beginning 1) | 1240 | (match-beginning 1) (+ (match-beginning 1) |
| @@ -1192,7 +1247,7 @@ mouse-[0-3]\\)\\)\\>")) | |||
| 1192 | (if (re-search-forward "\\(`\\(t\\|nil\\)'\\)" e t) | 1247 | (if (re-search-forward "\\(`\\(t\\|nil\\)'\\)" e t) |
| 1193 | (if (checkdoc-autofix-ask-replace | 1248 | (if (checkdoc-autofix-ask-replace |
| 1194 | (match-beginning 1) (match-end 1) | 1249 | (match-beginning 1) (match-end 1) |
| 1195 | (format "%s should not appear in quotes. Remove?" | 1250 | (format "%s should not appear in quotes. Remove? " |
| 1196 | (match-string 2)) | 1251 | (match-string 2)) |
| 1197 | (match-string 2) t) | 1252 | (match-string 2) t) |
| 1198 | nil | 1253 | nil |
| @@ -1235,10 +1290,12 @@ mouse-[0-3]\\)\\)\\>")) | |||
| 1235 | (last-pos 0) | 1290 | (last-pos 0) |
| 1236 | (found 1) | 1291 | (found 1) |
| 1237 | (order (and (nth 3 fp) (car (nth 3 fp)))) | 1292 | (order (and (nth 3 fp) (car (nth 3 fp)))) |
| 1238 | (nocheck (append '("&optional" "&rest") (nth 3 fp)))) | 1293 | (nocheck (append '("&optional" "&rest") (nth 3 fp))) |
| 1294 | (inopts nil)) | ||
| 1239 | (while (and args found (> found last-pos)) | 1295 | (while (and args found (> found last-pos)) |
| 1240 | (if (member (car args) nocheck) | 1296 | (if (member (car args) nocheck) |
| 1241 | (setq args (cdr args)) | 1297 | (setq args (cdr args) |
| 1298 | inopts t) | ||
| 1242 | (setq last-pos found | 1299 | (setq last-pos found |
| 1243 | found (save-excursion | 1300 | found (save-excursion |
| 1244 | (re-search-forward | 1301 | (re-search-forward |
| @@ -1264,15 +1321,32 @@ mouse-[0-3]\\)\\)\\>")) | |||
| 1264 | (if (checkdoc-autofix-ask-replace | 1321 | (if (checkdoc-autofix-ask-replace |
| 1265 | (match-beginning 1) (match-end 1) | 1322 | (match-beginning 1) (match-end 1) |
| 1266 | (format | 1323 | (format |
| 1267 | "Argument `%s' should appear as `%s'. Fix?" | 1324 | "Argument `%s' should appear as `%s'. Fix? " |
| 1268 | (car args) (upcase (car args))) | 1325 | (car args) (upcase (car args))) |
| 1269 | (upcase (car args)) t) | 1326 | (upcase (car args)) t) |
| 1270 | (setq found (match-beginning 1)))))) | 1327 | (setq found (match-beginning 1)))))) |
| 1271 | (if found (setq args (cdr args))))) | 1328 | (if found (setq args (cdr args))))) |
| 1272 | (if (not found) | 1329 | (if (not found) |
| 1273 | (format | 1330 | ;; It wasn't found at all! Offer to attach this new symbol |
| 1274 | "Argument `%s' should appear as `%s' in the doc-string" | 1331 | ;; to the end of the documentation string. |
| 1275 | (car args) (upcase (car args))) | 1332 | (if (y-or-n-p |
| 1333 | (format "Add %s documentation to end of doc-string?" | ||
| 1334 | (upcase (car args)))) | ||
| 1335 | ;; No do some majic an invent a doc string. | ||
| 1336 | (save-excursion | ||
| 1337 | (goto-char e) (forward-char -1) | ||
| 1338 | (insert "\n" | ||
| 1339 | (if inopts "Optional a" "A") | ||
| 1340 | "rgument " (upcase (car args)) | ||
| 1341 | " ") | ||
| 1342 | (insert (read-string "Describe: ")) | ||
| 1343 | (if (not (save-excursion (forward-char -1) | ||
| 1344 | (looking-at "[.?!]"))) | ||
| 1345 | (insert ".")) | ||
| 1346 | nil) | ||
| 1347 | (format | ||
| 1348 | "Argument `%s' should appear as `%s' in the doc-string" | ||
| 1349 | (car args) (upcase (car args)))) | ||
| 1276 | (if (or (and order (eq order 'yes)) | 1350 | (if (or (and order (eq order 'yes)) |
| 1277 | (and (not order) checkdoc-arguments-in-order-flag)) | 1351 | (and (not order) checkdoc-arguments-in-order-flag)) |
| 1278 | (if (< found last-pos) | 1352 | (if (< found last-pos) |
| @@ -1488,9 +1562,9 @@ Some editors & news agents may remove it"))) | |||
| 1488 | ;; This is not a complex activity | 1562 | ;; This is not a complex activity |
| 1489 | (if (checkdoc-autofix-ask-replace | 1563 | (if (checkdoc-autofix-ask-replace |
| 1490 | (match-beginning 1) (match-end 1) | 1564 | (match-beginning 1) (match-end 1) |
| 1491 | "White space at end of line. Remove?" "") | 1565 | "White space at end of line. Remove? " "") |
| 1492 | nil | 1566 | nil |
| 1493 | (setq msg "White space found at end of line."))))) | 1567 | (setq msg "White space found at end of line"))))) |
| 1494 | ;; Return an error and leave the cursor at that spot, or restore | 1568 | ;; Return an error and leave the cursor at that spot, or restore |
| 1495 | ;; the cursor. | 1569 | ;; the cursor. |
| 1496 | (if msg | 1570 | (if msg |
| @@ -1530,7 +1604,7 @@ Code:, and others referenced in the style guide." | |||
| 1530 | ;; it's set to never | 1604 | ;; it's set to never |
| 1531 | (if (and checkdoc-autofix-flag | 1605 | (if (and checkdoc-autofix-flag |
| 1532 | (not (eq checkdoc-autofix-flag 'never)) | 1606 | (not (eq checkdoc-autofix-flag 'never)) |
| 1533 | (y-or-n-p "There is no first line summary! Add one?")) | 1607 | (y-or-n-p "There is no first line summary! Add one? ")) |
| 1534 | (progn | 1608 | (progn |
| 1535 | (goto-char (point-min)) | 1609 | (goto-char (point-min)) |
| 1536 | (insert ";;; " fn fe " --- " (read-string "Summary: ") "\n")) | 1610 | (insert ";;; " fn fe " --- " (read-string "Summary: ") "\n")) |
| @@ -1573,7 +1647,7 @@ Code:, and others referenced in the style guide." | |||
| 1573 | nil t)) | 1647 | nil t)) |
| 1574 | (if (and checkdoc-autofix-flag | 1648 | (if (and checkdoc-autofix-flag |
| 1575 | (not (eq checkdoc-autofix-flag 'never)) | 1649 | (not (eq checkdoc-autofix-flag 'never)) |
| 1576 | (y-or-n-p "No identifiable footer! Add one?")) | 1650 | (y-or-n-p "No identifiable footer! Add one? ")) |
| 1577 | (progn | 1651 | (progn |
| 1578 | (goto-char (point-max)) | 1652 | (goto-char (point-max)) |
| 1579 | (insert "\n(provide '" fn ")\n;;; " fn fe " ends here\n")) | 1653 | (insert "\n(provide '" fn ")\n;;; " fn fe " ends here\n")) |
| @@ -1600,8 +1674,8 @@ Code:, and others referenced in the style guide." | |||
| 1600 | (if (and (checkdoc-outside-major-sexp) ;in code is ok. | 1674 | (if (and (checkdoc-outside-major-sexp) ;in code is ok. |
| 1601 | (checkdoc-autofix-ask-replace | 1675 | (checkdoc-autofix-ask-replace |
| 1602 | (match-beginning 1) (match-end 1) | 1676 | (match-beginning 1) (match-end 1) |
| 1603 | "Multiple occurances of ;;; found. Use ;; instead?" "" | 1677 | "Multiple occurances of ;;; found. Use ;; instead? " |
| 1604 | complex-replace)) | 1678 | "" complex-replace)) |
| 1605 | ;; Learn that, yea, the user did want to do this a | 1679 | ;; Learn that, yea, the user did want to do this a |
| 1606 | ;; whole bunch of times. | 1680 | ;; whole bunch of times. |
| 1607 | (setq complex-replace nil)) | 1681 | (setq complex-replace nil)) |
| @@ -1636,6 +1710,124 @@ Code:, and others referenced in the style guide." | |||
| 1636 | (or (progn (beginning-of-defun) (bobp)) | 1710 | (or (progn (beginning-of-defun) (bobp)) |
| 1637 | (progn (end-of-defun) (< (point) p))))))) | 1711 | (progn (end-of-defun) (< (point) p))))))) |
| 1638 | 1712 | ||
| 1713 | ;;; `error' and `message' text verifier. | ||
| 1714 | ;; | ||
| 1715 | (defun checkdoc-message-text (&optional take-notes) | ||
| 1716 | "Scan the buffer for occurrences of the error function, and verify text. | ||
| 1717 | Optional argument TAKE-NOTES causes all errors to be logged." | ||
| 1718 | (interactive "P") | ||
| 1719 | (if take-notes (checkdoc-start-section "checkdoc-message-text")) | ||
| 1720 | (let ((p (point)) | ||
| 1721 | (e (checkdoc-message-text-search))) | ||
| 1722 | (if e (if take-notes (checkdoc-error (point) e) (error e))) | ||
| 1723 | (if (and take-notes e) (checkdoc-show-diagnostics)) | ||
| 1724 | (goto-char p)) | ||
| 1725 | (if (interactive-p) (message "Checking error message text...done."))) | ||
| 1726 | |||
| 1727 | (defun checkdoc-message-text-search (&optional beg end) | ||
| 1728 | "Search between BEG and END for an error with `error'. | ||
| 1729 | Optional arguments BEG and END represent the boundary of the check. | ||
| 1730 | The default boundary is the entire buffer." | ||
| 1731 | (let ((e nil)) | ||
| 1732 | (if (not (or beg end)) (setq beg (point-min) end (point-max))) | ||
| 1733 | (goto-char beg) | ||
| 1734 | (while (and (not e) (re-search-forward "(\\s-*error[ \t\n]" end t)) | ||
| 1735 | (if (looking-at "\"") | ||
| 1736 | (setq e (checkdoc-message-text-engine 'error)))) | ||
| 1737 | (goto-char beg) | ||
| 1738 | (while (and (not e) (re-search-forward | ||
| 1739 | "\\<y-or-n-p\\(-with-timeout\\)?[ \t\n]" end t)) | ||
| 1740 | ;; Format is common as a first arg.. | ||
| 1741 | (if (looking-at "(format[ \t\n]") (goto-char (match-end 0))) | ||
| 1742 | (if (looking-at "\"") | ||
| 1743 | (setq e (checkdoc-message-text-engine 'y-or-n-p)))) | ||
| 1744 | (goto-char beg) | ||
| 1745 | ;; this is cheating for checkdoc only. | ||
| 1746 | (while (and (not e) (re-search-forward | ||
| 1747 | "(checkdoc-autofix-ask-replace[ \t\n]" | ||
| 1748 | end t)) | ||
| 1749 | (forward-sexp 2) | ||
| 1750 | (skip-chars-forward " \t\n") | ||
| 1751 | (if (looking-at "(format[ \t\n]") (goto-char (match-end 0))) | ||
| 1752 | (if (looking-at "\"") | ||
| 1753 | (setq e (checkdoc-message-text-engine 'y-or-n-p)))) | ||
| 1754 | ;; Is it worth adding checks for read commands too? That would | ||
| 1755 | ;; require fixing up `interactive' which could be unpleasant. | ||
| 1756 | ;; Most people get that right by accident anyway. | ||
| 1757 | e)) | ||
| 1758 | |||
| 1759 | (defun checkdoc-message-text-engine (type) | ||
| 1760 | "Return or fix errors found in strings passed to a message display function. | ||
| 1761 | According to the documentation for the function `error', the error string | ||
| 1762 | should not end with a period, and should start with a capitol letter. | ||
| 1763 | The function `y-or-n-p' has similar constraints. | ||
| 1764 | Argument TYPE specifies the type of question, such as `error or `y-or-n-p." | ||
| 1765 | (let ((case-fold-search nil)) | ||
| 1766 | (or | ||
| 1767 | ;; From the documentation of the symbol `error': | ||
| 1768 | ;; In Emacs, the convention is that error messages start with a capital | ||
| 1769 | ;; letter but *do not* end with a period. Please follow this convention | ||
| 1770 | ;; for the sake of consistency. | ||
| 1771 | (if (and (save-excursion (forward-char 1) | ||
| 1772 | (looking-at "[a-z]\\w+")) | ||
| 1773 | (not (checkdoc-autofix-ask-replace | ||
| 1774 | (match-beginning 0) (match-end 0) | ||
| 1775 | "Capitalize your message text? " | ||
| 1776 | (capitalize (match-string 0)) | ||
| 1777 | t))) | ||
| 1778 | "Messages should start with a capitol letter" | ||
| 1779 | nil) | ||
| 1780 | (if (and (eq type 'error) | ||
| 1781 | (save-excursion (forward-sexp 1) | ||
| 1782 | (forward-char -2) | ||
| 1783 | (looking-at "\\.")) | ||
| 1784 | (not (checkdoc-autofix-ask-replace (match-beginning 0) | ||
| 1785 | (match-end 0) | ||
| 1786 | "Remove period from error? " | ||
| 1787 | "" | ||
| 1788 | t))) | ||
| 1789 | "Error messages should *not* end with a period" | ||
| 1790 | nil) | ||
| 1791 | ;; `y-or-n-p' documentation explicitly says: | ||
| 1792 | ;; It should end in a space; `y-or-n-p' adds `(y or n) ' to it. | ||
| 1793 | ;; I added the ? requirement. Without it, it is unclear that we | ||
| 1794 | ;; ask a question and it appears to be an undocumented style. | ||
| 1795 | (if (and (eq type 'y-or-n-p) | ||
| 1796 | (save-excursion (forward-sexp 1) | ||
| 1797 | (forward-char -3) | ||
| 1798 | (not (looking-at "\\? "))) | ||
| 1799 | (if (save-excursion (forward-sexp 1) | ||
| 1800 | (forward-char -2) | ||
| 1801 | (looking-at "\\?")) | ||
| 1802 | ;; If we see a ?, then replace with "? ". | ||
| 1803 | (if (checkdoc-autofix-ask-replace | ||
| 1804 | (match-beginning 0) (match-end 0) | ||
| 1805 | "y-or-n-p text should endwith \"? \". Fix? " | ||
| 1806 | "? " t) | ||
| 1807 | nil | ||
| 1808 | "y-or-n-p text should endwith \"? \".") | ||
| 1809 | (if (save-excursion (forward-sexp 1) | ||
| 1810 | (forward-char -2) | ||
| 1811 | (looking-at " ")) | ||
| 1812 | (if (checkdoc-autofix-ask-replace | ||
| 1813 | (match-beginning 0) (match-end 0) | ||
| 1814 | "y-or-n-p text should endwith \"? \". Fix? " | ||
| 1815 | "? " t) | ||
| 1816 | nil | ||
| 1817 | "y-or-n-p text should endwith \"? \".") | ||
| 1818 | (if (and ;; if this isn't true, we have a problem. | ||
| 1819 | (save-excursion (forward-sexp 1) | ||
| 1820 | (forward-char -1) | ||
| 1821 | (looking-at "\"")) | ||
| 1822 | (checkdoc-autofix-ask-replace | ||
| 1823 | (match-beginning 0) (match-end 0) | ||
| 1824 | "y-or-n-p text should endwith \"? \". Fix? " | ||
| 1825 | "? \"" t)) | ||
| 1826 | nil | ||
| 1827 | "y-or-n-p text should endwith \"? \".")))) | ||
| 1828 | nil) | ||
| 1829 | ))) | ||
| 1830 | |||
| 1639 | ;;; Auto-fix helper functions | 1831 | ;;; Auto-fix helper functions |
| 1640 | ;; | 1832 | ;; |
| 1641 | (defun checkdoc-autofix-ask-replace (start end question replacewith | 1833 | (defun checkdoc-autofix-ask-replace (start end question replacewith |