>From a3ee18626be6ac564eef34128d50a006073aa130 Mon Sep 17 00:00:00 2001 From: Damien Cassou Date: Thu, 12 Dec 2019 20:27:05 +0100 Subject: [PATCH 5/5] Add unattended spell-checking to checkdoc This commit makes checkdoc capable of spell-checking even when the user isn't using it interactively. When TAKE-NOTES is non-nil, checkdoc will run spell-checking (with ispell) and report spelling mistakes. * lisp/emacs-lisp/checkdoc.el (checkdoc-current-buffer): Pass TAKE-NOTES to `checkdoc-start`. (checkdoc-continue): Pass TAKE-NOTES to `checkdoc-this-string-valid`. (checkdoc-this-string-valid): Add optional argument TAKE-NOTES and pass it to `checkdoc-this-string-valid-engine`. (checkdoc-this-string-valid-engine): Add optional argument TAKE-NOTES and pass it to `checkdoc-ispell-docstring-engine`. (checkdoc-ispell-docstring-engine): Add optional argument TAKE-NOTES to force reporting of spell-checking errors. --- lisp/emacs-lisp/checkdoc.el | 56 +++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el index 075817a252..3e6542bc80 100644 --- a/lisp/emacs-lisp/checkdoc.el +++ b/lisp/emacs-lisp/checkdoc.el @@ -849,7 +849,7 @@ checkdoc-current-buffer ;; every test is responsible for returning the cursor. (or (and buffer-file-name ;; only check comments in a file (checkdoc-comments)) - (checkdoc-start) + (checkdoc-start take-notes) (checkdoc-message-text) (checkdoc-rogue-spaces) (when checkdoc-package-keywords-flag @@ -902,7 +902,7 @@ checkdoc-continue ;; the user is navigating down through the buffer. (while (and (not wrong) (checkdoc-next-docstring)) ;; OK, let's look at the doc string. - (setq msg (checkdoc-this-string-valid)) + (setq msg (checkdoc-this-string-valid take-notes)) (if msg (setq wrong (point))))) (if wrong (progn @@ -1284,12 +1284,15 @@ checkdoc-create-common-verbs-regexp ;;; Checking engines ;; -(defun checkdoc-this-string-valid () +(defun checkdoc-this-string-valid (&optional take-notes) "Return a message string if the current doc string is invalid. Check for style only, such as the first line always being a complete sentence, whitespace restrictions, and making sure there are no hard-coded key-codes such as C-[char] or mouse-[number] in the comment. -See the style guide in the Emacs Lisp manual for more details." +See the style guide in the Emacs Lisp manual for more details. + +With a non-nil TAKE-NOTES, store all errors found in a warnings +buffer, otherwise stop after the first error." ;; Jump over comments between the last object and the doc string (while (looking-at "[ \t\n]*;") @@ -1366,13 +1369,16 @@ checkdoc-this-string-valid (point) (+ (point) 1) t))))) (if (and (not err) (= (following-char) ?\")) (with-syntax-table checkdoc-syntax-table - (checkdoc-this-string-valid-engine fp)) + (checkdoc-this-string-valid-engine fp take-notes)) err))) -(defun checkdoc-this-string-valid-engine (fp) +(defun checkdoc-this-string-valid-engine (fp &optional take-notes) "Return an error list or string if the current doc string is invalid. Depends on `checkdoc-this-string-valid' to reset the syntax table so that -regexp short cuts work. FP is the function defun information." +regexp short cuts work. FP is the function defun information. + +With a non-nil TAKE-NOTES, store all errors found in a warnings +buffer, otherwise stop after the first error." (let ((case-fold-search nil) ;; Use a marker so if an early check modifies the text, ;; we won't accidentally lose our place. This could cause @@ -1864,7 +1870,7 @@ checkdoc-this-string-valid-engine ;; Make sure the doc string has correctly spelled English words ;; in it. This function is extracted due to its complexity, ;; and reliance on the Ispell program. - (checkdoc-ispell-docstring-engine e) + (checkdoc-ispell-docstring-engine e take-notes) ;; User supplied checks (save-excursion (checkdoc-run-hooks 'checkdoc-style-functions fp e)) ;; Done! @@ -2107,27 +2113,32 @@ checkdoc-ispell-init (process-send-string ispell-process (concat "@" w "\n")))) (error (setq checkdoc-spellcheck-documentation-flag nil))))) -(defun checkdoc-ispell-docstring-engine (end) +(defun checkdoc-ispell-docstring-engine (end &optional take-notes) "Run the Ispell tools on the doc string between point and END. Since Ispell isn't Lisp-smart, we must pre-process the doc string -before using the Ispell engine on it." +before using the Ispell engine on it. + +With a non-nil TAKE-NOTES, store all errors found in a warnings +buffer, otherwise stop after the first error." (when (and checkdoc-spellcheck-documentation-flag ;; If the user wants no questions or fixing, then we must ;; disable spell checking as not useful. - checkdoc-autofix-flag - (not (eq checkdoc-autofix-flag 'never))) + (or take-notes + (and checkdoc-autofix-flag + (not (eq checkdoc-autofix-flag 'never))))) (checkdoc-ispell-init) (save-excursion (skip-chars-forward "^a-zA-Z") - (let (word sym case-fold-search err) + (let (word sym case-fold-search err word-beginning word-end) (while (and (not err) (< (point) end)) (if (save-excursion (forward-char -1) (looking-at "[('`]")) ;; Skip lists describing meta-syntax, or bound variables (forward-sexp 1) - (setq word (buffer-substring-no-properties - (point) (progn - (skip-chars-forward "a-zA-Z-") - (point))) + (setq word-beginning (point) + word-end (progn + (skip-chars-forward "a-zA-Z-") + (point)) + word (buffer-substring-no-properties word-beginning word-end) sym (intern-soft word)) (unless (and sym (or (boundp sym) (fboundp sym))) ;; Find out how we spell-check this word. @@ -2139,7 +2150,16 @@ checkdoc-ispell-docstring-engine ) (save-excursion (let ((lk last-input-event)) - (ispell-word nil t) + (if take-notes + (progn + (unless (ispell-correct-p) + (checkdoc-create-error + (format "Error checking word %s using %s with %s dictionary" + (funcall ispell-format-word-function word) + (file-name-nondirectory ispell-program-name) + (or ispell-current-dictionary "default")) + word-beginning word-end))) + (ispell-word nil t)) (if (not (equal last-input-event lk)) (progn (sit-for 0) -- 2.23.0