unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Titus von der Malsburg <malsburg@posteo.de>
To: rms@gnu.org
Cc: emacs-devel@gnu.org
Subject: Re: Changing dictionary while flyspell-buffer is running
Date: Thu, 28 Feb 2019 13:36:03 +0100	[thread overview]
Message-ID: <87sgw8145o.fsf@posteo.de> (raw)
In-Reply-To: <E1gx0E2-0000Lh-6Z@fencepost.gnu.org>


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.




  parent reply	other threads:[~2019-02-28 12:36 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-02-19 22:58 Changing dictionary while flyspell-buffer is running Titus von der Malsburg
2019-02-20 17:05 ` Eli Zaretskii
     [not found]   ` <87y36as44p.fsf@posteo.de>
     [not found]     ` <83o976gvd2.fsf@gnu.org>
     [not found]       ` <87h8cxsed3.fsf@posteo.de>
2019-02-21 14:59         ` Eli Zaretskii
2019-02-21  3:26 ` Richard Stallman
2019-02-21  3:46   ` Eli Zaretskii
2019-02-21  8:34     ` Titus von der Malsburg
2019-02-21 14:53       ` Eli Zaretskii
2019-02-21 19:42         ` Joost Kremers
2019-02-21 20:09           ` Eli Zaretskii
2019-02-21 21:19             ` Titus von der Malsburg
2019-02-22  7:10               ` Eli Zaretskii
2019-02-22  9:57                 ` Titus von der Malsburg
2019-02-22 10:32                   ` Eli Zaretskii
2019-02-23 15:24           ` Stefan Monnier
2019-02-21  8:29   ` Titus von der Malsburg
2019-02-21 13:12     ` Clément Pit-Claudel
2019-02-22  2:06     ` Richard Stallman
2019-02-22  9:27       ` Titus von der Malsburg
2019-02-28 12:36       ` Titus von der Malsburg [this message]
2019-02-28 17:50         ` Eli Zaretskii

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87sgw8145o.fsf@posteo.de \
    --to=malsburg@posteo.de \
    --cc=emacs-devel@gnu.org \
    --cc=rms@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).