-;;; checkdoc.el --- check documentation strings for style requirements
+;;; checkdoc.el --- check documentation strings for style requirements -*- lexical-binding:t -*-
-;; Copyright (C) 1997-1998, 2001-2013 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998, 2001-2015 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
;; Version: 0.6.2
(defcustom checkdoc-minor-mode-string " CDoc"
"String to display in mode line when Checkdoc mode is enabled; nil for none."
:type '(choice string (const :tag "None" nil))
- :group 'checkdoc
:version "23.1")
(defcustom checkdoc-autofix-flag 'semiautomatic
is `semiautomatic' or any other value, then simple fixes are made
without asking, and complex changes are made by asking the user first.
The value `never' is the same as nil, never ask or change anything."
- :group 'checkdoc
:type '(choice (const automatic)
(const query)
(const never)
"Non-nil means to \"bounce\" to auto-fix locations.
Setting this to nil will silently make fixes that require no user
interaction. See `checkdoc-autofix-flag' for auto-fixing details."
- :group 'checkdoc
:type 'boolean)
(defcustom checkdoc-force-docstrings-flag t
Style guide dictates that interactive functions MUST have documentation,
and that it's good but not required practice to make non user visible items
have doc strings."
- :group 'checkdoc
:type 'boolean)
-;;;###autoload(put 'checkdoc-force-docstrings-flag 'safe-local-variable 'booleanp)
+;;;###autoload(put 'checkdoc-force-docstrings-flag 'safe-local-variable #'booleanp)
(defcustom checkdoc-force-history-flag nil
"Non-nil means that files should have a History section or ChangeLog file.
This helps document the evolution of, and recent changes to, the package."
- :group 'checkdoc
:type 'boolean)
-;;;###autoload(put 'checkdoc-force-history-flag 'safe-local-variable 'booleanp)
+;;;###autoload(put 'checkdoc-force-history-flag 'safe-local-variable #'booleanp)
(defcustom checkdoc-permit-comma-termination-flag nil
"Non-nil means the first line of a docstring may end with a comma.
there is a substantial caveat to the one-line description -- the comma
should be used when the first part could stand alone as a sentence, but
it indicates that a modifying clause follows."
- :group 'checkdoc
:type 'boolean)
-;;;###autoload(put 'checkdoc-permit-comma-termination-flag 'safe-local-variable 'booleanp)
+;;;###autoload(put 'checkdoc-permit-comma-termination-flag 'safe-local-variable #'booleanp)
(defcustom checkdoc-spellcheck-documentation-flag nil
"Non-nil means run Ispell on text based on value.
buffer - Spell-check when style checking the whole buffer
interactive - Spell-check during any interactive check.
t - Always spell-check"
- :group 'checkdoc
:type '(choice (const nil)
(const defun)
(const buffer)
(const interactive)
(const t)))
+;;;###autoload(put 'checkdoc-spellcheck-documentation-flag 'safe-local-variable #'booleanp)
(defvar checkdoc-ispell-lisp-words
'("alist" "emacs" "etags" "keymap" "paren" "regexp" "sexp" "xemacs")
"List of words that are correct when spell-checking Lisp documentation.")
+;;;###autoload(put 'checkdoc-ispell-list-words 'safe-local-variable #'checkdoc-list-of-strings-p)
(defcustom checkdoc-max-keyref-before-warn 10
"The number of \\ [command-to-keystroke] tokens allowed in a doc string.
Any more than this and a warning is generated suggesting that the construct
\\ {keymap} be used instead."
- :group 'checkdoc
:type 'integer)
(defcustom checkdoc-arguments-in-order-flag t
appear in the proper form in the documentation, not that they are in
the same order as they appear in the argument list. No mention is
made in the style guide relating to order."
- :group 'checkdoc
:type 'boolean)
-;;;###autoload(put 'checkdoc-arguments-in-order-flag 'safe-local-variable 'booleanp)
+;;;###autoload(put 'checkdoc-arguments-in-order-flag 'safe-local-variable #'booleanp)
+
+(defcustom checkdoc-package-keywords-flag nil
+ "Non-nil means warn if this file's package keywords are not recognized.
+Currently, all recognized keywords must be on `finder-known-keywords'."
+ :version "25.1"
+ :type 'boolean)
(define-obsolete-variable-alias 'checkdoc-style-hooks
'checkdoc-style-functions "24.3")
"Non-nil means to attempt to check the voice of the doc string.
This check keys off some words which are commonly misused. See the
variable `checkdoc-common-verbs-wrong-voice' if you wish to add your own."
- :group 'checkdoc
:type 'boolean)
+;;;###autoload(put 'checkdoc-verb-check-experimental-flag 'safe-local-variable #'booleanp)
(defvar checkdoc-generate-compile-warnings-flag nil
"Non-nil means generate warnings in a buffer for browsing.
"A list of symbol names (strings) which also happen to make good words.
These words are ignored when unquoted symbols are searched for.
This should be set in an Emacs Lisp file's local variables."
- :group 'checkdoc
:type '(repeat (symbol :tag "Word")))
-;;;###autoload(put 'checkdoc-symbol-words 'safe-local-variable 'checkdoc-list-of-strings-p)
+;;;###autoload(put 'checkdoc-symbol-words 'safe-local-variable #'checkdoc-list-of-strings-p)
;;;###autoload
(defun checkdoc-list-of-strings-p (obj)
+ "Return t when OBJ is a list of strings."
;; this is a function so it might be shared by checkdoc-proper-noun-list
;; and/or checkdoc-ispell-lisp-words in the future
(and (listp obj)
- (not (memq nil (mapcar 'stringp obj)))))
+ (not (memq nil (mapcar #'stringp obj)))))
(defvar checkdoc-proper-noun-list
'("ispell" "xemacs" "emacs" "lisp")
(regexp-opt checkdoc-proper-noun-list t)
"\\(\\_>\\|[.!?][ \t\n\"]\\)")
"Regular expression derived from `checkdoc-proper-noun-regexp'.")
+;;;###autoload(put 'checkdoc-proper-noun-regexp 'safe-local-variable 'stringp)
(defvar checkdoc-common-verbs-regexp nil
"Regular expression derived from `checkdoc-common-verbs-regexp'.")
+;;;###autoload(put 'checkdoc-common-verbs-regexp 'safe-local-variable 'stringp)
(defvar checkdoc-common-verbs-wrong-voice
'(("adds" . "add")
;;; Compatibility
;;
(defalias 'checkdoc-make-overlay
- (if (featurep 'xemacs) 'make-extent 'make-overlay))
+ (if (featurep 'xemacs) #'make-extent #'make-overlay))
(defalias 'checkdoc-overlay-put
- (if (featurep 'xemacs) 'set-extent-property 'overlay-put))
+ (if (featurep 'xemacs) #'set-extent-property #'overlay-put))
(defalias 'checkdoc-delete-overlay
- (if (featurep 'xemacs) 'delete-extent 'delete-overlay))
+ (if (featurep 'xemacs) #'delete-extent #'delete-overlay))
(defalias 'checkdoc-overlay-start
- (if (featurep 'xemacs) 'extent-start 'overlay-start))
+ (if (featurep 'xemacs) #'extent-start #'overlay-start))
(defalias 'checkdoc-overlay-end
- (if (featurep 'xemacs) 'extent-end 'overlay-end))
+ (if (featurep 'xemacs) #'extent-end #'overlay-end))
(defalias 'checkdoc-mode-line-update
- (if (featurep 'xemacs) 'redraw-modeline 'force-mode-line-update))
+ (if (featurep 'xemacs) #'redraw-modeline #'force-mode-line-update))
(defalias 'checkdoc-char=
- (if (featurep 'xemacs) 'char= '=))
+ (if (featurep 'xemacs) #'char= #'=))
;;; User level commands
;;
;; Due to a design flaw, this will never spell check
;; docstrings.
(checkdoc-interactive-loop start-here showstatus
- 'checkdoc-next-error)
+ #'checkdoc-next-error)
;; This is a workaround to perform spell checking.
(checkdoc-interactive-ispell-loop start-here))))
(prog1
;; Due to a design flaw, this will never spell check messages.
(checkdoc-interactive-loop start-here showstatus
- 'checkdoc-next-message-error)
+ #'checkdoc-next-message-error)
;; This is a workaround to perform spell checking.
(checkdoc-message-interactive-ispell-loop start-here))))
(goto-char (cdr (car err-list)))
;; `automatic-then-never' tells the autofix function
;; to only allow one fix to be automatic. The autofix
- ;; function will then set the flag to 'never, allowing
+ ;; function will then set the flag to `never', allowing
;; the checker to return a different error.
(let ((checkdoc-autofix-flag 'automatic-then-never)
(fixed nil))
;; Loop over docstrings.
(while (checkdoc-next-docstring)
(message "Searching for doc string spell error...%d%%"
- (/ (* 100 (point)) (point-max)))
+ (floor (* 100.0 (point)) (point-max)))
(if (looking-at "\"")
(checkdoc-ispell-docstring-engine
(save-excursion (forward-sexp 1) (point-marker)))))
;; Loop over message strings.
(while (checkdoc-message-text-next-string (point-max))
(message "Searching for message string spell error...%d%%"
- (/ (* 100 (point)) (point-max)))
+ (floor (* 100.0 (point)) (point-max)))
(if (looking-at "\"")
(checkdoc-ispell-docstring-engine
(save-excursion (forward-sexp 1) (point-marker)))))
(condition-case nil
(while (and (not msg) (checkdoc-next-docstring))
(message "Searching for doc string error...%d%%"
- (/ (* 100 (point)) (point-max)))
+ (floor (* 100.0 (point)) (point-max)))
(if (setq msg (checkdoc-this-string-valid))
(setq msg (cons msg (point)))))
;; Quit.. restore position, Other errors, leave alone
(setq type
(checkdoc-message-text-next-string (point-max))))
(message "Searching for message string error...%d%%"
- (/ (* 100 (point)) (point-max)))
+ (floor (* 100.0 (point)) (point-max)))
(if (setq msg (checkdoc-message-text-engine type))
(setq msg (cons msg (point)))))
;; Quit.. restore position, Other errors, leave alone
(checkdoc-start)
(checkdoc-message-text)
(checkdoc-rogue-spaces)
+ (when checkdoc-package-keywords-flag
+ (checkdoc-package-keywords))
(not (called-interactively-p 'interactive))
(if take-notes (checkdoc-show-diagnostics))
(message "Checking buffer for style...Done."))))
+;;;###autoload
+(defun checkdoc-file (file)
+ "Check FILE for document, comment, error style, and rogue spaces."
+ (with-current-buffer (find-file-noselect file)
+ (let ((checkdoc-diagnostic-buffer "*warn*"))
+ (checkdoc-current-buffer t))))
+
;;;###autoload
(defun checkdoc-start (&optional take-notes)
"Start scanning the current buffer for documentation string style errors.
documentation is checked. If there is a documentation error, then the display
of what was evaluated will be overwritten by the diagnostic message."
(interactive)
- (call-interactively 'eval-defun)
+ (call-interactively #'eval-defun)
(checkdoc-defun))
;;;###autoload
;;
;;;###autoload
-(defun checkdoc-ispell (&optional take-notes)
+(defun checkdoc-ispell ()
"Check the style and spelling of everything interactively.
Calls `checkdoc' with spell-checking turned on.
-Prefix argument TAKE-NOTES is the same as for `checkdoc'"
+Prefix argument is the same as for `checkdoc'"
(interactive)
(let ((checkdoc-spellcheck-documentation-flag t))
- (call-interactively 'checkdoc nil current-prefix-arg)))
+ (call-interactively #'checkdoc nil current-prefix-arg)))
;;;###autoload
-(defun checkdoc-ispell-current-buffer (&optional take-notes)
+(defun checkdoc-ispell-current-buffer ()
"Check the style and spelling of the current buffer.
Calls `checkdoc-current-buffer' with spell-checking turned on.
-Prefix argument TAKE-NOTES is the same as for `checkdoc-current-buffer'"
+Prefix argument is the same as for `checkdoc-current-buffer'"
(interactive)
(let ((checkdoc-spellcheck-documentation-flag t))
- (call-interactively 'checkdoc-current-buffer nil current-prefix-arg)))
+ (call-interactively #'checkdoc-current-buffer nil current-prefix-arg)))
;;;###autoload
-(defun checkdoc-ispell-interactive (&optional take-notes)
+(defun checkdoc-ispell-interactive ()
"Check the style and spelling of the current buffer interactively.
Calls `checkdoc-interactive' with spell-checking turned on.
-Prefix argument TAKE-NOTES is the same as for `checkdoc-interactive'"
+Prefix argument is the same as for `checkdoc-interactive'"
(interactive)
(let ((checkdoc-spellcheck-documentation-flag t))
- (call-interactively 'checkdoc-interactive nil current-prefix-arg)))
+ (call-interactively #'checkdoc-interactive nil current-prefix-arg)))
;;;###autoload
-(defun checkdoc-ispell-message-interactive (&optional take-notes)
+(defun checkdoc-ispell-message-interactive ()
"Check the style and spelling of message text interactively.
Calls `checkdoc-message-interactive' with spell-checking turned on.
-Prefix argument TAKE-NOTES is the same as for `checkdoc-message-interactive'"
+Prefix argument is the same as for `checkdoc-message-interactive'"
(interactive)
(let ((checkdoc-spellcheck-documentation-flag t))
- (call-interactively 'checkdoc-message-interactive nil current-prefix-arg)))
+ (call-interactively #'checkdoc-message-interactive
+ nil current-prefix-arg)))
;;;###autoload
-(defun checkdoc-ispell-message-text (&optional take-notes)
+(defun checkdoc-ispell-message-text ()
"Check the style and spelling of message text interactively.
Calls `checkdoc-message-text' with spell-checking turned on.
-Prefix argument TAKE-NOTES is the same as for `checkdoc-message-text'"
+Prefix argument is the same as for `checkdoc-message-text'"
(interactive)
(let ((checkdoc-spellcheck-documentation-flag t))
- (call-interactively 'checkdoc-message-text nil current-prefix-arg)))
+ (call-interactively #'checkdoc-message-text nil current-prefix-arg)))
;;;###autoload
-(defun checkdoc-ispell-start (&optional take-notes)
+(defun checkdoc-ispell-start ()
"Check the style and spelling of the current buffer.
Calls `checkdoc-start' with spell-checking turned on.
-Prefix argument TAKE-NOTES is the same as for `checkdoc-start'"
+Prefix argument is the same as for `checkdoc-start'"
(interactive)
(let ((checkdoc-spellcheck-documentation-flag t))
- (call-interactively 'checkdoc-start nil current-prefix-arg)))
+ (call-interactively #'checkdoc-start nil current-prefix-arg)))
;;;###autoload
-(defun checkdoc-ispell-continue (&optional take-notes)
+(defun checkdoc-ispell-continue ()
"Check the style and spelling of the current buffer after point.
Calls `checkdoc-continue' with spell-checking turned on.
-Prefix argument TAKE-NOTES is the same as for `checkdoc-continue'"
+Prefix argument is the same as for `checkdoc-continue'"
(interactive)
(let ((checkdoc-spellcheck-documentation-flag t))
- (call-interactively 'checkdoc-continue nil current-prefix-arg)))
+ (call-interactively #'checkdoc-continue nil current-prefix-arg)))
;;;###autoload
-(defun checkdoc-ispell-comments (&optional take-notes)
+(defun checkdoc-ispell-comments ()
"Check the style and spelling of the current buffer's comments.
Calls `checkdoc-comments' with spell-checking turned on.
-Prefix argument TAKE-NOTES is the same as for `checkdoc-comments'"
+Prefix argument is the same as for `checkdoc-comments'"
(interactive)
(let ((checkdoc-spellcheck-documentation-flag t))
- (call-interactively 'checkdoc-comments nil current-prefix-arg)))
+ (call-interactively #'checkdoc-comments nil current-prefix-arg)))
;;;###autoload
-(defun checkdoc-ispell-defun (&optional take-notes)
+(defun checkdoc-ispell-defun ()
"Check the style and spelling of the current defun with Ispell.
Calls `checkdoc-defun' with spell-checking turned on.
-Prefix argument TAKE-NOTES is the same as for `checkdoc-defun'"
+Prefix argument is the same as for `checkdoc-defun'"
(interactive)
(let ((checkdoc-spellcheck-documentation-flag t))
- (call-interactively 'checkdoc-defun nil current-prefix-arg)))
+ (call-interactively #'checkdoc-defun nil current-prefix-arg)))
;;; Error Management
;;
(defsubst checkdoc-run-hooks (hookvar &rest args)
"Run hooks in HOOKVAR with ARGS."
(if (fboundp 'run-hook-with-args-until-success)
- (apply 'run-hook-with-args-until-success hookvar args)
+ (apply #'run-hook-with-args-until-success hookvar args)
;; This method was similar to above. We ignore the warning
;; since we will use the above for future Emacs versions
- (apply 'run-hook-with-args hookvar args)))
+ (apply #'run-hook-with-args hookvar args)))
(defsubst checkdoc-create-common-verbs-regexp ()
"Rebuild the contents of `checkdoc-common-verbs-regexp'."
(when (re-search-forward "^(" e t)
(if (checkdoc-autofix-ask-replace (match-beginning 0)
(match-end 0)
- "Escape this '('? "
+ (format-message "Escape this `('? ")
"\\(")
nil
(checkdoc-create-error
;; Instead, use the `\\[...]' construct to stand for them.
(save-excursion
(let ((f nil) (m nil) (start (point))
- (re "[^`A-Za-z0-9_]\\([CMA]-[a-zA-Z]\\|\\(\\([CMA]-\\)?\
+ (re "[^`‘A-Za-z0-9_]\\([CMA]-[a-zA-Z]\\|\\(\\([CMA]-\\)?\
mouse-[0-3]\\)\\)\\>"))
;; Find the first key sequence not in a sample
(while (and (not f) (setq m (re-search-forward re e t)))
(save-excursion
(let ((case-fold-search t)
(ret nil) mb me)
- (while (and (re-search-forward "`\\(\\sw\\(\\sw\\|\\s_\\)+\\)'" e t)
+ (while (and (re-search-forward
+ "[`‘]\\(\\sw\\(\\sw\\|\\s_\\)+\\)['’]" e t)
(not ret))
(let* ((ms1 (match-string 1))
(sym (intern-soft ms1)))
(or
;; * The documentation string for a variable that is a
;; yes-or-no flag should start with words such as Non-nil
- ;; means..., to make it clear that all non-`nil' values are
- ;; equivalent and indicate explicitly what `nil' and non-`nil'
+ ;; means..., to make it clear that all non-nil values are
+ ;; equivalent and indicate explicitly what nil and non-nil
;; mean.
;; * If a user option variable records a true-or-false
;; condition, give it a name that ends in `-flag'.
;; Addendum: Make sure they appear in the doc in the same
;; order that they are found in the arg list.
- (let ((args (cdr (cdr (cdr (cdr fp)))))
+ (let ((args (nthcdr 4 fp))
(last-pos 0)
(found 1)
(order (and (nth 3 fp) (car (nth 3 fp))))
(nocheck (append '("&optional" "&rest") (nth 3 fp)))
(inopts nil))
(while (and args found (> found last-pos))
- (if (member (car args) nocheck)
+ (if (or (member (car args) nocheck)
+ (string-match "\\`_" (car args)))
(setq args (cdr args)
inopts t)
(setq last-pos found
e t))
(if (checkdoc-autofix-ask-replace
(match-beginning 1) (match-end 1)
- (format
+ (format-message
"If this is the argument `%s', it should appear as %s. Fix? "
(car args) (upcase (car args)))
(upcase (car args)) t)
(insert "."))
nil)
(checkdoc-create-error
- (format
+ (format-message
"Argument `%s' should appear (as %s) in the doc string"
(car args) (upcase (car args)))
s (marker-position e)))
)))
;;* When a documentation string refers to a Lisp symbol, write it as
;; it would be printed (which usually means in lower case), with
- ;; single-quotes around it. For example: `lambda'. There are two
- ;; exceptions: write t and nil without single-quotes. (In this
- ;; manual, we normally do use single-quotes for those symbols.)
+ ;; single-quotes around it. For example: ‘lambda’. There are two
+ ;; exceptions: write t and nil without single-quotes. (For
+ ;; compatibility with an older Emacs style, quoting with ` and '
+ ;; also works, e.g., `lambda' is treated like ‘lambda’.)
(save-excursion
(let ((found nil) (start (point)) (msg nil) (ms nil))
(while (and (not msg)
(re-search-forward
;; Ignore manual page references like
;; git-config(1).
- "[^-([`':a-zA-Z]\\(\\w+[:-]\\(\\w\\|\\s_\\)+\\)[^](']"
+ "[^-([`'‘’:a-zA-Z]\\(\\w+[:-]\\(\\w\\|\\s_\\)+\\)[^]('’]"
e t))
(setq ms (match-string 1))
;; A . is a \s_ char, so we must remove periods from
(setq found (intern-soft ms))
(or (boundp found) (fboundp found)))
(progn
- (setq msg (format "Add quotes around Lisp symbol `%s'? "
- ms))
+ (setq msg (format-message
+ "Add quotes around Lisp symbol `%s'? " ms))
(if (checkdoc-autofix-ask-replace
(match-beginning 1) (+ (match-beginning 1)
(length ms))
- msg (concat "`" ms "'") t)
+ msg (format-message "`%s'" ms) t)
(setq msg nil)
(setq msg
- (format "Lisp symbol `%s' should appear in quotes"
- ms))))))
+ (format-message
+ "Lisp symbol `%s' should appear in quotes" ms))))))
(if msg
(checkdoc-create-error msg (match-beginning 1)
(+ (match-beginning 1)
nil)))
;; t and nil case
(save-excursion
- (if (re-search-forward "\\(`\\(t\\|nil\\)'\\)" e t)
+ (if (re-search-forward "\\([`‘]\\(t\\|nil\\)['’]\\)" e t)
(if (checkdoc-autofix-ask-replace
(match-beginning 1) (match-end 1)
(format "%s should not appear in quotes. Remove? "
(match-string 2) t)
nil
(checkdoc-create-error
- "Symbols t and nil should not appear in `...' quotes"
+ "Symbols t and nil should not appear in single quotes"
(match-beginning 1) (match-end 1)))))
;; Here is some basic sentence formatting
(checkdoc-sentencespace-region-engine (point) e)
"Return non-nil if the current point is in a code fragment.
A code fragment is identified by an open parenthesis followed by a
symbol which is a valid function or a word in all CAPS, or a parenthesis
-that is quoted with the ' character. Only the region from START to LIMIT
+that is quoted with the \\=' character. Only the region from START to LIMIT
is allowed while searching for the bounding parenthesis."
(save-match-data
(save-restriction
(if (and (not (save-excursion
(goto-char b)
(forward-char -1)
- (looking-at "`\\|\"\\|\\.\\|\\\\")))
+ (looking-at "[`\".‘]\\|\\\\")))
;; surrounded by /, as in a URL or filename: /emacs/
(not (and (= ?/ (char-after e))
(= ?/ (char-before b))))
nil
(require 'lisp-mnt)
;; Old XEmacs don't have `lm-commentary-mark'
- (if (and (not (fboundp 'lm-commentary-mark)) (boundp 'lm-commentary))
- (defalias 'lm-commentary-mark 'lm-commentary)))
+ (if (and (not (fboundp 'lm-commentary-mark)) (fboundp 'lm-commentary))
+ (defalias 'lm-commentary-mark #'lm-commentary)))
(save-excursion
(let* ((f1 (file-name-nondirectory (buffer-file-name)))
(fn (file-name-sans-extension f1))
(if (or (not checkdoc-force-history-flag)
(file-exists-p "ChangeLog")
(file-exists-p "../ChangeLog")
- (let ((fn 'lm-history-mark)) ;bestill byte-compiler
- (and (fboundp fn) (funcall fn))))
+ (and (fboundp 'lm-history-mark) (funcall #'lm-history-mark)))
nil
(progn
(goto-char (or (lm-commentary-mark) (point-min)))
According to the documentation for the function `error', the error list
should not end with a period, and should start with a capital letter.
The function `y-or-n-p' has similar constraints.
-Argument TYPE specifies the type of question, such as `error or `y-or-n-p."
+Argument TYPE specifies the type of question, such as `error' or `y-or-n-p'."
;; If type is nil, then attempt to derive it.
(if (not type)
(save-excursion
;; If we see a ?, then replace with "? ".
(if (checkdoc-autofix-ask-replace
(match-beginning 0) (match-end 0)
- "`y-or-n-p' argument should end with \"? \". Fix? "
+ (format-message
+ "`y-or-n-p' argument should end with \"? \". Fix? ")
"? " t)
nil
(checkdoc-create-error
(looking-at " "))
(if (checkdoc-autofix-ask-replace
(match-beginning 0) (match-end 0)
- "`y-or-n-p' argument should end with \"? \". Fix? "
+ (format-message
+ "`y-or-n-p' argument should end with \"? \". Fix? ")
"? " t)
nil
(checkdoc-create-error
(looking-at "\""))
(checkdoc-autofix-ask-replace
(match-beginning 0) (match-end 0)
- "`y-or-n-p' argument should end with \"? \". Fix? "
+ (format-message
+ "`y-or-n-p' argument should end with \"? \". Fix? ")
"? \"" t))
nil
(checkdoc-create-error
(define-derived-mode checkdoc-output-mode compilation-mode "Checkdoc"
"Set up the major mode for the buffer containing the list of errors."
- (set (make-local-variable 'compilation-error-regexp-alist)
- checkdoc-output-error-regex-alist)
- (set (make-local-variable 'compilation-mode-font-lock-keywords)
- checkdoc-output-font-lock-keywords))
+ (setq-local compilation-error-regexp-alist
+ checkdoc-output-error-regex-alist)
+ (setq-local compilation-mode-font-lock-keywords
+ checkdoc-output-font-lock-keywords))
(defun checkdoc-buffer-label ()
"The name to use for a checkdoc buffer in the error list."
"Store POINT and MSG as errors in the checkdoc diagnostic buffer."
(setq checkdoc-pending-errors t)
(let ((text (list "\n" (checkdoc-buffer-label) ":"
- (int-to-string
- (count-lines (point-min) (or point (point-min))))
- ": " msg)))
- (with-current-buffer (get-buffer checkdoc-diagnostic-buffer)
- (goto-char (point-max))
- (let ((inhibit-read-only t))
- (apply 'insert text)))))
+ (int-to-string
+ (count-lines (point-min) (or point (point-min))))
+ ": " msg)))
+ (if (string= checkdoc-diagnostic-buffer "*warn*")
+ (warn (apply #'concat text))
+ (with-current-buffer (get-buffer checkdoc-diagnostic-buffer)
+ (let ((inhibit-read-only t)
+ (pt (point-max)))
+ (goto-char pt)
+ (apply #'insert text))))))
(defun checkdoc-show-diagnostics ()
"Display the checkdoc diagnostic buffer in a temporary window."
(if checkdoc-pending-errors
- (let ((b (get-buffer checkdoc-diagnostic-buffer)))
- (if b (progn (pop-to-buffer b)
- (goto-char (point-max))
- (re-search-backward "\C-l" nil t)
- (beginning-of-line)
- (forward-line 1)
- (recenter 0)))
- (other-window -1)
+ (let* ((b (get-buffer checkdoc-diagnostic-buffer))
+ (win (if b (display-buffer b))))
+ (when win
+ (with-selected-window win
+ (goto-char (point-max))
+ (re-search-backward "\C-l" nil t)
+ (beginning-of-line)
+ (forward-line 1)
+ (recenter 0)))
(setq checkdoc-pending-errors nil)
nil)))
+(defun checkdoc-get-keywords ()
+ "Return a list of package keywords for the current file."
+ (save-excursion
+ (goto-char (point-min))
+ (when (re-search-forward "^;; Keywords: \\(.*\\)$" nil t)
+ (split-string (match-string-no-properties 1) ", " t))))
+
+(defvar finder-known-keywords)
+
+;;;###autoload
+(defun checkdoc-package-keywords ()
+ "Find package keywords that aren't in `finder-known-keywords'."
+ (interactive)
+ (require 'finder)
+ (let ((unrecognized-keys
+ (cl-remove-if
+ (lambda (x) (assoc (intern-soft x) finder-known-keywords))
+ (checkdoc-get-keywords))))
+ (if unrecognized-keys
+ (let* ((checkdoc-autofix-flag 'never)
+ (checkdoc-generate-compile-warnings-flag t))
+ (save-excursion
+ (goto-char (point-min))
+ (re-search-forward "^;; Keywords: \\(.*\\)$" nil t)
+ (checkdoc-start-section "checkdoc-package-keywords")
+ (checkdoc-create-error
+ (concat "Unrecognized keywords: "
+ (mapconcat #'identity unrecognized-keys ", "))
+ (match-beginning 1) (match-end 1)))
+ (checkdoc-show-diagnostics))
+ (when (called-interactively-p 'any)
+ (message "No Package Keyword Errors.")))))
+
(custom-add-option 'emacs-lisp-mode-hook 'checkdoc-minor-mode)
(provide 'checkdoc)