aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorEric M. Ludlam1998-05-17 13:20:26 +0000
committerEric M. Ludlam1998-05-17 13:20:26 +0000
commita4370a7744b1b5c15b16795e8a22cb26a32eb8c3 (patch)
treee5db407a3b7fa060b88dfa8ffb71ae1142f7e8cc /lisp
parent10714c98bf986bbb93e81b075148a2fba19f8eda (diff)
downloademacs-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.el260
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.
465Evaluation is done first because good documentation for something that 481Evaluation is done first because good documentation for something that
466doesn't work is just not useful. Comments, Doc-strings, and rogue 482doesn't work is just not useful. Comments, doc-strings, and rogue
467spacing are all verified." 483spacing 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.
475Optional argument TAKE-NOTES non-nil will store all found errors in a 491Optional argument TAKE-NOTES non-nil will store all found errors in a
476warnings buffer, otherwise it stops after the first error." 492warnings 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 \
1036may require more formatting.") 1057may 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/ \
1195function,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.
1717Optional 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'.
1729Optional arguments BEG and END represent the boundary of the check.
1730The 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.
1761According to the documentation for the function `error', the error string
1762should not end with a period, and should start with a capitol letter.
1763The function `y-or-n-p' has similar constraints.
1764Argument 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