Subject: bug#62677: Merge flyspell-mode with flyspell-prog-mode

From: Stefan Kangas <[email-masked]>
Date: Sun, 24 Sep 2023 07:08:56 -0700

Eli Zaretskii <[email-masked]> writes:

>> From: Stefan Kangas <[email-masked]>
>> Date: Wed, 6 Sep 2023 11:51:14 -0700
>> Cc: [email-masked], [email-masked], [email-masked]
>>
>> Here's the plan I'd propose: Add a new defvar-local
>> `flyspell-use-prog-mode' or somesuch that major modes can set.  Now,
>> when a user enables `flymake-mode' in a buffer where that variable is
>> non-nil, the extra stuff done in `flyspell-prog-mode' gets done too.
>> Then decide which built-in major modes that would benefit, and set that
>> variable in them.
>
> SGTM.
>
>> Would `prog-mode' be a candidate though, or do we expect any modes
>> inheriting from it to want the regular `flyspell-mode'?
>
> The former, I guess?

Thanks.  How does the attached patch look?
From a922af5bf37ffd9ec27bac0413d4a01c5b5bbfec Mon Sep 17 00:00:00 2001
From: Stefan Kangas <[email-masked]>
Date: Sun, 24 Sep 2023 15:32:42 +0200
Subject: [PATCH] Make flyspell-mode DWIM in prog-mode buffers

* lisp/textmodes/flyspell.el: Doc fixes.
(flyspell-programming-mode-list): New variable.
(flyspell--enable-programming-mode): New helper function.
(flyspell-prog-mode): Use above new helper function, and document
as being deprecated.
(flyspell-mode): Use above new helper function.
* lisp/progmodes/prog-mode.el (prog-mode-hook): Replace
'flyspell-prog-mode' with 'flyspell-mode'.
* lisp/emacs-lisp/checkdoc.el:
* doc/emacs/fixit.texi (Spelling): Document the above.  (Bug#62677)
---
 doc/emacs/fixit.texi        | 24 ++++++---------
 etc/NEWS                    | 11 +++++++
 lisp/emacs-lisp/checkdoc.el |  2 +-
 lisp/progmodes/prog-mode.el |  7 +++--
 lisp/textmodes/flyspell.el  | 60 +++++++++++++++++++++++++++++++------
 5 files changed, 76 insertions(+), 28 deletions(-)

diff --git a/doc/emacs/fixit.texi b/doc/emacs/fixit.texi
index 78503d31a38..75d38adf35d 100644
--- a/doc/emacs/fixit.texi
+++ b/doc/emacs/fixit.texi
@@ -299,8 +299,6 @@ Spelling
 (@code{ispell-complete-word}).
 @item M-x flyspell-mode
 Enable Flyspell mode, which highlights all misspelled words.
-@item M-x flyspell-prog-mode
-Enable Flyspell mode for comments and strings only.
 @end table
 
 @kindex M-$
@@ -450,11 +448,15 @@ Spelling
 does not recognize, it highlights that word.  Type @w{@kbd{M-x
 flyspell-mode}} to toggle Flyspell mode in the current buffer.  To
 enable Flyspell mode in all text mode buffers, add
-@code{flyspell-mode} to @code{text-mode-hook}.  @xref{Hooks}.  Note
-that, as Flyspell mode needs to check each word across which you move,
-it will slow down cursor motion and scrolling commands.  It also
-doesn't automatically check the text you didn't type or move across;
-use @code{flyspell-region} or @code{flyspell-buffer} for that.
+@code{flyspell-mode} to @code{text-mode-hook}.  To enable it in
+programming language modes, add @code{flyspell-mode} to
+@code{prog-mode-hook}.  @xref{Hooks}.  In programming language modes,
+Flyspell mode will only check comments and string literals.
+
+  Note that, as Flyspell mode needs to check each word across which
+you move, it will slow down cursor motion and scrolling commands.  It
+also doesn't automatically check text that you didn't type or move
+across; use @code{flyspell-region} or @code{flyspell-buffer} for that.
 
 @findex flyspell-correct-word
 @findex flyspell-auto-correct-word
@@ -468,11 +470,3 @@ Spelling
 @w{@kbd{C-c $}} (@code{flyspell-correct-word-before-point}) will pop
 up a menu of possible corrections.  Of course, you can always correct
 the misspelled word by editing it manually in any way you like.
-
-@findex flyspell-prog-mode
-  Flyspell Prog mode works just like ordinary Flyspell mode, except
-that it only checks words in comments and string constants.  This
-feature is useful for editing programs.  Type @w{@kbd{M-x
-flyspell-prog-mode}} to enable or disable this mode in the current
-buffer.  To enable this mode in all programming mode buffers, add
-@code{flyspell-prog-mode} to @code{prog-mode-hook} (@pxref{Hooks}).
diff --git a/etc/NEWS b/etc/NEWS
index 53c8451dc19..cb4a1e9a73e 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -628,6 +628,17 @@ distracting and easily confused with actual code, or a significant
 early aid that relieves you from moving the buffer or reaching for the
 mouse to consult an error message.
 
+** Flyspell
+
++++
+*** 'flyspell-prog-mode' is now deprecated.
+Use 'flyspell-mode' instead, which will now automatically ensure that
+only text in strings and comments is spell checked in relevant modes.
+This includes any mode that inherits 'prog-mode'.  Major mode authors
+should consider adding their mode to 'flyspell-programming-mode-list',
+if it does not inherit 'prog-mode'.  'flyspell-prog-mode' will be
+marked obsolete in a future version of Emacs.
+
 ** Python Mode
 
 ---
diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el
index cf7b7c318f6..a28cc45742c 100644
--- a/lisp/emacs-lisp/checkdoc.el
+++ b/lisp/emacs-lisp/checkdoc.el
@@ -106,7 +106,7 @@
 ;; install into Ispell on the fly, but only if Ispell is not already
 ;; running.  Use `ispell-kill-ispell' to make checkdoc restart it with
 ;; these words enabled.
