all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Agustin Martin <agustin.martin@hispalinux.es>
To: emacs-devel@gnu.org
Subject: ispell.el, flyspell.el: better ispell/aspell switching
Date: Fri, 4 Apr 2008 14:02:17 +0200	[thread overview]
Message-ID: <20080404120217.GA7503@agmartin.aq.upm.es> (raw)

[-- Attachment #1: Type: text/plain, Size: 2043 bytes --]

Hi,

I come back with a rewritten approach for a problem in current ispell.el and
flyspell.el when switching spellchecker in an emacs session.

The problem is as follows, when in an emacs run aspell is used for the first
time, ispell-dictionary-alist is filled with the aspell values, and if
ispell-program-name is customized or changed to ispell during that emacs run
it inherits the aspell values, thus failing if there was an aspell entry
with the same name. Since ispell is still (rarely) needed for pseudo-encodings
like [\'a -> á] I think this should not happen and all ispell values should
be restored in such case. Also current behavior is too ispell/aspell
centric, in case support for another spellchecker is ever added.

In the proposed attached patches (ispell-maybe-find-aspell-dictionaries) is
replaced by (more neutral) new (ispell-set-spellchecker-params) function.
That function will check if spellchecker is changed and fill
``ispell-dictionary-alist'' with the appropriate values. As written it has
support for info provided by distros. Patches are mostly as currently used
in Debian, with some comments rewritten, and a naive check for [:alpha:]
used (instead of just discarding that for xemacs as in Debian). Keeping
those xemacs checks saves me a couple of patches, please leave them there if
possible.

ispell.el:
==========
(ispell-set-spellchecker-params): 
  New function to make sure right params and dictionary alists are used
  after spellchecker changes.

``ispell-aspell-dictionary-alist'', ``ispell-last-program-name'':
  New variables: used by (ispell-set-spellchecker-params)

(ispell-find-aspell-dictionaries)
  Modified to use ``ispell-aspell-dictionary-alist''

(ispell-maybe-find-aspell-dictionaries)
  Removed. Calls replaced by (ispell-set-spellchecker-params) calls.

(ispell-have-aspell-dictionaries)
  Removed.

flyspell.el:
============
(ispell-maybe-find-aspell-dictionaries)
  Calls replaced by (ispell-set-spellchecker-params) calls.

-- 
Agustin

[-- Attachment #2: ispell.el_ispell-set-spellchecker-params.diff --]
[-- Type: text/x-diff, Size: 5750 bytes --]

--- ispell.el.orig	2008-03-28 12:55:25.000000000 +0100
+++ ispell.el	2008-04-04 13:33:11.000000000 +0200
@@ -879,20 +879,63 @@
 				   )
   "Non-nil means that the OS supports asynchronous processes.")
 
-;; Make ispell.el work better with aspell.
+;; Set params according to the selected spellchecker
 
-(defvar ispell-have-aspell-dictionaries nil
-  "Non-nil if we have queried Aspell for dictionaries at least once.")
+(defvar ispell-last-program-name nil
+  "Last value of ispell-program name. Internal use.")
 
-(defun ispell-maybe-find-aspell-dictionaries ()
-  "Find Aspell's dictionaries, unless already done."
-  (when (and (not ispell-have-aspell-dictionaries)
-	     (condition-case ()
-		 (progn (ispell-check-version) t)
+(defun ispell-set-spellchecker-params ()
+  "Initialize some spellchecker params when it is changed."
+  (unless (eq ispell-last-program-name ispell-program-name)
+    (ispell-kill-ispell t)
+    (if (and (condition-case ()
+		 (progn
+		   (setq ispell-library-directory (ispell-check-version))
+		   t)
 	       (error nil))
 	     ispell-really-aspell
-	     ispell-aspell-supports-utf8)
-    (ispell-find-aspell-dictionaries)))
+	     ispell-aspell-supports-utf8
+	     ;; xemacs does not like [:alpha:] regexps
+	     (string-match "^[[:alpha:]]+$" "abcde"))
+	(unless ispell-aspell-dictionary-alist
+	  (ispell-find-aspell-dictionaries)))
+
+    ;; Substitute ispell-dictionary-alist with the list of dictionaries
+    ;; corresponding to the given spellchecker. If a recent aspell, use
+    ;; the list of really installed dictionaries and add to it elements
+    ;; of the original list that are not present there. Allow distro info.
+    (let ((base-dicts-alist
+	   (append ispell-dictionary-alist-1 ispell-dictionary-alist-2
+		   ispell-dictionary-alist-3 ispell-dictionary-alist-4
+		   ispell-dictionary-alist-5 ispell-dictionary-alist-6))
+	  (found-dicts-alist
+	   (if (and ispell-really-aspell
+		    ispell-aspell-supports-utf8)
+	       ispell-aspell-dictionary-alist
+	     nil))
+	  distro-override-dicts-alist ; Override even found-dicts-alist
+	  distro-fallback-dicts-alist ; Override only base-dicts-alist
+	  all-dicts-alist)
+
+      ;; If distro has more info, consider it if needed. Mostly for possible
+      ;; ``distro-override-dicts-alist'' and ``distro-fallback-dicts-alist''.
+      (run-hooks 'ispell-spellchecker-init-pre-hook)
+
+      ;; Add dicts to ``ispell-dictionary-alist'' unless already present.
+      (setq all-dicts-alist distro-override-dicts-alist)
+      (dolist (dict (append found-dicts-alist
+			    distro-fallback-dicts-alist
+			    base-dicts-alist))
+	(unless (assoc (car dict) all-dicts-alist)
+	  (add-to-list 'all-dicts-alist dict)))
+      (setq ispell-dictionary-alist all-dicts-alist))
+    (setq ispell-last-program-name ispell-program-name)))
+
+;; Make ispell.el work better with aspell.
+
+(defvar ispell-aspell-dictionary-alist nil
+  "An alist of parsed aspell dicts and associated parameters.
+Internal use.")
 
 (defun ispell-find-aspell-dictionaries ()
   "Find Aspell's dictionaries, and record in `ispell-dictionary-alist'."
@@ -915,14 +958,13 @@
     (dolist (dict ispell-dictionary-alist)
       (unless (assoc (car dict) found)
 	(setq found (nconc found (list dict)))))
-    (setq ispell-dictionary-alist found)
+    (setq ispell-aspell-dictionary-alist found)
     ;; Add a default entry
     (let* ((english-dict (assoc "en" ispell-dictionary-alist))
 	   (default-dict
 	     (cons nil (or (cdr english-dict)
 			   (cdr (car ispell-dictionary-alist-1))))))
-      (push default-dict ispell-dictionary-alist))
-    (setq ispell-have-aspell-dictionaries t)))
+      (push default-dict ispell-aspell-dictionary-alist))))
 
 (defvar ispell-aspell-data-dir nil
   "Data directory of Aspell.")
@@ -1007,8 +1049,12 @@
 (defun ispell-valid-dictionary-list ()
   "Returns a list of valid dictionaries.
 The variable `ispell-library-directory' defines the library location."
-  ;; If Ispell is really Aspell, query it for the dictionary list.
-  (ispell-maybe-find-aspell-dictionaries)
+  ;; Initialize variables and dictionaries alists for desired spellchecker.
+  ;; Make sure ispell.el is loaded to avoid some autoload loops in xemacs
+  ;; (and may be others)
+  (if (featurep 'ispell)
+      (ispell-set-spellchecker-params))
+
   (let ((dicts (append ispell-local-dictionary-alist ispell-dictionary-alist))
 	(dict-list (cons "default" nil))
 	name load-dict)
@@ -1566,7 +1612,7 @@
     (ispell-region (region-beginning) (region-end)))
    (continue (ispell-continue))
    (t
-    (ispell-maybe-find-aspell-dictionaries)
+    (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
 	  (word (ispell-get-word following))
@@ -2602,7 +2648,7 @@
 	       (mapcar 'list (ispell-valid-dictionary-list)))
 	  nil t)
 	 current-prefix-arg))
-  (ispell-maybe-find-aspell-dictionaries)
+  (ispell-set-spellchecker-params) ; Initilize variables and dicts alists
   (unless arg (ispell-buffer-local-dict 'no-reload))
   (if (equal dict "default") (setq dict nil))
   ;; This relies on completing-read's bug of returning "" for no match
@@ -2653,7 +2699,7 @@
 Return nil if spell session is quit,
  otherwise returns shift offset amount for last line processed."
   (interactive "r")			; Don't flag errors on read-only bufs.
-  (ispell-maybe-find-aspell-dictionaries)
+  (ispell-set-spellchecker-params)      ; Initialize variables and dicts alists
   (if (not recheckp)
       (ispell-accept-buffer-local-defs)) ; set up dictionary, local words, etc.
   (let ((skip-region-start (make-marker))

[-- Attachment #3: flyspell.el_ispell-set-spellchecker-params.diff --]
[-- Type: text/x-diff, Size: 1536 bytes --]

--- flyspell.el.orig	2008-03-28 12:55:25.000000000 +0100
+++ flyspell.el	2008-03-28 12:58:02.000000000 +0100
@@ -578,7 +578,7 @@
 ;;*---------------------------------------------------------------------*/
 (defun flyspell-mode-on ()
   "Turn Flyspell mode on.  Do not use this; use `flyspell-mode' instead."
-  (ispell-maybe-find-aspell-dictionaries)
+  (ispell-set-spellchecker-params) ; Initialize variables and dicts alists
   (setq ispell-highlight-face 'flyspell-incorrect)
   ;; local dictionaries setup
   (or ispell-local-dictionary ispell-dictionary
@@ -1016,6 +1016,7 @@
 (defun flyspell-word (&optional following)
   "Spell check a word."
   (interactive (list ispell-following-word))
+  (ispell-set-spellchecker-params)    ; Initialize variables and dicts alists
   (save-excursion
     ;; use the correct dictionary
     (flyspell-accept-buffer-local-defs)
@@ -1531,7 +1532,7 @@
     ;; this is done, we can start checking...
     (if flyspell-issue-message-flag (message "Checking region..."))
     (set-buffer curbuf)
-    (ispell-check-version)
+    (ispell-set-spellchecker-params)  ; Initialize variables and dicts alists
     ;; Local dictionary becomes the global dictionary in use.
     (setq ispell-current-dictionary
 	  (or ispell-local-dictionary ispell-dictionary))
@@ -1590,6 +1591,7 @@
 (defun flyspell-region (beg end)
   "Flyspell text between BEG and END."
   (interactive "r")
+  (ispell-set-spellchecker-params)  ; Initialize variables and dicts alists
   (if (= beg end)
       ()
     (save-excursion

             reply	other threads:[~2008-04-04 12:02 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-04-04 12:02 Agustin Martin [this message]
2008-04-15 18:00 ` ispell.el, flyspell.el: better ispell/aspell switching Agustin Martin
2008-04-15 18:14   ` Lennart Borgman (gmail)
2008-04-15 18:40 ` Stefan Monnier
2008-04-15 18:47   ` Jason Rumney
2008-04-16  1:22     ` Stefan Monnier
2008-04-16  9:49   ` Agustin Martin
2008-04-16 15:21     ` Stefan Monnier
2008-04-17 17:56       ` Agustin Martin
2008-04-18  1:38         ` Stefan Monnier
2008-04-21 17:15           ` Agustin Martin
2008-04-23 20:40             ` Stefan Monnier

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

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

  git send-email \
    --in-reply-to=20080404120217.GA7503@agmartin.aq.upm.es \
    --to=agustin.martin@hispalinux.es \
    --cc=emacs-devel@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 external index

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.