aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReuben Thomas2016-12-04 22:39:27 +0000
committerReuben Thomas2017-08-07 21:57:22 +0100
commit7136e6723d87b51ae3089f5ceef6b14621bfaf87 (patch)
tree84122686488546bbdbb28410f4dc9cae37ce552e
parent85512e752191091d38cd5e34e7bed80eac1e9013 (diff)
downloademacs-7136e6723d87b51ae3089f5ceef6b14621bfaf87.tar.gz
emacs-7136e6723d87b51ae3089f5ceef6b14621bfaf87.zip
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.
-rw-r--r--lisp/textmodes/ispell.el79
1 files changed, 65 insertions, 14 deletions
diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el
index 773023a34a6..9ca43895581 100644
--- a/lisp/textmodes/ispell.el
+++ b/lisp/textmodes/ispell.el
@@ -208,6 +208,10 @@ Must be greater than 1."
208 :type 'integer 208 :type 'integer
209 :group 'ispell) 209 :group 'ispell)
210 210
211;; XXX Add enchant to this list once enchant >= 1.6.1 is widespread.
212;; Before that, adding it is useless, as if it is found, it will just
213;; cause an error; and one of the other spelling engines below is
214;; almost certainly installed in any case, for enchant to use.
211(defcustom ispell-program-name 215(defcustom ispell-program-name
212 (or (executable-find "aspell") 216 (or (executable-find "aspell")
213 (executable-find "ispell") 217 (executable-find "ispell")
@@ -605,6 +609,8 @@ english.aff). Aspell and Hunspell don't have this limitation.")
605 "Non-nil if we can use Aspell extensions.") 609 "Non-nil if we can use Aspell extensions.")
606(defvar ispell-really-hunspell nil 610(defvar ispell-really-hunspell nil
607 "Non-nil if we can use Hunspell extensions.") 611 "Non-nil if we can use Hunspell extensions.")
612(defvar ispell-really-enchant nil
613 "Non-nil if we can use Enchant extensions.")
608(defvar ispell-encoding8-command nil 614(defvar ispell-encoding8-command nil
609 "Command line option prefix to select encoding if supported, nil otherwise. 615 "Command line option prefix to select encoding if supported, nil otherwise.
610If setting the encoding is supported by spellchecker and is selectable from 616If 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."
739 (and (search-forward-regexp 745 (and (search-forward-regexp
740 "(but really Hunspell \\([0-9]+\\.[0-9\\.-]+\\)?)" 746 "(but really Hunspell \\([0-9]+\\.[0-9\\.-]+\\)?)"
741 nil t) 747 nil t)
748 (match-string 1)))
749 (setq ispell-really-enchant
750 (and (search-forward-regexp
751 "(but really Enchant \\([0-9]+\\.[0-9\\.-]+\\)?)"
752 nil t)
742 (match-string 1))))) 753 (match-string 1)))))
743 754
744 (let* ((aspell8-minver "0.60") 755 (let* ((aspell8-minver "0.60")
745 (ispell-minver "3.1.12") 756 (ispell-minver "3.1.12")
746 (hunspell8-minver "1.1.6") 757 (hunspell8-minver "1.1.6")
758 (enchant-minver "1.6.1")
747 (minver (cond 759 (minver (cond
748 ((not (version<= ispell-minver ispell-program-version)) 760 ((not (version<= ispell-minver ispell-program-version))
749 ispell-minver) 761 ispell-minver)
750 ((and ispell-really-aspell 762 ((and ispell-really-aspell
751 (not (version<= aspell8-minver ispell-really-aspell))) 763 (not (version<= aspell8-minver ispell-really-aspell)))
752 aspell8-minver)))) 764 aspell8-minver)
765 ((and ispell-really-enchant
766 (not (version<= enchant-minver ispell-really-enchant)))
767 enchant-minver))))
753 768
754 (if minver 769 (if minver
755 (error "%s release %s or greater is required" 770 (error "%s release %s or greater is required"
@@ -1183,6 +1198,36 @@ dictionary from that list was found."
1183 (list dict)) 1198 (list dict))
1184 ispell-hunspell-dictionary-alist :test #'equal)))) 1199 ispell-hunspell-dictionary-alist :test #'equal))))
1185 1200
1201;; Make ispell.el work better with enchant.
1202
1203(defvar ispell-enchant-dictionary-alist nil
1204 "An alist of parsed Enchant dicts and associated parameters.
1205Internal use.")
1206
1207(defun ispell-find-enchant-dictionaries ()
1208 "Find Enchant's dictionaries, and record in `ispell-enchant-dictionary-alist'."
1209 (let* ((dictionaries
1210 (split-string
1211 (with-temp-buffer
1212 (ispell-call-process
1213 (concat ispell-program-name "-lsmod") nil t nil "-list-dicts")
1214 (buffer-string))
1215 " ([^)]+)\n"))
1216 (found
1217 (mapcar #'(lambda (lang)
1218 `(,lang "[[:alpha:]]" "[^[:alpha:]]" "['.’-]" t nil nil utf-8))
1219 dictionaries)))
1220 ;; Merge into FOUND any elements from the standard ispell-dictionary-base-alist
1221 ;; which have no element in FOUND at all.
1222 (dolist (dict ispell-dictionary-base-alist)
1223 (unless (assoc (car dict) found)
1224 (setq found (nconc found (list dict)))))
1225 (setq ispell-enchant-dictionary-alist found)
1226 ;; Add a default entry
1227 (let ((default-dict
1228 '(nil "[[:alpha:]]" "[^[:alpha:]]" "['.’-]" t nil nil utf-8)))
1229 (push default-dict ispell-enchant-dictionary-alist))))
1230
1186;; Set params according to the selected spellchecker 1231;; Set params according to the selected spellchecker
1187 1232
1188(defvar ispell-last-program-name nil 1233(defvar ispell-last-program-name nil
@@ -1208,7 +1253,7 @@ aspell is used along with Emacs).")
1208 (setq ispell-library-directory (ispell-check-version)) 1253 (setq ispell-library-directory (ispell-check-version))
1209 t) 1254 t)
1210 (error nil)) 1255 (error nil))
1211 ispell-encoding8-command) 1256 (or ispell-encoding8-command ispell-really-enchant))
1212 ;; auto-detection will only be used if spellchecker is not 1257 ;; auto-detection will only be used if spellchecker is not
1213 ;; ispell and supports a way to set communication to UTF-8. 1258 ;; ispell and supports a way to set communication to UTF-8.
1214 (if ispell-really-aspell 1259 (if ispell-really-aspell
@@ -1216,11 +1261,14 @@ aspell is used along with Emacs).")
1216 (ispell-find-aspell-dictionaries)) 1261 (ispell-find-aspell-dictionaries))
1217 (if ispell-really-hunspell 1262 (if ispell-really-hunspell
1218 (or ispell-hunspell-dictionary-alist 1263 (or ispell-hunspell-dictionary-alist
1219 (ispell-find-hunspell-dictionaries))))) 1264 (ispell-find-hunspell-dictionaries))
1265 (if ispell-really-enchant
1266 (or ispell-enchant-dictionary-alist
1267 (ispell-find-enchant-dictionaries))))))
1220 1268
1221 ;; Substitute ispell-dictionary-alist with the list of 1269 ;; Substitute ispell-dictionary-alist with the list of
1222 ;; dictionaries corresponding to the given spellchecker. 1270 ;; dictionaries corresponding to the given spellchecker.
1223 ;; If a recent aspell or hunspell, use the list of really 1271 ;; With programs that support it, use the list of really
1224 ;; installed dictionaries and add to it elements of the original 1272 ;; installed dictionaries and add to it elements of the original
1225 ;; list that are not present there. Allow distro info. 1273 ;; list that are not present there. Allow distro info.
1226 (let ((found-dicts-alist 1274 (let ((found-dicts-alist
@@ -1229,17 +1277,19 @@ aspell is used along with Emacs).")
1229 ispell-aspell-dictionary-alist 1277 ispell-aspell-dictionary-alist
1230 (if ispell-really-hunspell 1278 (if ispell-really-hunspell
1231 ispell-hunspell-dictionary-alist)) 1279 ispell-hunspell-dictionary-alist))
1232 nil)) 1280 (if ispell-really-enchant
1281 ispell-enchant-dictionary-alist
1282 nil)))
1233 (ispell-dictionary-base-alist ispell-dictionary-base-alist) 1283 (ispell-dictionary-base-alist ispell-dictionary-base-alist)
1234 ispell-base-dicts-override-alist ; Override only base-dicts-alist 1284 ispell-base-dicts-override-alist ; Override only base-dicts-alist
1235 all-dicts-alist) 1285 all-dicts-alist)
1236 1286
1237 ;; While ispell and aspell (through aliases) use the traditional 1287 ;; While ispell and aspell (through aliases) use the traditional
1238 ;; dict naming originally expected by ispell.el, hunspell 1288 ;; dict naming originally expected by ispell.el, hunspell & Enchant
1239 ;; uses locale based names with no alias. We need to map 1289 ;; use locale-based names with no alias. We need to map
1240 ;; standard names to locale based names to make default dict 1290 ;; standard names to locale based names to make default dict
1241 ;; definitions available for hunspell. 1291 ;; definitions available to these programs.
1242 (if ispell-really-hunspell 1292 (if (or ispell-really-hunspell ispell-really-enchant)
1243 (let (tmp-dicts-alist) 1293 (let (tmp-dicts-alist)
1244 (dolist (adict ispell-dictionary-base-alist) 1294 (dolist (adict ispell-dictionary-base-alist)
1245 (let* ((dict-name (nth 0 adict)) 1295 (let* ((dict-name (nth 0 adict))
@@ -1264,7 +1314,7 @@ aspell is used along with Emacs).")
1264 (setq ispell-args 1314 (setq ispell-args
1265 (nconc ispell-args (list "-d" dict-equiv))) 1315 (nconc ispell-args (list "-d" dict-equiv)))
1266 (message 1316 (message
1267 "ispell-set-spellchecker-params: Missing Hunspell equiv for \"%s\". Skipping." 1317 "ispell-set-spellchecker-params: Missing equivalent for \"%s\". Skipping."
1268 dict-name) 1318 dict-name)
1269 (setq skip-dict t))) 1319 (setq skip-dict t)))
1270 1320
@@ -1306,7 +1356,7 @@ aspell is used along with Emacs).")
1306 (nth 4 adict) ; many-otherchars-p 1356 (nth 4 adict) ; many-otherchars-p
1307 (nth 5 adict) ; ispell-args 1357 (nth 5 adict) ; ispell-args
1308 (nth 6 adict) ; extended-character-mode 1358 (nth 6 adict) ; extended-character-mode
1309 (if ispell-encoding8-command 1359 (if (or ispell-encoding8-command ispell-really-enchant)
1310 'utf-8 1360 'utf-8
1311 (nth 7 adict))) 1361 (nth 7 adict)))
1312 adict) 1362 adict)
@@ -1742,9 +1792,10 @@ and pass it the output of the last Ispell invocation."
1742 (erase-buffer))))))) 1792 (erase-buffer)))))))
1743 1793
1744(defun ispell-send-replacement (misspelled replacement) 1794(defun ispell-send-replacement (misspelled replacement)
1745 "Notify Aspell that MISSPELLED should be spelled REPLACEMENT. 1795 "Notify spell checker that MISSPELLED should be spelled REPLACEMENT.
1746This allows improving the suggestion list based on actual misspellings." 1796This allows improving the suggestion list based on actual misspellings.
1747 (and ispell-really-aspell 1797Only works for Aspell and Enchant."
1798 (and (or ispell-really-aspell ispell-really-enchant)
1748 (ispell-send-string (concat "$$ra " misspelled "," replacement "\n")))) 1799 (ispell-send-string (concat "$$ra " misspelled "," replacement "\n"))))
1749 1800
1750 1801