-;;   See also the `flyspell-prog-mode' minor mode.
+;;   See also the `flyspell-mode' minor mode.
 ;;
 ;; Checking parameters:
 ;;
diff --git a/lisp/progmodes/prog-mode.el b/lisp/progmodes/prog-mode.el
index 37c54a90f42..35d57b34857 100644
--- a/lisp/progmodes/prog-mode.el
+++ b/lisp/progmodes/prog-mode.el
@@ -46,9 +46,10 @@ prog-mode
 (defcustom prog-mode-hook nil
   "Normal hook run when entering programming modes."
   :type 'hook
-  :options '(flyspell-prog-mode abbrev-mode flymake-mode
-                                display-line-numbers-mode
-                                prettify-symbols-mode))
+  :options '( flyspell-mode abbrev-mode flymake-mode
+              display-line-numbers-mode
+              prettify-symbols-mode)
+  :version "30.1")
 
 (defun prog-context-menu (menu click)
   "Populate MENU with xref commands at CLICK."
diff --git a/lisp/textmodes/flyspell.el b/lisp/textmodes/flyspell.el
index 1ca508e14ef..e61b01e90b1 100644
--- a/lisp/textmodes/flyspell.el
+++ b/lisp/textmodes/flyspell.el
@@ -26,14 +26,37 @@
 ;; Flyspell is a minor Emacs mode performing on-the-fly spelling
 ;; checking.
 ;;
-;; To enable Flyspell minor mode, type M-x flyspell-mode.
+;; To enable Flyspell minor mode, type `M-x flyspell-mode'.
 ;; This applies only to the current buffer.
 ;;
-;; To enable Flyspell in text representing computer programs, type
-;; M-x flyspell-prog-mode.
-;; In that mode only text inside comments and strings is checked.
+;; To automatically enable flyspell-mode in all buffers using a
+;; certain mode, add something like the following to your init file:
+;;
+;;     (add-to-hook 'text-mode-hook 'flyspell-mode)
+;;
+;; For example, to enable it in programming language modes, you can
+;; use:
+;;
+;;     (add-to-hook 'prog-mode-hook 'flyspell-mode)
+;;
+;; When spell checking source code, it doesn't necessarily make sense
+;; to spell check things like names of variables and functions.  In
+;; such modes, flycheck will therefore automatically restrict itself
+;; to checking only text in strings and comments.
 ;;
 ;; Use `M-x customize-group RET flyspell RET' to customize flyspell.
+;;
+;; * `flyspell-prog-mode' is deprecated
+;;
+;; Note that `flyspell-prog-mode' is deprecated starting with Emacs
+;; 30.1.  Use 'flyspell-mode' instead, which will now automatically
+;; ensure that only text in strings and comments is spell checked in
+;; relevant modes.  This includes any mode that inherits 'prog-mode'.
+;;
+;; Major mode authors should consider adding their mode to
+;; 'flyspell-programming-mode-list', if it does not inherit
+;; 'prog-mode'.  'flyspell-prog-mode' will be marked obsolete in a
+;; future version of Emacs.
 
 ;;; Code:
 
@@ -385,6 +408,7 @@ sgml-mode-flyspell-verify
 ;;*---------------------------------------------------------------------*/
 ;;*    Programming mode                                                 */
 ;;*---------------------------------------------------------------------*/
+
 (defcustom flyspell-prog-text-faces
   '(font-lock-string-face font-lock-comment-face font-lock-doc-face)
   "Faces corresponding to text in programming-mode buffers."
@@ -393,6 +417,18 @@ flyspell-prog-text-faces
               (const font-lock-doc-face))
   :version "28.1")
 
