ispell.el 172 KB
Newer Older
1
;;; ispell.el --- interface to International Ispell Versions 3.1 and 3.2  -*- lexical-binding:t -*-
Richard M. Stallman's avatar
Richard M. Stallman committed
2

Paul Eggert's avatar
Paul Eggert committed
3
;; Copyright (C) 1994-1995, 1997-2016 Free Software Foundation, Inc.
Richard M. Stallman's avatar
Richard M. Stallman committed
4

5
;; Author:           Ken Stevens <k.stevens@ieee.org>
6
;; Status          : Release with 3.1.12+ and 3.2.0+ ispell.
Dave Love's avatar
Dave Love committed
7
;; Keywords: unix wp
Richard M. Stallman's avatar
Richard M. Stallman committed
8

Erik Naggum's avatar
Erik Naggum committed
9 10
;; This file is part of GNU Emacs.

11
;; GNU Emacs is free software: you can redistribute it and/or modify
Erik Naggum's avatar
Erik Naggum committed
12
;; it under the terms of the GNU General Public License as published by
13 14
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
Erik Naggum's avatar
Erik Naggum committed
15 16 17 18 19 20 21

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
22
;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
Erik Naggum's avatar
Erik Naggum committed
23 24

;; Note: version numbers and time stamp are not updated
Stefan Monnier's avatar
Stefan Monnier committed
25
;;   when this file is edited for release with GNU Emacs.
Richard M. Stallman's avatar
Richard M. Stallman committed
26

Richard M. Stallman's avatar
Richard M. Stallman committed
27 28
;;; Commentary:

Erik Naggum's avatar
Erik Naggum committed
29
;; INSTRUCTIONS
30

31 32 33 34
;;   This code contains a section of user-settable variables that you
;; should inspect prior to installation.  Look past the end of the history
;; list.  Set them up for your locale and the preferences of the majority
;; of the users.  Otherwise the users may need to set a number of variables
Erik Naggum's avatar
Erik Naggum committed
35
;; themselves.
36
;;   You particularly may want to change the default dictionary for your
Erik Naggum's avatar
Erik Naggum committed
37
;; country and language.
38 39
;;   Most dictionary changes should be made in this file so all users can
;; enjoy them.  Local or modified dictionaries are supported in your .emacs
40 41
;; file.  Use the variable `ispell-local-dictionary-alist' to specify
;; your own dictionaries.
42

Erik Naggum's avatar
Erik Naggum committed
43
;;  Depending on the mail system you use, you may want to include these:
44 45 46
;;  (add-hook 'news-inews-hook #'ispell-message)
;;  (add-hook 'mail-send-hook  #'ispell-message)
;;  (add-hook 'mh-before-send-letter-hook #'ispell-message)
47

48
;;   Ispell has a TeX parser and a nroff parser (the default).
Erik Naggum's avatar
Erik Naggum committed
49 50 51
;; The parsing is controlled by the variable ispell-parser.  Currently
;; it is just a "toggle" between TeX and nroff, but if more parsers are
;; added it will be updated.  See the variable description for more info.
52 53


Erik Naggum's avatar
Erik Naggum committed
54
;; TABLE OF CONTENTS
55

Erik Naggum's avatar
Erik Naggum committed
56 57 58 59
;;   ispell-word
;;   ispell-region
;;   ispell-buffer
;;   ispell-message
60
;;   ispell-comments-and-strings
Erik Naggum's avatar
Erik Naggum committed
61 62 63 64 65 66
;;   ispell-continue
;;   ispell-complete-word
;;   ispell-complete-word-interior-frag
;;   ispell-change-dictionary
;;   ispell-kill-ispell
;;   ispell-pdict-save
67 68
;;   ispell-skip-region-alist

Erik Naggum's avatar
Erik Naggum committed
69 70
;; Commands in ispell-region:
;; Character replacement: Replace word with choice.  May query-replace.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
;; ` ': Accept word this time.
;; `i': Accept word and insert into private dictionary.
;; `a': Accept word for this session.
;; `A': Accept word and place in buffer-local dictionary.
;; `r': Replace word with typed-in value.  Rechecked.
;; `R': Replace word with typed-in value. Query-replaced in buffer. Rechecked.
;; `?': Show these commands
;; `x': Exit spelling buffer.  Move cursor to original point.
;; `X': Exit spelling buffer.  Leaves cursor at the current point, and permits
;;      the check to be completed later.
;; `q': Quit spelling session (Kills ispell process).
;; `l': Look up typed-in replacement in alternate dictionary.  Wildcards okay.
;; `u': Like `i', but the word is lower-cased first.
;; `m': Place entered value in personal dictionary, then recheck current word.
;; `C-l': redraws screen
;; `C-r': recursive edit
Stefan Monnier's avatar
Stefan Monnier committed
87
;; `C-z': suspend Emacs or iconify frame
88

Erik Naggum's avatar
Erik Naggum committed
89 90 91 92 93 94 95 96
;; Buffer-Local features:
;; There are a number of buffer-local features that can be used to customize
;;  ispell for the current buffer.  This includes language dictionaries,
;;  personal dictionaries, parsing, and local word spellings.  Each of these
;;  local customizations are done either through local variables, or by
;;  including the keyword and argument(s) at the end of the buffer (usually
;;  prefixed by the comment characters).  See the end of this file for
;;  examples.  The local keywords and variables are:
97

Erik Naggum's avatar
Erik Naggum committed
98 99 100 101 102 103
;;  ispell-dictionary-keyword   language-dictionary
;;      uses local variable ispell-local-dictionary
;;  ispell-pdict-keyword        personal-dictionary
;;      uses local variable ispell-local-pdict
;;  ispell-parsing-keyword      mode-arg extended-char-arg
;;  ispell-words-keyword        any number of local word spellings
104 105 106 107 108 109 110

