Mercurial > emacs
diff lisp/textmodes/ispell.el @ 90224:2d92f5c9d6ae
Revision: miles@gnu.org--gnu-2005/emacs--unicode--0--patch-78
Merge from emacs--cvs-trunk--0
Patches applied:
* emacs--cvs-trunk--0 (patch 514-518)
- Update from CVS
- Merge from gnus--rel--5.10
* gnus--rel--5.10 (patch 104-105)
- Update from CVS
author | Miles Bader <miles@gnu.org> |
---|---|
date | Fri, 26 Aug 2005 09:51:52 +0000 |
parents | fbb2bea03df9 008b8c9ce315 |
children | a3716f7538f2 |
line wrap: on
line diff
--- a/lisp/textmodes/ispell.el Fri Aug 05 10:57:36 2005 +0000 +++ b/lisp/textmodes/ispell.el Fri Aug 26 09:51:52 2005 +0000 @@ -1,7 +1,7 @@ ;;; ispell.el --- interface to International Ispell Versions 3.1 and 3.2 -;; Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005 -;; Free Software Foundation, Inc. +;; Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, +;; 2004, 2005 Free Software Foundation, Inc. ;; Author: Ken Stevens <k.stevens@ieee.org> ;; Maintainer: Ken Stevens <k.stevens@ieee.org> @@ -862,9 +862,113 @@ ) "Non-nil means that the OS supports asynchronous processes.") +;; Make ispell.el work better with aspell. + +(defvar ispell-have-aspell-dictionaries nil + "Non-nil if we have queried Aspell for dictionaries at least once.") + +(defun ispell-find-aspell-dictionaries () + "Find Aspell's dictionaries, and record in `ispell-dictionary-alist'." + (interactive) + (unless ispell-really-aspell + (error "This function only works with aspell")) + (let ((dictionaries + (split-string + (with-temp-buffer + (call-process ispell-program-name nil t nil "dicts") + (buffer-string))))) + (setq ispell-dictionary-alist + (mapcar #'ispell-aspell-find-dictionary dictionaries)) + (ispell-aspell-add-aliases) + ;; Add a default entry + (let* ((english-dict (assoc "en" ispell-dictionary-alist)) + (default-dict (cons nil (cdr english-dict)))) + (push default-dict ispell-dictionary-alist)) + (setq ispell-have-aspell-dictionaries t))) + +(defvar ispell-aspell-data-dir nil + "Data directory of Aspell.") + +(defvar ispell-aspell-dict-dir nil + "Dictionary directory of Aspell.") + +(defun ispell-get-aspell-config-value (key) + "Return value of Aspell configuration option KEY. +Assumes that value contains no whitespace." + (with-temp-buffer + (call-process ispell-program-name nil t nil "config" key) + (car (split-string (buffer-string))))) + +(defun ispell-aspell-find-dictionary (dict-name) + (let* ((lang ;; Strip out region, variant, etc. + (and (string-match "^[[:alpha:]]+" dict-name) + (match-string 0 dict-name))) + (data-file + (concat (or ispell-aspell-data-dir + (setq ispell-aspell-data-dir + (ispell-get-aspell-config-value "data-dir"))) + "/" lang ".dat")) + otherchars) + ;; This file really should exist; there is no sensible recovery. + (with-temp-buffer + (insert-file-contents data-file) + ;; There is zero or one line with special characters declarations. + (when (search-forward-regexp "^special" nil t) + (let ((specials (split-string + (buffer-substring (point) + (progn (end-of-line) (point)))))) + ;; The line looks like: special ' -** - -** . -** : -*- + ;; -** means that this character + ;; - doesn't appear at word start + ;; * may appear in the middle of a word + ;; * may appear at word end + ;; `otherchars' is about the middle case. + (while specials + (when (eq (aref (cadr specials) 1) ?*) + (push (car specials) otherchars)) + (setq specials (cddr specials)))))) + (list dict-name + "[[:alpha:]]" + "[^[:alpha:]]" + (regexp-opt otherchars) + t ; We can't tell, so set this to t + (list "-d" dict-name "--encoding=utf-8") + nil ; aspell doesn't support this + ;; Here we specify the encoding to use while communicating with + ;; aspell. This doesn't apply to command line arguments, so + ;; just don't pass words to spellcheck as arguments... + 'utf-8))) + +(defun ispell-aspell-add-aliases () + "Find aspell's dictionary aliases and add them to `ispell-dictionary-alist'." + (let ((aliases (file-expand-wildcards + (concat (or ispell-aspell-dict-dir + (setq ispell-aspell-dict-dir + (ispell-get-aspell-config-value "dict-dir"))) + "/*.alias")))) + (dolist (alias-file aliases) + (with-temp-buffer + (insert-file-contents alias-file) + ;; Look for a line "add FOO.multi", extract FOO + (when (search-forward-regexp "^add \\([^.]+\\)\\.multi" nil t) + (let* ((aliasname (file-name-sans-extension + (file-name-nondirectory alias-file))) + (already-exists-p (assoc aliasname ispell-dictionary-alist)) + (realname (match-string 1)) + (realdict (assoc realname ispell-dictionary-alist))) + (when (and realdict (not already-exists-p)) + (push (cons aliasname (cdr realdict)) ispell-dictionary-alist)))))))) + (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. + (when (and (not ispell-have-aspell-dictionaries) + (condition-case () + (progn (ispell-check-version) t) + (error nil)) + ispell-really-aspell) + (ispell-find-aspell-dictionaries)) (let ((dicts (append ispell-local-dictionary-alist ispell-dictionary-alist)) (dict-list (cons "default" nil)) name load-dict) @@ -875,7 +979,9 @@ (if (and name ;; include all dictionaries if lib directory not known. - (or (not ispell-library-directory) + ;; For Aspell, we already know which dictionaries exist. + (or ispell-really-aspell + (not ispell-library-directory) (file-exists-p (concat ispell-library-directory "/" name ".hash")) (file-exists-p (concat ispell-library-directory "/" name ".has")) @@ -887,36 +993,11 @@ (setq dict-list (cons name dict-list)))) dict-list)) -;;;###autoload -(if ispell-menu-map-needed - (let ((dicts (if (fboundp 'ispell-valid-dictionary-list) - (ispell-valid-dictionary-list) - ;; This case is used in loaddefs.el - ;; since ispell-valid-dictionary-list isn't defined then. - (mapcar (lambda (x) (or (car x) "default")) - ispell-dictionary-alist))) - (dict-map (make-sparse-keymap "Dictionaries"))) - (setq ispell-menu-map (make-sparse-keymap "Spell")) - ;; add the dictionaries to the bottom of the list. - (if (not dicts) - (define-key ispell-menu-map [default] - '("Select Default Dict" - "Dictionary for which Ispell was configured" - . (lambda () (interactive) - (ispell-change-dictionary "default"))))) - (fset 'ispell-dict-map dict-map) - (define-key ispell-menu-map [dictionaries] - `(menu-item "Select Dict" ispell-dict-map)) - (dolist (name dicts) - (define-key dict-map (vector (intern name)) - (cons (concat "Select " (capitalize name) " Dict") - `(lambda () (interactive) - (ispell-change-dictionary ,name))))))) - ;;; define commands in menu in opposite order you want them to appear. ;;;###autoload (if ispell-menu-map-needed (progn + (setq ispell-menu-map (make-sparse-keymap "Spell")) (define-key ispell-menu-map [ispell-change-dictionary] '(menu-item "Change Dictionary..." ispell-change-dictionary :help "Supply explicit dictionary file name")) @@ -1461,7 +1542,8 @@ (funcall ispell-format-word word))) (and (fboundp 'extent-at) (extent-at start) - (delete-extent (extent-at start)))) + (and (fboundp 'delete-extent) + (delete-extent (extent-at start))))) ((stringp poss) (or quietly (message "%s is correct because of root %s" @@ -1469,13 +1551,15 @@ (funcall ispell-format-word poss))) (and (fboundp 'extent-at) (extent-at start) - (delete-extent (extent-at start)))) + (and (fboundp 'delete-extent) + (delete-extent (extent-at start))))) ((null poss) (message "Error in ispell process")) (ispell-check-only ; called from ispell minor mode. (if (fboundp 'make-extent) - (let ((ext (make-extent start end))) - (set-extent-property ext 'face ispell-highlight-face) - (set-extent-property ext 'priority 2000)) + (if (fboundp 'set-extent-property) + (let ((ext (make-extent start end))) + (set-extent-property ext 'face ispell-highlight-face) + (set-extent-property ext 'priority 2000))) (beep) (message "%s is incorrect"(funcall ispell-format-word word)))) (t ; prompt for correct word. @@ -2036,9 +2120,13 @@ (while (search-backward "*" nil t) (insert ".")) (setq word (buffer-string)) (erase-buffer)) - (setq status (if lookup-dict - (call-process prog nil t nil args word lookup-dict) - (call-process prog nil t nil args word))) + (setq status (apply 'call-process prog nil t nil + (nconc (if (and args (> (length args) 0)) + (list args) + (if look-p nil + (list "-e"))) + (list word) + (if lookup-dict (list lookup-dict))))) ;; grep returns status 1 and no output when word not found, which ;; is a perfectly normal thing. (if (stringp status)