(require 'ispell) (setq ispell-debug t) (setq ispell-program-name "hunspell") (setq ispell-hunspell-dict-paths-alist nil) (setq ispell-hunspell-dictionary-alist nil) (defun ispell-print-if-debug (string) "" (if ispell-debug (message "%s" string))) (defun ispell-replace-dictionary-entry (dicts-alist new-entry) "Replace old entry in `DICTS-ALIST' with `NEW-ENTRY'. Mostly intended to play with `ispell-dictionary-alist' and friends." (let (newlist) (dolist (entry dicts-alist) (if (string= (car new-entry) (car entry)) (add-to-list 'newlist new-entry) (add-to-list 'newlist entry))) newlist)) (defun ispell-parse-hunspell-affix-file (dict-name) "Parse hunspell affix file for `dict-name'. Return a list in `ispell-dictionary-alist' format." (let* ((path (cadr (assoc dict-name ispell-hunspell-dict-paths-alist))) (affix-file (concat path dict-name ".aff"))) (unless path (error "No matching entry for %s" dict-name)) (if (file-exists-p affix-file) (with-temp-buffer (insert-file-contents affix-file) (let (otherchars-string otherchars-list) (setq otherchars-string (save-excursion (beginning-of-buffer) (if (search-forward-regexp "^WORDCHARS +" nil t ) (buffer-substring (point) (progn (end-of-line) (point)))))) ;; Remove trailing whitespace and extra stuff. Make list if non-nil. (setq otherchars-list (if otherchars-string (split-string (if (string-match " +.*$" otherchars-string) (replace-match "" nil nil otherchars-string) otherchars-string) "" t))) ;; Fill dict entry (list dict-name "[[:alpha:]]" "[^[:alpha:]]" (if otherchars-list (regexp-opt otherchars-list) "") t ;; many-otherchars-p: We can't tell, set to t (list "-d" dict-name) nil ;; extended-char-mode: not supported by hunspell 'utf-8))) (error "File \"%s\" not found" affix-file)))) (defun ispell-find-hunspell-dictionaries () "Parse installed hunspell dictionaries." (let ((hunspell-found-dicts (split-string (with-temp-buffer (ispell-call-process ispell-program-name null-device t nil "-D") (buffer-string)) "[\n\r]+" t)) hunspell-default-dict hunspell-default-dict-entry) (dolist (dict hunspell-found-dicts) (let* ((full-name (file-name-nondirectory dict)) (path (file-name-directory dict)) (basename (file-name-sans-extension full-name))) (if (string-match "\\.aff$" dict) ;; Found default dictionary (if hunspell-default-dict (error "Default dict already defined as %s. Not using %s." hunspell-default-dict dict) (setq hunspell-default-dict (list basename path))) (if (and (not (assoc basename ispell-hunspell-dict-paths-alist)) (file-exists-p (concat dict ".aff"))) ;; Entry has an associated .aff file and no previous value. (progn (ispell-print-if-debug (format "++ dict-entry:%s name:%s basename:%s path:%s aff:%s" dict full-name basename path (concat dict ".aff"))) (add-to-list 'ispell-hunspell-dict-paths-alist (list basename path))) (ispell-print-if-debug (format "-- Skipping %s" dict)))))) ;; Parse values for default dictionary. (setq hunspell-default-dict (car hunspell-default-dict)) (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 (append (list nil) (cdr hunspell-default-dict-entry)))) (dolist (dict (mapcar 'car ispell-hunspell-dict-paths-alist)) (if (string= dict hunspell-default-dict) (add-to-list 'ispell-hunspell-dictionary-alist hunspell-default-dict-entry) (add-to-list 'ispell-hunspell-dictionary-alist (list dict)))))) (ispell-find-hunspell-dictionaries) (setq mylang "en_US") (message "-- For selected language \"%s\" before: %s" mylang (assoc mylang ispell-hunspell-dictionary-alist)) (or (cadr (assoc mylang ispell-hunspell-dictionary-alist)) (let ((dict-entry (ispell-parse-hunspell-affix-file mylang))) (setq ispell-hunspell-dictionary-alist (ispell-replace-dictionary-entry ispell-hunspell-dictionary-alist dict-entry)))) (message "-- For selected language \"%s\" after: %s" mylang (assoc mylang ispell-hunspell-dictionary-alist))