emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Changing dictionary while flyspell-buffer is running


From: Titus von der Malsburg
Subject: Re: Changing dictionary while flyspell-buffer is running
Date: Thu, 28 Feb 2019 13:36:03 +0100
User-agent: mu4e 1.1.0; emacs 26.1.91

On 2019-02-22 Fri 03:06, Richard Stallman wrote:
> [[[ To any NSA and FBI agents reading my email: please consider    ]]]
> [[[ whether defending the US Constitution against all enemies,     ]]]
> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
>
>   > > I don't use flyspell, but I would appreciate this feature of
>   > > automatically selecting the proper dictionary.  Could you arrange
>   > > some other way to automatically run the program?
>   > > Perhaps a variable that would tell the user-level ispell commands
>   > > to call your package at the suitable times?
>
>   > Sure, that would work, but then we’d have to make changes in
>   > ispell.el.
>
> Would adding hooks in ispell.el be enough?

Below is a patch for ispell.el that adds a hook that is run before
`ispell-set-spellchecker-params'.  Functions on this hook of course need
to be careful not to trigger an infinite recursion when they call Ispell
functions like `ispell-change-dictionary'.  There is a note on that in
the documentation of the hook.

To make automatic language detection work with Ispell, the following
function could be added to this hook:

(defun guess-language-ispell-set-buffer-language ()
  "Detects the buffer language and changes the dictionary for Ispell
if the language has changed since the last detection."
  (let* ((lang (guess-language-buffer))
        (new-dictionary (cadr (assq lang guess-language-langcodes)))
        (ispell-before-setting-spellchecker-params-hook
          (delete #'guess-language-ispell-set-buffer-language
                  (copy-sequence 
ispell-before-setting-spellchecker-params-hook))))
    (ispell-change-dictionary new-dictionary)))

(add-hook 'ispell-before-setting-spellchecker-params-hook
          #'guess-language-ispell-set-buffer-language)

  Titus


diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el
index 237997d41d..87e369ebd7 100644
--- a/lisp/textmodes/ispell.el
+++ b/lisp/textmodes/ispell.el
@@ -211,6 +211,7 @@ ispell-program-name
   :set (lambda (symbol value)
          (set-default symbol value)
          (if (featurep 'ispell)
+             (run-hooks 'ispell-before-setting-spellchecker-params-hook)
              (ispell-set-spellchecker-params)))
   :group 'ispell)
 
@@ -1259,6 +1260,13 @@ ispell-last-program-name
 ;; advertised in the doc string of ispell-initialize-spellchecker-hook.
 (defvar ispell-base-dicts-override-alist)
 
+(defvar ispell-before-setting-spellchecker-params-hook nil
+  "Normal hook run before setting spellchecker parameters.
+This hook can be used for automatic spellchecker configuration,
+e.g. automatic detection of the buffer language.  Hooked
+functions need to be careful when calling Ispell functions as
+this could cause infinite recursion.")
+
 (defvar ispell-initialize-spellchecker-hook nil
   "Normal hook run on spellchecker initialization.
 This hook is run when a spellchecker is used for the first
@@ -1394,8 +1402,9 @@ ispell-valid-dictionary-list
 The variable `ispell-library-directory' defines their location."
   ;; Initialize variables and dictionaries alists for desired spellchecker.
   ;; Make sure ispell.el is loaded to avoid some autoload loops.
-  (if (featurep 'ispell)
-      (ispell-set-spellchecker-params))
+  (when (featurep 'ispell)
+    (run-hooks 'ispell-before-setting-spellchecker-params-hook)
+    (ispell-set-spellchecker-params))
 
   (let ((dicts (append ispell-local-dictionary-alist ispell-dictionary-alist))
        (dict-list (cons "default" nil))
@@ -1935,6 +1944,7 @@ ispell-word
     (ispell-region (region-beginning) (region-end)))
    (continue (ispell-continue))
    (t
+    (run-hooks 'ispell-before-setting-spellchecker-params-hook)
     (ispell-set-spellchecker-params)    ; Initialize variables and dicts alists
     (ispell-accept-buffer-local-defs)  ; use the correct dictionary
     (let ((cursor-location (point))    ; retain cursor location
@@ -2035,6 +2045,7 @@ ispell-get-word
 
 Word syntax is controlled by the definition of the chosen dictionary,
 which is in `ispell-local-dictionary-alist' or `ispell-dictionary-alist'."
+  (run-hooks 'ispell-before-setting-spellchecker-params-hook)
   (ispell-set-spellchecker-params)    ; Initialize variables and dicts alists
   (let* ((ispell-casechars (ispell-get-casechars))
         (ispell-not-casechars (ispell-get-not-casechars))
@@ -2989,6 +3000,7 @@ ispell-change-dictionary
               (mapcar #'list (ispell-valid-dictionary-list)))
          nil t)
         current-prefix-arg))
+  (run-hooks 'ispell-before-setting-spellchecker-params-hook)
   (ispell-set-spellchecker-params) ; Initialize variables and dicts alists
   (unless arg (ispell-buffer-local-dict 'no-reload))
   (if (equal dict "default") (setq dict nil))
@@ -3047,6 +3059,7 @@ ispell-region
 Return nil if spell session was terminated, otherwise returns shift offset
 amount for last line processed."
   (interactive "r")                    ; Don't flag errors on read-only bufs.
+  (run-hooks 'ispell-before-setting-spellchecker-params-hook)
   (ispell-set-spellchecker-params)      ; Initialize variables and dicts alists
   (if (not recheckp)
       (ispell-accept-buffer-local-defs)) ; set up dictionary, local words, etc.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]