diff options
| author | Reuben Thomas | 2016-12-04 22:39:27 +0000 |
|---|---|---|
| committer | Reuben Thomas | 2017-08-07 21:57:22 +0100 |
| commit | 7136e6723d87b51ae3089f5ceef6b14621bfaf87 (patch) | |
| tree | 84122686488546bbdbb28410f4dc9cae37ce552e | |
| parent | 85512e752191091d38cd5e34e7bed80eac1e9013 (diff) | |
| download | emacs-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.el | 79 |
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. |
| 610 | If setting the encoding is supported by spellchecker and is selectable from | 616 | 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." | |||
| 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. | ||
| 1205 | Internal 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. |
| 1746 | This allows improving the suggestion list based on actual misspellings." | 1796 | This allows improving the suggestion list based on actual misspellings. |
| 1747 | (and ispell-really-aspell | 1797 | Only 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 | ||