;; Region skipping:
;;  Place new regular expression definitions of regions you prefer not to
;;  spell check in `ispell-skip-region-alist'.  Mode-dependent features can
;;  be added to latex by modifying `ispell-tex-skip-alists'.
;;  `ispell-message' contains some custom skipping code for e-mail messages.

Erik Naggum's avatar
Erik Naggum committed
111
;; BUGS:
112 113 114
;;  Need a way to select between different character mappings without separate
;;    dictionary entries.
;;  Multi-byte characters if not defined by current dictionary may result in the
Stefan Monnier's avatar
Stefan Monnier committed
115 116
;;    evil "misalignment error" in some versions of MULE Emacs.
;;  On some versions of Emacs, growing the minibuffer fails.
117
;;    see `ispell-help-in-bufferp'.
118 119
;;  Recursive edits (?C-r or ?R) inside a keyboard text replacement check (?r)
;;    can cause misalignment errors.
120

121 122 123
;;; XEmacs21 does not have `with-no-warnings'. Taken from org mode.
(defmacro ispell-with-no-warnings (&rest body)
  (cons (if (fboundp 'with-no-warnings) 'with-no-warnings 'progn) body))
124

Richard M. Stallman's avatar
Richard M. Stallman committed
125 126
;;; Code:

127 128
(eval-when-compile (require 'cl-lib))

129 130
(defvar mail-yank-prefix)

131
(defgroup ispell nil
132
  "User variables for Emacs ispell interface."
133
  :group 'applications)
134

135
(defalias 'check-ispell-version 'ispell-check-version)
136

137 138 139 140 141 142
;;; **********************************************************************
;;; The following variables should be set according to personal preference
;;; and location of binaries:
;;; **********************************************************************


143
;;;  ******* THIS FILE IS WRITTEN FOR ISPELL VERSION 3.1+
144 145

(defcustom ispell-highlight-p 'block
146
  "Highlight spelling errors when non-nil.
147
When set to `block', assumes a block cursor with TTY displays."
148
  :type '(choice (const block) (const :tag "off" nil) (const :tag "on" t))
149 150
  :group 'ispell)

