Function: ispell-find-hunspell-dictionaries
ispell-find-hunspell-dictionaries is a byte-compiled function defined
in ispell.el.gz.
Signature
(ispell-find-hunspell-dictionaries &optional DICTIONARY)
Documentation
Look for installed Hunspell dictionaries.
Will initialize ispell-hunspell-dictionary-alist according
to dictionaries found, and will remove aliases from the list
in ispell-dicts-name2locale-equivs-alist if an explicit
dictionary from that list was found.
If DICTIONARY, check for that dictionary explicitly.
Source Code
;; Defined in /usr/src/emacs/lisp/textmodes/ispell.el.gz
(defun ispell-find-hunspell-dictionaries (&optional dictionary)
"Look for installed Hunspell dictionaries.
Will initialize `ispell-hunspell-dictionary-alist' according
to dictionaries found, and will remove aliases from the list
in `ispell-dicts-name2locale-equivs-alist' if an explicit
dictionary from that list was found.
If DICTIONARY, check for that dictionary explicitly."
(let ((hunspell-found-dicts
(seq-filter
(lambda (str)
(when (string-match
;; Hunspell gives this error when there is some
;; installation problem, for example if $LANG is unset.
(concat "^Can't open affix or dictionary files "
"for dictionary named \"default\".$")
str)
(user-error "Hunspell error (is $LANG unset?): %s" str))
(file-name-absolute-p str))
(split-string
(with-temp-buffer
(apply #'ispell-call-process
ispell-program-name nil t nil
`("-D"
,@(and dictionary (list "-d" dictionary))
;; Use -a to prevent Hunspell from trying to
;; initialize its curses/termcap UI, which
;; causes it to crash or fail to start in some
;; MS-Windows ports.
"-a"
;; Hunspell 1.7.0 (and later?) won't show LOADED
;; DICTIONARY unless there's at least one file
;; argument on the command line. So we feed it
;; with the null device.
,null-device))
(buffer-string))
"[\n\r]+"
t)))
hunspell-default-dict
hunspell-default-dict-entry
hunspell-multi-dict)
(dolist (dict hunspell-found-dicts)
(let* ((full-name (file-name-nondirectory dict))
(basename (file-name-sans-extension full-name))
(affix-file (concat dict ".aff")))
(if (string-match "\\.aff$" dict)
;; Found default dictionary
(progn
(if hunspell-default-dict
(setq hunspell-multi-dict
(concat (or hunspell-multi-dict
(car hunspell-default-dict))
"," basename))
(setq affix-file dict)
;; FIXME: The cdr of the list we cons below is never
;; used. Why do we need a list?
(setq hunspell-default-dict (list basename affix-file)))
(ispell-print-if-debug
"++ ispell-fhd: default dict-entry:%s name:%s basename:%s\n"
dict full-name basename))
(if (and (not (assoc basename ispell-hunspell-dict-paths-alist))
(file-exists-p affix-file))
;; Entry has an associated .aff file and no previous value.
(let ((affix-file (expand-file-name affix-file)))
(ispell-print-if-debug
"++ ispell-fhd: dict-entry:%s name:%s basename:%s affix-file:%s\n"
dict full-name basename affix-file)
(cl-pushnew (list basename affix-file)
ispell-hunspell-dict-paths-alist :test #'equal))
(ispell-print-if-debug
"-- ispell-fhd: Skipping entry: %s\n" dict)))))
;; Remove entry from aliases alist if explicit dict was found.
(let (newlist)
(dolist (dict ispell-dicts-name2locale-equivs-alist)
(if (assoc (car dict) ispell-hunspell-dict-paths-alist)
(ispell-print-if-debug
"-- ispell-fhd: Excluding %s alias. Standalone dict found.\n"
(car dict))
(cl-pushnew dict newlist :test #'equal)))
(setq ispell-dicts-name2locale-equivs-alist newlist))
;; Add known hunspell aliases
(dolist (dict-equiv ispell-dicts-name2locale-equivs-alist)
(let ((dict-equiv-key (car dict-equiv))
(dict-equiv-value (cadr dict-equiv))
(exclude-aliases (list ;; Exclude TeX aliases
"esperanto-tex"
"francais7"
"francais-tex"
"norsk7-tex")))
(if (and (assoc dict-equiv-value ispell-hunspell-dict-paths-alist)
(not (assoc dict-equiv-key ispell-hunspell-dict-paths-alist))
(not (member dict-equiv-key exclude-aliases)))
(let ((affix-file (cadr (assoc dict-equiv-value
ispell-hunspell-dict-paths-alist))))
(ispell-print-if-debug "++ ispell-fhd: Adding alias %s -> %s.\n"
dict-equiv-key affix-file)
(cl-pushnew (list dict-equiv-key affix-file)
ispell-hunspell-dict-paths-alist :test #'equal)))))
;; Parse and set values for default dictionary.
(setq hunspell-default-dict (or hunspell-multi-dict
(car hunspell-default-dict)))
;; If we didn't find a dictionary based on the environment (i.e.,
;; the locale and the DICTIONARY variable), try again if
;; `ispell-dictionary' is set.
(when (and (not hunspell-default-dict)
(not dictionary)
ispell-dictionary)
(setq hunspell-default-dict
(ispell-find-hunspell-dictionaries ispell-dictionary)))
;; If hunspell-default-dict is nil, ispell-parse-hunspell-affix-file
;; will barf with an error message that doesn't help users figure
;; out what is wrong. Produce an error message that points to the
;; root cause of the problem.
(unless hunspell-default-dict
(error "Can't find Hunspell dictionary with a .aff affix file"))
(setq hunspell-default-dict-entry
(ispell-parse-hunspell-affix-file hunspell-default-dict))
;; Create an alist of found dicts with only names, except for default dict.
(setq ispell-hunspell-dictionary-alist
(list (cons nil (cdr hunspell-default-dict-entry))))
(dolist (dict (mapcar #'car ispell-hunspell-dict-paths-alist))
(cl-pushnew (if (string= dict hunspell-default-dict)
hunspell-default-dict-entry
(list dict))
ispell-hunspell-dictionary-alist :test #'equal))
hunspell-default-dict))