+(defvar flyspell-programming-mode-list '(prog-mode)
+  "List of modes for which programming language semantics will be applied.
+If a mode is in this list, only strings and comments will be
+spell checked by 'flyspell-mode' in buffers using that mode.
+
+This is same behavior as if using the old `flyspell-prog-mode',
+which is deprecated starting with Emacs 30.1.")
+
+(defun flyspell--enable-programming-mode ()
+  (setq flyspell-generic-check-word-predicate
+        #'flyspell-generic-progmode-verify))
+
 (defun flyspell-generic-progmode-verify ()
   "Used for `flyspell-generic-check-word-predicate' in programming modes."
   (unless (eql (point) (point-min))
@@ -402,10 +438,13 @@ flyspell-generic-progmode-verify
 
 ;;;###autoload
 (defun flyspell-prog-mode ()
-  "Turn on `flyspell-mode' for comments and strings."
+  "Turn on `flyspell-mode' for comments and strings.
+
+This function is deprecated starting with Emacs 30.1.
+Instead of using this, add the relevant major mode to
+`flyspell-programming-mode-list' and invoke `flymake-mode'."
   (interactive)
-  (setq flyspell-generic-check-word-predicate
-        #'flyspell-generic-progmode-verify)
+  (flyspell--enable-programming-mode)
   (flyspell-mode 1)
   (run-hooks 'flyspell-prog-mode-hook))
 
@@ -516,8 +555,11 @@ flyspell-mode
   :group 'flyspell
   (if flyspell-mode
       (condition-case err
-          (flyspell--mode-on (called-interactively-p 'interactive))
-	(error (message "Error enabling Flyspell mode:\n%s" (cdr err))
+          (progn
+            (when (derived-mode-p flyspell-programming-mode-list)
+              (flyspell--enable-programming-mode))
+            (flyspell--mode-on (called-interactively-p 'interactive)))
+        (error (message "Error enabling Flyspell mode:\n%s" (cdr err))
 	       (flyspell-mode -1)))
     (flyspell--mode-off)))
 
-- 
2.42.0