diff options
author | Reuben Thomas <rrt@sc3d.org> | 2016-12-04 22:39:27 +0000 |
---|---|---|
committer | Reuben Thomas <rrt@sc3d.org> | 2017-08-20 11:55:40 +0100 |
commit | 60d417545a2852d36427799691792e4ddff8f86c (patch) | |
tree | a41da04223d1129ee7862819f985db54c641e5bb /lisp/textmodes/ispell.el | |
parent | dbd3a17cb068148bd49e288eb0b44ca7eb4a4e3c (diff) | |
download | emacs-60d417545a2852d36427799691792e4ddff8f86c.tar.gz |
Add Enchant support to ispell.el (Bug#17742)
* lisp/textmodes/ispell.el (ispell-program-name): Add “enchant”.
(ispell-really-enchant): Add variable.
(ispell-check-version): If using Enchant, check it’s new enough (at
least 1.6.1). (Like the ispell check, this is absolute: cannot work
without.)
(ispell-enchant-dictionary-alist): Add variable.
(ispell-find-enchant-dictionaries): Add function, based on
ispell-find-aspell-dictionaries.
(ispell-set-spellchecker-params): Allow dictionary auto-detection for
Enchant, and call ispell-find-enchant-dictionaries to find them. Use
old ispell name to locale mapping code for Enchant too.
(ispell-send-replacement): Make it work with Enchant.
Diffstat (limited to 'lisp/textmodes/ispell.el')
-rw-r--r-- | lisp/textmodes/ispell.el | 92 |
1 files changed, 78 insertions, 14 deletions
diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el index 773023a34a6..e6ca32f20d9 100644 --- a/lisp/textmodes/ispell.el +++ b/lisp/textmodes/ispell.el @@ -208,6 +208,10 @@ Must be greater than 1." :type 'integer :group 'ispell) +;; XXX Add enchant to this list once enchant >= 2.1.0 is widespread. +;; Before that, adding it is useless, as if it is found, it will just +;; cause an error; and one of the other spelling engines below is +;; almost certainly installed in any case, for enchant to use. (defcustom ispell-program-name (or (executable-find "aspell") (executable-find "ispell") @@ -605,6 +609,8 @@ english.aff). Aspell and Hunspell don't have this limitation.") "Non-nil if we can use Aspell extensions.") (defvar ispell-really-hunspell nil "Non-nil if we can use Hunspell extensions.") +(defvar ispell-really-enchant nil + "Non-nil if we can use Enchant extensions.") (defvar ispell-encoding8-command nil "Command line option prefix to select encoding if supported, nil otherwise. If setting the encoding is supported by spellchecker and is selectable from @@ -739,17 +745,26 @@ Otherwise returns the library directory name, if that is defined." (and (search-forward-regexp "(but really Hunspell \\([0-9]+\\.[0-9\\.-]+\\)?)" nil t) + (match-string 1))) + (setq ispell-really-enchant + (and (search-forward-regexp + "(but really Enchant \\([0-9]+\\.[0-9\\.-]+\\)?)" + nil t) (match-string 1))))) (let* ((aspell8-minver "0.60") (ispell-minver "3.1.12") (hunspell8-minver "1.1.6") + (enchant-minver "2.1.0") (minver (cond ((not (version<= ispell-minver ispell-program-version)) ispell-minver) ((and ispell-really-aspell (not (version<= aspell8-minver ispell-really-aspell))) - aspell8-minver)))) + aspell8-minver) + ((and ispell-really-enchant + (not (version<= enchant-minver ispell-really-enchant))) + enchant-minver)))) (if minver (error "%s release %s or greater is required" @@ -1183,6 +1198,49 @@ dictionary from that list was found." (list dict)) ispell-hunspell-dictionary-alist :test #'equal)))) +;; Make ispell.el work better with enchant. + +(defvar ispell-enchant-dictionary-alist nil + "An alist of parsed Enchant dicts and associated parameters. +Internal use.") + +(defun ispell--call-enchant-lsmod (&rest args) + "Call enchant-lsmod with ARGS and return the output as string." + (with-output-to-string + (with-current-buffer + standard-output + (apply 'ispell-call-process + (concat ispell-program-name "-lsmod") nil t nil args)))) + +(defun ispell--get-extra-word-characters (&optional lang) + "Get the extra word characters for LANG as a character class. +If LANG is omitted, get the extra word characters for the default language." + (concat "[" (string-trim-right (apply 'ispell--call-enchant-lsmod + (append '("-word-chars") (if lang `(,lang))))) "]")) + +(defun ispell-find-enchant-dictionaries () + "Find Enchant's dictionaries, and record in `ispell-enchant-dictionary-alist'." + (let* ((dictionaries + (split-string + (ispell--call-enchant-lsmod "-list-dicts" (buffer-string)) " ([^)]+)\n")) + (found + (mapcar #'(lambda (lang) + `(,lang "[[:alpha:]]" "[^[:alpha:]]" + ,(ispell--get-extra-word-characters) t nil nil utf-8)) + dictionaries))) + ;; Merge into FOUND any elements from the standard ispell-dictionary-base-alist + ;; which have no element in FOUND at all. + (dolist (dict ispell-dictionary-base-alist) + (unless (assoc (car dict) found) + (setq found (nconc found (list dict))))) + (setq ispell-enchant-dictionary-alist found) + ;; Add a default entry + (let ((default-dict + `(nil "[[:alpha:]]" "[^[:alpha:]]" + ,(ispell--get-extra-word-characters) + t nil nil utf-8))) + (push default-dict ispell-enchant-dictionary-alist)))) + ;; Set params according to the selected spellchecker (defvar ispell-last-program-name nil @@ -1208,7 +1266,7 @@ aspell is used along with Emacs).") (setq ispell-library-directory (ispell-check-version)) t) (error nil)) - ispell-encoding8-command) + (or ispell-encoding8-command ispell-really-enchant)) ;; auto-detection will only be used if spellchecker is not ;; ispell and supports a way to set communication to UTF-8. (if ispell-really-aspell @@ -1216,11 +1274,14 @@ aspell is used along with Emacs).") (ispell-find-aspell-dictionaries)) (if ispell-really-hunspell (or ispell-hunspell-dictionary-alist - (ispell-find-hunspell-dictionaries))))) + (ispell-find-hunspell-dictionaries)) + (if ispell-really-enchant + (or ispell-enchant-dictionary-alist + (ispell-find-enchant-dictionaries)))))) ;; Substitute ispell-dictionary-alist with the list of ;; dictionaries corresponding to the given spellchecker. - ;; If a recent aspell or hunspell, use the list of really + ;; With programs that support it, 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 ((found-dicts-alist @@ -1229,17 +1290,19 @@ aspell is used along with Emacs).") ispell-aspell-dictionary-alist (if ispell-really-hunspell ispell-hunspell-dictionary-alist)) - nil)) + (if ispell-really-enchant + ispell-enchant-dictionary-alist + nil))) (ispell-dictionary-base-alist ispell-dictionary-base-alist) ispell-base-dicts-override-alist ; Override only base-dicts-alist all-dicts-alist) ;; While ispell and aspell (through aliases) use the traditional - ;; dict naming originally expected by ispell.el, hunspell - ;; uses locale based names with no alias. We need to map + ;; dict naming originally expected by ispell.el, hunspell & Enchant + ;; use locale-based names with no alias. We need to map ;; standard names to locale based names to make default dict - ;; definitions available for hunspell. - (if ispell-really-hunspell + ;; definitions available to these programs. + (if (or ispell-really-hunspell ispell-really-enchant) (let (tmp-dicts-alist) (dolist (adict ispell-dictionary-base-alist) (let* ((dict-name (nth 0 adict)) @@ -1264,7 +1327,7 @@ aspell is used along with Emacs).") (setq ispell-args (nconc ispell-args (list "-d" dict-equiv))) (message - "ispell-set-spellchecker-params: Missing Hunspell equiv for \"%s\". Skipping." + "ispell-set-spellchecker-params: Missing equivalent for \"%s\". Skipping." dict-name) (setq skip-dict t))) @@ -1306,7 +1369,7 @@ aspell is used along with Emacs).") (nth 4 adict) ; many-otherchars-p (nth 5 adict) ; ispell-args (nth 6 adict) ; extended-character-mode - (if ispell-encoding8-command + (if (or ispell-encoding8-command ispell-really-enchant) 'utf-8 (nth 7 adict))) adict) @@ -1742,9 +1805,10 @@ and pass it the output of the last Ispell invocation." (erase-buffer))))))) (defun ispell-send-replacement (misspelled replacement) - "Notify Aspell that MISSPELLED should be spelled REPLACEMENT. -This allows improving the suggestion list based on actual misspellings." - (and ispell-really-aspell + "Notify spell checker that MISSPELLED should be spelled REPLACEMENT. +This allows improving the suggestion list based on actual misspellings. +Only works for Aspell and Enchant." + (and (or ispell-really-aspell ispell-really-enchant) (ispell-send-string (concat "$$ra " misspelled "," replacement "\n")))) |