tmalsburg / guess-language.el

Emacs minor mode that detects the language you're typing in. Automatically switches spell checker. Supports multiple languages per document.
115 stars 14 forks source link

Redundant aspell processes after magit-commit #34

Closed jakanakaevangeli closed 3 years ago

jakanakaevangeli commented 3 years ago

Emacs -Q:

(progn
  (setq package-archives '(("gnu" . "https://elpa.gnu.org/packages/")
                           ("nongnu" . "https://elpa.nongnu.org/nongnu/")))
  (package-install 'magit)
  (package-install 'guess-language)
  (package-activate-all)

  (setq guess-language-languages '(en sl))
  (setq-default ispell-dictionary "slovenian")
  (add-hook 'text-mode-hook 'flyspell-mode)
  (add-hook 'flyspell-mode-hook 'guess-language-mode))

Each M-x magit-commit-create will leave an extra aspell process. (A bit more info can be found on http://debbugs.gnu.org/cgi/bugreport.cgi?bug=48379 )

tmalsburg commented 3 years ago

Ah, that's where all these aspell processes are coming from.

the problem was an idle timer from guess-language, accidentally hijacking itself into ispell's sit-for.

I'm afraid I don't understand the internals of ispell enough to work with this description. Do you by any chance have an idea of what needs to be fixed?

jakanakaevangeli commented 3 years ago

How about something like the following patch. The idea is that post-command-hook is more predictable and well behaved than an idle timer, which can fire during any call to sit-for.

diff --git a/guess-language.el b/guess-language.el
index 0fecc2a..d390e42 100644
--- a/guess-language.el
+++ b/guess-language.el
@@ -232,6 +232,8 @@ (defun guess-language-function (_beginning _end _doublon)
   ;; words:
   nil)

+(defalias 'guess-language--post-command-h #'ignore)
+
 (defun guess-language-switch-flyspell-function (lang beginning end)
   "Switch the Flyspell dictionary and recheck the current paragraph.

@@ -249,14 +251,15 @@ (defun guess-language-switch-flyspell-function (lang beginning end)
       ;; from flyspell-incorrect-hook that called us. Otherwise, the
       ;; word at point is highlighted as incorrect even if it is
       ;; correct according to the new dictionary.
-      (run-with-idle-timer 0 nil
-                           (lambda ()
-                             (let ((flyspell-issue-welcome-flag nil)
-                                   (flyspell-issue-message-flag nil)
-                                   (flyspell-incorrect-hook nil)
-                                   (flyspell-large-region 1))
-                               (with-local-quit
-                                 (flyspell-region beginning end))))))))
+      (fset 'guess-language--post-command-h
+            (lambda ()
+              (fset 'guess-language--post-command-h #'ignore)
+              (let ((flyspell-issue-welcome-flag nil)
+                    (flyspell-issue-message-flag nil)
+                    (flyspell-incorrect-hook nil)
+                    (flyspell-large-region 1))
+                (with-local-quit
+                  (flyspell-region beginning end))))))))

 (defun guess-language-switch-typo-mode-function (lang _beginning _end)
   "Switch the language used by typo-mode.
@@ -299,8 +302,10 @@ (define-minor-mode guess-language-mode
   (if guess-language-mode
       (progn
         (add-hook 'flyspell-incorrect-hook #'guess-language-function nil t)
+        (add-hook 'post-command-hook #'guess-language--post-command-h 'append t)
         (advice-add 'flyspell-buffer :around #'guess-language-flyspell-buffer-wrapper))
     (remove-hook 'flyspell-incorrect-hook #'guess-language-function t)
+    (remove-hook 'post-command-hook #'guess-language--post-command-h t)
     (advice-remove 'flyspell-buffer #'guess-language-flyspell-buffer-wrapper)))

 (defun guess-language-mark-lines (&optional highlight)

Edit: with-local-quit is required after all.