151
(defcustom ispell-lazy-highlight (boundp 'lazy-highlight-cleanup)
152
  "Controls the lazy-highlighting of spelling errors.
153 154 155 156 157 158 159 160 161
When non-nil, all text in the buffer matching the current spelling
error is highlighted lazily using isearch lazy highlighting (see
`lazy-highlight-initial-delay' and `lazy-highlight-interval')."
  :type 'boolean
  :group 'lazy-highlight
  :group 'ispell
  :version "22.1")

(defcustom ispell-highlight-face (if ispell-lazy-highlight 'isearch 'highlight)
162
  "Face used for Ispell highlighting.
Richard M. Stallman's avatar
Richard M. Stallman committed
163 164
This variable can be set by the user to whatever face they desire.
It's most convenient if the cursor color and highlight color are
165 166 167
slightly different."
  :type 'face
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
168

169
(defcustom ispell-check-comments t
170
  "Spelling of comments checked when non-nil.
171 172 173
When set to `exclusive', ONLY comments are checked.  (For code comments).
Warning!  Not checking comments, when a comment start is embedded in strings,
may produce undesired results."
174
  :type '(choice (const exclusive) (const :tag "off" nil) (const :tag "on" t))
175
  :group 'ispell)
176 177 178
;;;###autoload
(put 'ispell-check-comments 'safe-local-variable
     (lambda (a) (memq a '(nil t exclusive))))
Richard M. Stallman's avatar
Richard M. Stallman committed
179

180
(defcustom ispell-query-replace-choices nil
181
  "Corrections made throughout region when non-nil.
182 183 184
Uses `query-replace' (\\[query-replace]) for corrections."
  :type 'boolean
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
185

186
(defcustom ispell-skip-tib nil
187
  "Does not spell check `tib' bibliography references when non-nil.
Richard M. Stallman's avatar
Richard M. Stallman committed
188
Skips any text between strings matching regular expressions
Richard M. Stallman's avatar
Richard M. Stallman committed
189
`ispell-tib-ref-beginning' and `ispell-tib-ref-end'.
Richard M. Stallman's avatar
Richard M. Stallman committed
190

Eli Zaretskii's avatar
Eli Zaretskii committed
191 192 193
TeX users beware:  Any text between [. and .] will be skipped -- even if
that's your whole buffer -- unless you set `ispell-skip-tib' to nil.
That includes the [.5mm] type of number..."
194 195
  :type 'boolean
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
196 197 198 199 200 201 202

(defvar ispell-tib-ref-beginning "[[<]\\."
  "Regexp matching the beginning of a Tib reference.")

(defvar ispell-tib-ref-end "\\.[]>]"
  "Regexp matching the end of a Tib reference.")

203
(defcustom ispell-keep-choices-win t
204
  "If non-nil, keep the `*Choices*' window for the entire spelling session.
205 206 207
This minimizes redisplay thrashing."
  :type 'boolean
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
208

209
(defcustom ispell-choices-win-default-height 2
210
  "The default size of the `*Choices*' window, including the mode line.
211
Must be greater than 1."
212 213
  :type 'integer
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
214

215
(defcustom ispell-program-name
216 217 218
  (or (executable-find "aspell")
      (executable-find "ispell")
      (executable-find "hunspell")
219
      "ispell")
220 221
  "Program invoked by \\[ispell-word] and \\[ispell-region] commands."
  :type 'string
222 223 224 225
  :set (lambda (symbol value)
         (set-default symbol value)
         (if (featurep 'ispell)
             (ispell-set-spellchecker-params)))
226
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
227

228
(defcustom ispell-alternate-dictionary
229 230 231 232 233 234
  (cond ((file-readable-p "/usr/dict/web2") "/usr/dict/web2")
	((file-readable-p "/usr/share/dict/web2") "/usr/share/dict/web2")
	((file-readable-p "/usr/dict/words") "/usr/dict/words")
	((file-readable-p "/usr/lib/dict/words") "/usr/lib/dict/words")
	((file-readable-p "/usr/share/dict/words") "/usr/share/dict/words")
	((file-readable-p "/usr/share/lib/dict/words")
235
	 "/usr/share/lib/dict/words")
236
	((file-readable-p "/sys/dict") "/sys/dict"))
237
  "Alternate plain word-list dictionary for spelling help."
238
  :type '(choice file (const :tag "None" nil))
239
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
240

241
(defcustom ispell-complete-word-dict nil
242
  "Plain word-list dictionary used for word completion if
243
different from `ispell-alternate-dictionary'."
244
  :type '(choice file (const :tag "None" nil))
245
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
246

247
(defcustom ispell-message-dictionary-alist nil
248
  "List used by `ispell-message' to select a new dictionary.
249 250 251 252
It consists of pairs (REGEXP . DICTIONARY).  If REGEXP is found
in the message headers, `ispell-local-dictionary' will be set to
DICTIONARY if `ispell-local-dictionary' is not buffer-local.
E.g. you may use the following value:
253
   ((\"^Newsgroups:[ \\t]*de\\\\.\" . \"deutsch8\")
254 255 256
    (\"^To:[^\\n,]+\\\\.de[ \\t\\n,>]\" . \"deutsch8\"))"
  :type '(repeat (cons regexp string))
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
257

258

259
(defcustom ispell-message-fcc-skip 50000
260
  "Query before saving Fcc message copy if attachment larger than this value.
261 262 263 264 265
Always stores Fcc copy of message when nil."
  :type '(choice integer (const :tag "off" nil))
  :group 'ispell)


266
(defcustom ispell-grep-command
Paul Eggert's avatar
Paul Eggert committed
267
  "grep"
268 269 270 271
  "Name of the grep command for search processes."
  :type 'string
  :group 'ispell)

272
(defcustom ispell-grep-options
Paul Eggert's avatar
Paul Eggert committed
273
  "-Ei"
Richard M. Stallman's avatar
Richard M. Stallman committed
274
  "String of options to use when running the program in `ispell-grep-command'.
Paul Eggert's avatar
Paul Eggert committed
275
Should probably be \"-Ei\"."
276 277
  :type 'string
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
278

279 280 281 282 283
(defcustom ispell-look-command
  (cond ((file-exists-p "/bin/look") "/bin/look")
	((file-exists-p "/usr/local/bin/look") "/usr/local/bin/look")
	((file-exists-p "/usr/bin/look") "/usr/bin/look")
	(t "look"))
Richard M. Stallman's avatar
Richard M. Stallman committed
284
  "Name of the look command for search processes.
285 286 287
This must be an absolute file name."
  :type 'file
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
288

289
(defcustom ispell-look-p (file-exists-p ispell-look-command)
290
  "Non-nil means use `look' rather than `grep'.
291 292 293
Default is based on whether `look' seems to be available."
  :type 'boolean
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
294

295
(defcustom ispell-have-new-look nil
296
  "Non-nil means use the `-r' option (regexp) when running `look'."
297 298
  :type 'boolean
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
299

300 301 302 303
(defcustom ispell-look-options (if ispell-have-new-look "-dfr" "-df")
  "String of command options for `ispell-look-command'."
  :type 'string
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
304

305
(defcustom ispell-use-ptys-p nil
Richard M. Stallman's avatar
Richard M. Stallman committed
306
  "When non-nil, Emacs uses ptys to communicate with Ispell.
307 308 309
When nil, Emacs uses pipes."
  :type 'boolean
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
310

311
(defcustom ispell-following-word nil
312
  "Non-nil means `ispell-word' checks the word around or after point.
313 314 315
Otherwise `ispell-word' checks the preceding word."
  :type 'boolean
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
316

317
(defcustom ispell-help-in-bufferp nil
318
  "Non-nil means display interactive keymap help in a buffer.
319
The following values are supported:
320 321 322 323
  nil        Expand the minibuffer and display a short help message
             there for a couple of seconds.
  t          Pop up a new buffer and display a short help message there
             for a couple of seconds.
324
  electric   Pop up a new buffer and display a long help message there.
325
             User can browse and then exit the help mode."
326
  :type '(choice (const electric) (const :tag "off" nil) (const :tag "on" t))
327
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
328

329
(defcustom ispell-quietly nil
330
  "Non-nil means suppress messages in `ispell-word'."
331 332
  :type 'boolean
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
333

334
(defcustom ispell-format-word-function (function upcase)
335
  "Formatting function for displaying word being spell checked.
336 337 338
The function must take one string argument and return a string."
  :type 'function
  :group 'ispell)
339
(defvaralias 'ispell-format-word 'ispell-format-word-function)
Richard M. Stallman's avatar
Richard M. Stallman committed
340

341 342 343 344
(defcustom ispell-use-framepop-p nil
  "When non-nil ispell uses framepop to display choices in a dedicated frame.
You can set this variable to dynamically use framepop if you are in a
window system by evaluating the following on startup to set this variable:
345
  (and window-system (condition-case () (require \\='framepop) (error nil)))"
346 347 348
  :type 'boolean
  :group 'ispell)

349
;;;###autoload
350
(defcustom ispell-personal-dictionary nil
351
  "File name of your personal spelling dictionary, or nil.
352
If nil, the default personal dictionary for your spelling checker is used."
353 354
  :type '(choice file
		 (const :tag "default" nil))
355
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
356

357
(defcustom ispell-silently-savep nil
358
  "When non-nil, save personal dictionary without asking for confirmation."
359 360
  :type 'boolean
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
361

362 363
(defvar ispell-local-dictionary-overridden nil
  "Non-nil means the user has explicitly set this buffer's Ispell dictionary.")
364
(make-variable-buffer-local 'ispell-local-dictionary-overridden)
365

366
(defcustom ispell-local-dictionary nil
367 368 369 370
  "If non-nil, the dictionary to be used for Ispell commands in this buffer.
The value must be a string dictionary name,
or nil, which means use the global setting in `ispell-dictionary'.
Dictionary names are defined in `ispell-local-dictionary-alist'
371
and `ispell-dictionary-alist'.
372

373
Setting `ispell-local-dictionary' to a value has the same effect as
374 375
calling \\[ispell-change-dictionary] with that value.  This variable
is automatically set when defined in the file with either
376
`ispell-dictionary-keyword' or the Local Variable syntax."
377 378 379
  :type '(choice string
		 (const :tag "default" nil))
  :group 'ispell)
380 381
;;;###autoload
(put 'ispell-local-dictionary 'safe-local-variable 'string-or-null-p)
382 383 384

(make-variable-buffer-local 'ispell-local-dictionary)

385 386 387 388 389 390
(defcustom ispell-dictionary nil
  "Default dictionary to use if `ispell-local-dictionary' is nil."
  :type '(choice string
		 (const :tag "default" nil))
  :group 'ispell)

391
(defcustom ispell-extra-args nil
392
  "If non-nil, a list of extra switches to pass to the Ispell program.
393
For example, (\"-W\" \"3\") to cause it to accept all 1-3 character
Richard M. Stallman's avatar
Richard M. Stallman committed
394
words as correct.  See also `ispell-dictionary-alist', which may be used
395 396 397
for language-specific arguments."
  :type '(repeat string)
  :group 'ispell)
Richard M. Stallman's avatar
Richard M. Stallman committed
398

399

400

401
(defcustom ispell-skip-html 'use-mode-name
402
  "Indicates whether ispell should skip spell checking of SGML markup.
403 404 405 406 407 408 409
If t, always skip SGML markup; if nil, never skip; if non-t and non-nil,
guess whether SGML markup should be skipped according to the name of the
buffer's major mode."
  :type '(choice (const :tag "always" t) (const :tag "never" nil)
		 (const :tag "use-mode-name" use-mode-name))
  :group 'ispell)

410 411
(make-variable-buffer-local 'ispell-skip-html)

412

413
(defcustom ispell-local-dictionary-alist nil
414
  "List of local or customized dictionary definitions.
415
These can override the values in `ispell-dictionary-alist'.
416

417 418
To make permanent changes to your dictionary definitions, you
will need to make your changes in this variable, save, and then
419
re-start Emacs."
420 421 422 423 424 425 426 427 428 429 430 431
  :type '(repeat (list (choice :tag "Dictionary"
			       (string :tag "Dictionary name")
			       (const :tag "default" nil))
		       (regexp :tag "Case characters")
		       (regexp :tag "Non case characters")
		       (regexp :tag "Other characters")
		       (boolean :tag "Many other characters")
		       (repeat :tag "Ispell command line args"
			       (string :tag "Arg"))
		       (choice :tag "Extended character mode"
			       (const "~tex") (const "~plaintex")
			       (const "~nroff") (const "~list")
432
			       (const "~latin1") (const "~latin3")
433
 			       (const :tag "default" nil))
434
		       (coding-system :tag "Coding System")))
435 436 437
  :group 'ispell)


Stefan Monnier's avatar
Stefan Monnier committed
438
(defvar ispell-dictionary-base-alist
439
  '((nil                                ; default
440 441 442
     ;; The default dictionary.  It may be English.aff, or any other
     ;; dictionary depending on locale and such things.  We should probably
     ;; ask ispell what dictionary it's using, but until we do that, let's
443 444
     ;; just use a minimal regexp. [:alpha:] will later be set if possible.
     "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil iso-8859-1)
Stefan Monnier's avatar
Stefan Monnier committed
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
    ("american"				; Yankee English
     "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil iso-8859-1)
    ("brasileiro"			; Brazilian mode
     "[A-Z\301\311\315\323\332\300\310\314\322\331\303\325\307\334\302\312\324a-z\341\351\355\363\372\340\350\354\362\371\343\365\347\374\342\352\364]"
     "[^A-Z\301\311\315\323\332\300\310\314\322\331\303\325\307\334\302\312\324a-z\341\351\355\363\372\340\350\354\362\371\343\365\347\374\342\352\364]"
     "[']" nil nil nil iso-8859-1)
    ("british"				; British version
     "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil iso-8859-1)
    ("castellano"			; Spanish mode
     "[A-Z\301\311\315\321\323\332\334a-z\341\351\355\361\363\372\374]"
     "[^A-Z\301\311\315\321\323\332\334a-z\341\351\355\361\363\372\374]"
     "[-]" nil ("-B") "~tex" iso-8859-1)
    ("castellano8"			; 8 bit Spanish mode
     "[A-Z\301\311\315\321\323\332\334a-z\341\351\355\361\363\372\374]"
     "[^A-Z\301\311\315\321\323\332\334a-z\341\351\355\361\363\372\374]"
     "[-]" nil ("-B" "-d" "castellano") "~latin1" iso-8859-1)
    ("czech"
     "[A-Za-z\301\311\314\315\323\332\331\335\256\251\310\330\317\253\322\341\351\354\355\363\372\371\375\276\271\350\370\357\273\362]"
     "[^A-Za-z\301\311\314\315\323\332\331\335\256\251\310\330\317\253\322\341\351\354\355\363\372\371\375\276\271\350\370\357\273\362]"
     "" nil ("-B") nil iso-8859-2)
    ("dansk"				; Dansk.aff
     "[A-Z\306\330\305a-z\346\370\345]" "[^A-Z\306\330\305a-z\346\370\345]"
     "[']" nil ("-C") nil iso-8859-1)
    ("deutsch"				; Deutsch.aff
     "[a-zA-Z\"]" "[^a-zA-Z\"]" "[']" t ("-C") "~tex" iso-8859-1)
    ("deutsch8"
     "[a-zA-Z\304\326\334\344\366\337\374]"
     "[^a-zA-Z\304\326\334\344\366\337\374]"
     "[']" t ("-C" "-d" "deutsch") "~latin1" iso-8859-1)
    ("english"				; make English explicitly selectable
     "[A-Za-z]" "[^A-Za-z]" "[']" nil ("-B") nil iso-8859-1)
    ("esperanto"
     "[A-Za-z\246\254\266\274\306\330\335\336\346\370\375\376]"
     "[^A-Za-z\246\254\266\274\306\330\335\336\346\370\375\376]"
     "[-']" t ("-C") "~latin3" iso-8859-3)
    ("esperanto-tex"
     "[A-Za-z^\\]" "[^A-Za-z^\\]"
     "[-'`\"]" t ("-C" "-d" "esperanto") "~tex" iso-8859-3)
483 484 485 486
    ("finnish"
     "[A-Za-z\345\344\366\305\304\326]"
     "[^A-Za-z\345\344\366\305\304\326]"
     "[:]" nil ("-C") "~list" iso-8859-1)
Stefan Monnier's avatar
Stefan Monnier committed
487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
    ("francais7"
     "[A-Za-z]" "[^A-Za-z]" "[`'^-]" t nil nil iso-8859-1)
    ("francais"				; Francais.aff
     "[A-Za-z\300\302\306\307\310\311\312\313\316\317\324\331\333\334\340\342\347\350\351\352\353\356\357\364\371\373\374]"
     "[^A-Za-z\300\302\306\307\310\311\312\313\316\317\324\331\333\334\340\342\347\350\351\352\353\356\357\364\371\373\374]"
     "[-'.@]" t nil "~list" iso-8859-1)
    ("francais-tex"			; Francais.aff
     "[A-Za-z\300\302\306\307\310\311\312\313\316\317\324\331\333\334\340\342\347\350\351\352\353\356\357\364\371\373\374\\]"
     "[^A-Za-z\300\302\306\307\310\311\312\313\316\317\324\331\333\334\340\342\347\350\351\352\353\356\357\364\371\373\374\\]"
     "[-'^`\".@]" t nil "~tex" iso-8859-1)
    ("german"				; german.aff
     "[a-zA-Z\"]" "[^a-zA-Z\"]" "[']" t ("-C") "~tex" iso-8859-1)
    ("german8"				; german.aff
     "[a-zA-Z\304\326\334\344\366\337\374]"
     "[^a-zA-Z\304\326\334\344\366\337\374]"
     "[']" t ("-C" "-d" "german") "~latin1" iso-8859-1)
    ("italiano"				; Italian.aff
     "[A-Z\300\301\310\311\314\315\322\323\331\332a-z\340\341\350\351\354\355\363\371\372]"
     "[^A-Z\300\301\310\311\314\315\322\323\331\332a-z\340\341\350\351\354\355\363\371\372]"
     "[-.]" nil ("-B" "-d" "italian") "~tex" iso-8859-1)
    ("nederlands"			; Nederlands.aff
     "[A-Za-z\300\301\302\303\304\305\307\310\311\312\313\314\315\316\317\322\323\324\325\326\331\332\333\334\340\341\342\343\344\345\347\350\351\352\353\354\355\356\357\361\362\363\364\365\366\371\372\373\374]"
     "[^A-Za-z\300\301\302\303\304\305\307\310\311\312\313\314\315\316\317\322\323\324\325\326\331\332\333\334\340\341\342\343\344\345\347\350\351\352\353\354\355\356\357\361\362\363\364\365\366\371\372\373\374]"
     "[']" t ("-C") nil iso-8859-1)
    ("nederlands8"			; Dutch8.aff
     "[A-Za-z\300\301\302\303\304\305\307\310\311\312\313\314\315\316\317\322\323\324\325\326\331\332\333\334\340\341\342\343\344\345\347\350\351\352\353\354\355\356\357\361\362\363\364\365\366\371\372\373\374]"
     "[^A-Za-z\300\301\302\303\304\305\307\310\311\312\313\314\315\316\317\322\323\324\325\326\331\332\333\334\340\341\342\343\344\345\347\350\351\352\353\354\355\356\357\361\362\363\364\365\366\371\372\373\374]"
     "[']" t ("-C") nil iso-8859-1)
    ("norsk"				; 8 bit Norwegian mode
     "[A-Za-z\305\306\307\310\311\322\324\330\345\346\347\350\351\362\364\370]"
     "[^A-Za-z\305\306\307\310\311\322\324\330\345\346\347\350\351\362\364\370]"
     "[\"]" nil nil "~list" iso-8859-1)
    ("norsk7-tex"			; 7 bit Norwegian TeX mode
     "[A-Za-z{}\\'^`]" "[^A-Za-z{}\\'^`]"
     "[\"]" nil ("-d" "norsk") "~plaintex" iso-8859-1)
    ("polish"				; Polish mode
     "[A-Za-z\241\243\246\254\257\261\263\266\274\277\306\312\321\323\346\352\361\363]"
     "[^A-Za-z\241\243\246\254\257\261\263\266\274\277\306\312\321\323\346\352\361\363]"
     "[.]" nil nil nil iso-8859-2)
    ("portugues"                        ; Portuguese mode
527 528
     "[a-zA-Z\301\302\307\311\323\340\341\342\351\352\355\363\343\347\372]"
     "[^a-zA-Z\301\302\307\311\323\340\341\342\351\352\355\363\343\347\372]"
Stefan Monnier's avatar
Stefan Monnier committed
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
     "[']" t ("-C") "~latin1" iso-8859-1)
    ("russian"				; Russian.aff (KOI8-R charset)
     "[\341\342\367\347\344\345\263\366\372\351\352\353\354\355\356\357\360\362\363\364\365\346\350\343\376\373\375\370\371\377\374\340\361\301\302\327\307\304\305\243\326\332\311\312\313\314\315\316\317\320\322\323\324\325\306\310\303\336\333\335\330\331\337\334\300\321]"
     "[^\341\342\367\347\344\345\263\366\372\351\352\353\354\355\356\357\360\362\363\364\365\346\350\343\376\373\375\370\371\377\374\340\361\301\302\327\307\304\305\243\326\332\311\312\313\314\315\316\317\320\322\323\324\325\306\310\303\336\333\335\330\331\337\334\300\321]"
     "" nil nil nil koi8-r)
    ("russianw"				; russianw.aff (CP1251 charset)
     "[\300\301\302\303\304\305\250\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\334\333\332\335\336\337\340\341\342\343\344\345\270\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\374\373\372\375\376\377]"
     "[^\300\301\302\303\304\305\250\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\334\333\332\335\336\337\340\341\342\343\344\345\270\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\374\373\372\375\376\377]"
     "" nil nil nil windows-1251)
    ("slovak"				; Slovakian
     "[A-Za-z\301\304\311\315\323\332\324\300\305\245\335\256\251\310\317\253\322\341\344\351\355\363\372\364\340\345\265\375\276\271\350\357\273\362]"
     "[^A-Za-z\301\304\311\315\323\332\324\300\305\245\335\256\251\310\317\253\322\341\344\351\355\363\372\364\340\345\265\375\276\271\350\357\273\362]"
     "" nil ("-B") nil iso-8859-2)
    ("slovenian"                        ; Slovenian
     "[A-Za-z\301\304\311\315\323\332\324\300\305\245\335\256\251\310\317\253\322\341\344\351\355\363\372\364\340\345\265\375\276\271\350\357\273\362]"
     "[^A-Za-z\301\304\311\315\323\332\324\300\305\245\335\256\251\310\317\253\322\341\344\351\355\363\372\364\340\345\265\375\276\271\350\357\273\362]"
     "" nil ("-B" "-d" "slovenian") nil iso-8859-2)
    ("svenska"				; Swedish mode
     "[A-Za-z\345\344\366\351\340\374\350\346\370\347\305\304\326\311\300\334\310\306\330\307]"
     "[^A-Za-z\345\344\366\351\340\374\350\346\370\347\305\304\326\311\300\334\310\306\330\307]"
549 550
     "[']" nil ("-C") "~list" iso-8859-1)
    ("hebrew" "[\340\341\342\343\344\345\346\347\350\351\353\352\354\356\355\360\357\361\362\364\363\367\366\365\370\371\372]" "[^\340\341\342\343\344\345\346\347\350\351\353\352\354\356\355\360\357\361\362\364\363\367\366\365\370\371\372]" "" nil ("-B") nil cp1255))
Stefan Monnier's avatar
Stefan Monnier committed
551 552 553
  "Base value for `ispell-dictionary-alist'.")

(defvar ispell-dictionary-alist nil
Richard M. Stallman's avatar
Richard M. Stallman committed
554 555 556 557
  "An alist of dictionaries and their associated parameters.

Each element of this list is also a list:

558 559
 (DICTIONARY-NAME CASECHARS NOT-CASECHARS OTHERCHARS MANY-OTHERCHARS-P
        ISPELL-ARGS EXTENDED-CHARACTER-MODE CHARACTER-SET)
Richard M. Stallman's avatar
Richard M. Stallman committed
560

561 562
DICTIONARY-NAME is a possible string value of variable `ispell-dictionary',
nil means the default dictionary.
Richard M. Stallman's avatar
Richard M. Stallman committed
563

564
CASECHARS is a regular expression of valid characters that comprise a word.
Richard M. Stallman's avatar
Richard M. Stallman committed
565 566 567

NOT-CASECHARS is the opposite regexp of CASECHARS.

568 569 570
OTHERCHARS is a regexp of characters in the NOT-CASECHARS set but which can be
used to construct words in some special way.  If OTHERCHARS characters follow
and precede characters from CASECHARS, they are parsed as part of a word,
571
otherwise they become word-breaks.  As an example in English, assume the
572
regular expression \"[']\" for OTHERCHARS.  Then \"they're\" and
573 574
\"Steven's\" are parsed as single words including the \"'\" character, but
\"Stevens'\" does not include the quote character as part of the word.
575
If you want OTHERCHARS to be empty, use the empty string.
Richard M. Stallman's avatar
Richard M. Stallman committed
576 577
Hint: regexp syntax requires the hyphen to be declared first here.

578
CASECHARS, NOT-CASECHARS, and OTHERCHARS must be unibyte strings
579
containing bytes of CHARACTER-SET.  In addition, if they contain
Eli Zaretskii's avatar
Eli Zaretskii committed
580
non-ASCII bytes, the regular expression must be a single
581 582 583
`character set' construct that doesn't specify a character range
for non-ASCII bytes.

584 585 586
MANY-OTHERCHARS-P is non-nil when multiple OTHERCHARS are allowed in a word.
Otherwise only a single OTHERCHARS character is allowed to be part of any
single word.
Richard M. Stallman's avatar
Richard M. Stallman committed
587 588 589 590 591

ISPELL-ARGS is a list of additional arguments passed to the ispell
subprocess.

EXTENDED-CHARACTER-MODE should be used when dictionaries are used which
592
have been configured in an Ispell affix file.  (For example, umlauts
Richard M. Stallman's avatar
Richard M. Stallman committed
593
can be encoded as \\\"a, a\\\", \"a, ...)  Defaults are ~tex and ~nroff
Richard M. Stallman's avatar
Richard M. Stallman committed
594 595
in English.  This has the same effect as the command-line `-T' option.
The buffer Major Mode controls Ispell's parsing in tex or nroff mode,
Richard M. Stallman's avatar
Richard M. Stallman committed
596
but the dictionary can control the extended character mode.
Juanma Barranquero's avatar
Juanma Barranquero committed
597
Both defaults can be overruled in a buffer-local fashion.  See
Richard M. Stallman's avatar
Richard M. Stallman committed
598
`ispell-parsing-keyword' for details on this.
Richard M. Stallman's avatar
Richard M. Stallman committed
599

Eli Zaretskii's avatar
Eli Zaretskii committed
600 601
CHARACTER-SET used to encode text sent to the ispell subprocess
when the language uses non-ASCII characters.
602

Eli Zaretskii's avatar
Eli Zaretskii committed
603 604 605
Note that with \"ispell\" as the speller, the CASECHARS and
OTHERCHARS slots of the alist should contain the same character
set as casechars and otherchars in the LANGUAGE.aff file \(e.g.,
606
english.aff).  Aspell and Hunspell don't have this limitation.")
607

608
(defvar ispell-really-aspell nil
609
  "Non-nil if we can use Aspell extensions.")
610
(defvar ispell-really-hunspell nil
611
  "Non-nil if we can use Hunspell extensions.")
612
(defvar ispell-encoding8-command nil
Eli Zaretskii's avatar
Eli Zaretskii committed
613 614
  "Command line option prefix to select encoding if supported, nil otherwise.
If setting the encoding is supported by spellchecker and is selectable from
615 616 617 618
the command line, this variable will contain \"--encoding=\" for Aspell
and \"-i \" for Hunspell, so the appropriate mime charset can be selected.
That will be set in `ispell-check-version' for Hunspell >= 1.1.6 and
Aspell >= 0.60.
Eli Zaretskii's avatar
Eli Zaretskii committed
619

620
For Aspell, non-nil also means to try to automatically find its dictionaries.
Eli Zaretskii's avatar
Eli Zaretskii committed
621

622
Earlier Aspell versions do not consistently support charset encoding.  Handling
623
this would require some extra guessing in `ispell-aspell-find-dictionary'.")
624

625
(defvar ispell-aspell-supports-utf8 nil
626
  "Non-nil if Aspell has consistent command line UTF-8 support.  Obsolete.
627
ispell.el and flyspell.el will use for this purpose the more generic
628
variable `ispell-encoding8-command' for both Aspell and Hunspell.  Is left
629 630 631 632
here just for backwards compatibility.")

(make-obsolete-variable 'ispell-aspell-supports-utf8
                        'ispell-encoding8-command "23.1")
633

634
(defvar ispell-dicts-name2locale-equivs-alist
635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665
  '(("american"      "en_US")
    ("brasileiro"    "pt_BR")
    ("british"       "en_GB")
    ("castellano"    "es_ES")
    ("castellano8"   "es_ES")
    ("czech"         "cs_CZ")
    ("dansk"         "da_DK")
    ("deutsch"       "de_DE")
    ("deutsch8"      "de_DE")
    ("english"       "en_US")
    ("esperanto"     "eo")
    ("esperanto-tex" "eo")
    ("finnish"       "fi_FI")
    ("francais7"     "fr_FR")
    ("francais"      "fr_FR")
    ("francais-tex"  "fr_FR")
    ("german"        "de_DE")
    ("german8"       "de_DE")
    ("italiano"      "it_IT")
    ("nederlands"    "nl_NL")
    ("nederlands8"   "nl_NL")
    ("norsk"         "nn_NO")
    ("norsk7-tex"    "nn_NO")
    ("polish"        "pl_PL")
    ("portugues"     "pt_PT")
    ("russian"       "ru_RU")
    ("russianw"      "ru_RU")
    ("slovak"        "sk_SK")
    ("slovenian"     "sl_SI")
    ("svenska"       "sv_SE")
    ("hebrew"        "he_IL"))
666
  "Alist with known matching locales for standard dict names in
667 668
  `ispell-dictionary-base-alist'.")

669 670 671 672 673

;;; **********************************************************************
;;; The following are used by ispell, and should not be changed.
;;; **********************************************************************

Richard M. Stallman's avatar
Richard M. Stallman committed
674

675

676 677
;; The version must be 3.1 or greater for this version of ispell.el
;; There is an incompatibility between version 3.1.12 and lower versions.
678 679 680 681 682
(defconst ispell-required-version '(3 1 12)
  "Ispell versions with which this version of ispell.el is known to work.")
(defvar ispell-offset -1
  "Offset that maps protocol differences between ispell 3.1 versions.")

683
(defconst ispell-version "ispell.el 3.6 - 7-Jan-2003")
684 685


686
(defun ispell-check-version (&optional interactivep)
Eli Zaretskii's avatar
Eli Zaretskii committed
687
  "Ensure that `ispell-program-name' is valid and has the correct version.
688
Returns version number if called interactively.
689
Otherwise returns the library directory name, if that is defined."
690 691 692 693 694 695 696 697
  ;; This is a little wasteful as we actually launch ispell twice: once
  ;; to make sure it's the right version, and once for real.  But people
  ;; get confused by version mismatches *all* the time (and I've got the
  ;; email to prove it) so I think this is worthwhile.  And the -v[ersion]
  ;; option is the only way I can think of to do this that works with
  ;; all versions, since versions earlier than 3.0.09 didn't identify
  ;; themselves on startup.
  (interactive "p")
698
  (let ((default-directory (or (and (boundp 'temporary-file-directory)
699 700
				    temporary-file-directory)
			       default-directory))
701 702 703 704 705 706
	(get-config-var
	 (lambda (var)
	   (when (re-search-forward
		  (concat var " = \\\"\\(.+?\\)\\\"") nil t)
	     (match-string 1))))
	result libvar status ispell-program-version)
707 708

    (with-temp-buffer
709
      (setq status (ispell-call-process
Eli Zaretskii's avatar
Eli Zaretskii committed
710 711 712 713 714 715 716 717
		    ispell-program-name nil t nil
		    ;; aspell doesn't accept the -vv switch.
		    (let ((case-fold-search
			   (memq system-type '(ms-dos windows-nt)))
			  (speller
			   (file-name-nondirectory ispell-program-name)))
		      ;; Assume anything that isn't `aspell' is Ispell.
		      (if (string-match "\\`aspell" speller) "-v" "-vv"))))
718 719
      (goto-char (point-min))
      (if interactivep
720
	  ;; Report version information of ispell and ispell.el
721 722 723 724 725 726
	  (progn
	    (end-of-line)
	    (setq result (concat (buffer-substring-no-properties (point-min)
								 (point))
				 ", "
				 ispell-version))
Deepak Goel's avatar
Deepak Goel committed
727
	    (message "%s" result))
728 729 730 731 732 733 734
	;; return LIBDIR or LIBRARYVAR (overrides LIBDIR) env.
	(progn
	  (setq result (funcall get-config-var "LIBDIR")
		libvar (funcall get-config-var "LIBRARYVAR"))
	  (when libvar
	    (setq libvar (getenv libvar))
	    (unless (member libvar '(nil "")) (setq result libvar)))))
735 736 737 738
      (goto-char (point-min))
      (if (not (memq status '(0 nil)))
	  (error "%s exited with %s %s" ispell-program-name
		 (if (stringp status) "signal" "code") status))
739 740 741 742 743 744 745 746 747 748

      ;; Get relevant version strings. Only xx.yy.... format works well
      (let (case-fold-search)
	(setq ispell-program-version
	      (and (search-forward-regexp "\\([0-9]+\\.[0-9\\.]+\\)" nil t)
		   (match-string 1)))

	;; Make sure these variables are (re-)initialized to the default value
	(setq ispell-really-aspell nil
	      ispell-aspell-supports-utf8 nil
749 750
	      ispell-really-hunspell nil
	      ispell-encoding8-command nil)
751 752 753 754

	(goto-char (point-min))
	(or (setq ispell-really-aspell
		  (and (search-forward-regexp
755
			"(but really Aspell \\([0-9]+\\.[0-9\\.-]+\\)?)" nil t)
756 757 758
		       (match-string 1)))
	    (setq ispell-really-hunspell
		  (and (search-forward-regexp
759 760
			"(but really Hunspell \\([0-9]+\\.[0-9\\.-]+\\)?)"
                        nil t)
761 762 763 764 765 766 767 768
		       (match-string 1)))))

      (let ((aspell-minver    "0.50")
	    (aspell8-minver   "0.60")
	    (ispell0-minver   "3.1.0")
	    (ispell-minver    "3.1.12")
	    (hunspell8-minver "1.1.6"))

769 770
	(if (version<= ispell0-minver ispell-program-version)
	    (or (version<= ispell-minver ispell-program-version)
771 772 773 774 775 776 777
		(setq ispell-offset 0))
	  (error "%s release %s or greater is required"
		 ispell-program-name
		 ispell-minver))

	(cond
	 (ispell-really-aspell
778 779
	  (if (version<= aspell-minver ispell-really-aspell)
	      (if (version<= aspell8-minver ispell-really-aspell)
780 781 782
		  (progn
		    (setq ispell-aspell-supports-utf8 t)
		    (setq ispell-encoding8-command "--encoding=")))
783 784
	    (setq ispell-really-aspell nil)))
	 (ispell-really-hunspell
785
	  (if (version<= hunspell8-minver ispell-really-hunspell)
786
	      (setq ispell-encoding8-command "-i")
787
	    (setq ispell-really-hunspell nil))))))
788 789
    result))

790 791 792
(defun ispell-call-process (&rest args)
  "Like `call-process' but defend against bad `default-directory'."
  (let ((default-directory default-directory))
793
    (unless (file-accessible-directory-p default-directory)
794 795 796 797 798 799
      (setq default-directory (expand-file-name "~/")))
    (apply 'call-process args)))

(defun ispell-call-process-region (&rest args)
  "Like `call-process-region' but defend against bad `default-directory'."
  (let ((default-directory default-directory))
800
    (unless (file-accessible-directory-p default-directory)
801 802 803
      (setq default-directory (expand-file-name "~/")))
    (apply 'call-process-region args)))

804 805
(defvar ispell-debug-buffer)

806 807
(defun ispell-create-debug-buffer (&optional append)
  "Create an ispell debug buffer for debugging output.
808
If APPEND is non-nil, append the info to previous buffer if exists,
809 810 811 812 813 814 815 816 817 818
otherwise is reset.  Returns name of ispell debug buffer.
See `ispell-buffer-with-debug' for an example of use."
  (let ((ispell-debug-buffer (get-buffer-create "*ispell-debug*")))
    (with-current-buffer ispell-debug-buffer
      (if append
	  (insert
	   (format "-----------------------------------------------\n"))
	(erase-buffer)))
    ispell-debug-buffer))

819
(defsubst ispell-print-if-debug (format &rest args)
820
  "Print message using FORMAT and ARGS to `ispell-debug-buffer' buffer if enabled."
821 822
  (if (boundp 'ispell-debug-buffer)
      (with-current-buffer ispell-debug-buffer
823 824
	(goto-char (point-max))
	(insert (apply #'format format args)))))
825

826

827 828 829
;; The preparation of the menu bar menu must be autoloaded
;; because otherwise this file gets autoloaded every time Emacs starts
;; so that it can set up the menus and determine keyboard equivalents.
830

831
;;;###autoload
832
(defvar ispell-menu-map nil "Key map for ispell menu.")
833
;; Redo menu when loading ispell to get dictionary modifications
Karl Heuer's avatar
Karl Heuer committed
834
(setq ispell-menu-map nil)
Richard M. Stallman's avatar
Richard M. Stallman committed
835

836
;;; Set up dictionary
837
;;;###autoload
838
(defvar ispell-menu-map-needed
839
  (unless ispell-menu-map 'reload))
840

841
(defvar ispell-library-directory (condition-case ()
842
				     (ispell-check-version)
843 844
				   (error nil))
  "Directory where ispell dictionaries reside.")
845

846 847 848
(defvar ispell-process nil
  "The process object for Ispell.")

849
(defvar ispell-async-processp (and (fboundp 'delete-process)
850
				   (fboundp 'process-send-string)
Reuben Thomas's avatar
Reuben Thomas committed
851
				   (fboundp 'accept-process-output))
852
  "Non-nil means that the OS supports asynchronous processes.")
853

854 855
;; Make ispell.el work better with aspell.

856
(defvar ispell-aspell-dictionary-alist nil
857
  "An alist of parsed Aspell dicts and associated parameters.
858
Internal use.")
859

860 861
(defun ispell-find-aspell-dictionaries ()
  "Find Aspell's dictionaries, and record in `ispell-dictionary-alist'."
862
  (unless (and ispell-really-aspell ispell-encoding8-command)
863
    (error "This function only works with Aspell >= 0.60"))
864 865 866
  (let* ((dictionaries
	  (split-string
	   (with-temp-buffer
867
	     (ispell-call-process ispell-program-name nil t nil "dicts")
868 869 870
	     (buffer-string))))
	 ;; Search for the named dictionaries.
	 (found
871
	  (delq nil
872
		(mapcar #'ispell-aspell-find-dictionary dictionaries))))
873 874 875
    ;; Ensure aspell's alias dictionary will override standard
    ;; definitions.
    (setq found (ispell-aspell-add-aliases found))
876
    ;; Merge into FOUND any elements from the standard ispell-dictionary-base-alist
877
    ;; which have no element in FOUND at all.
878
    (dolist (dict ispell-dictionary-base-alist)
879