af808ea Jul 9, 2018
1 contributor

Users who have contributed to this file

190 lines (169 sloc) 7.55 KB
;; {{ flyspell setup for web-mode
(defun web-mode-flyspell-verify ()
(let* ((f (get-text-property (- (point) 1) 'face))
;; Check the words with these font faces, possibly.
;; This *blacklist* will be tweaked in next condition
((not (memq f '(web-mode-html-attr-value-face
web-mode-comment-face ;; focus on get html label right
(setq rlt t))
;; check attribute value under certain conditions
((memq f '(web-mode-html-attr-value-face))
(search-backward-regexp "=['\"]" (line-beginning-position) t)
(setq rlt (string-match "^\\(value\\|class\\|ng[A-Za-z0-9-]*\\)$"
(thing-at-point 'symbol)))))
;; finalize the blacklist
(setq rlt nil)))
(put 'web-mode 'flyspell-mode-predicate 'web-mode-flyspell-verify)
;; }}
;; {{ flyspell setup for js2-mode
(local-require 'wucuo)
(put 'js2-mode 'flyspell-mode-predicate 'wucuo-generic-check-word-predicate)
(put 'rjsx-mode 'flyspell-mode-predicate 'wucuo-generic-check-word-predicate)
;; }}
(eval-after-load 'flyspell
(require 'flyspell-lazy)
(flyspell-lazy-mode 1)))
;; better performance
(setq flyspell-issue-message-flag nil)
;; if (aspell installed) { use aspell}
;; else if (hunspell installed) { use hunspell }
;; whatever spell checker I use, I always use English dictionary
;; I prefer use aspell because:
;; 1. aspell is older
;; 2. looks Kevin Atkinson still get some road map for aspell:
;; @see
(defun flyspell-detect-ispell-args (&optional run-together)
"If RUN-TOGETHER is true, spell check the CamelCase words.
Please note RUN-TOGETHER will make aspell less capable. So it should only be used in prog-mode-hook."
(let (args)
(when ispell-program-name
((string-match "aspell$" ispell-program-name)
;; force the English dictionary, support Camel Case spelling check (tested with aspell 0.6)
(setq args (list "--sug-mode=ultra" "--lang=en_US"))
;; "--run-together-min" could not be 3, see `check` in "speller_impl.cpp" . The algorithm is
;; not precise .
;; Run `echo tasteTableConfig | aspell --lang=en_US -C --run-together-limit=16 --encoding=utf-8 -a` in shell.
(if run-together
(setq args (append args '("--run-together" "--run-together-limit=16")))))
((string-match "hunspell$" ispell-program-name)
(setq args nil))))
;; Aspell Setup (recommended):
;; Skipped because it's easy.
;; Hunspell Setup:
;; 1. Install hunspell from
;; 2. Download openoffice dictionary extension from
;; 3. That is download `dict-en.oxt'. Rename that to `' and unzip
;; the contents to a temporary folder.
;; 4. Copy `en_US.dic' and `en_US.aff' files from there to a folder where you
;; save dictionary files; I saved it to `~/usr_local/share/hunspell/'
;; 5. Add that path to shell env variable `DICPATH':
;; setenv DICPATH $MYLOCAL/share/hunspell
;; 6. Restart emacs so that when hunspell is run by ispell/flyspell, that env
;; variable is effective.
;; hunspell will search for a dictionary called `en_US' in the path specified by
(defvar force-to-use-hunspell nil
"If t, force to use hunspell. Or else, search aspell at first and fall
back to hunspell if aspell is not found.")
;; use aspell
((and (not force-to-use-hunspell) (executable-find "aspell"))
(setq ispell-program-name "aspell"))
;; use hunspell
((executable-find "hunspell")
(setq ispell-program-name "hunspell")
(setq ispell-local-dictionary "en_US")
(setq ispell-local-dictionary-alist
'(("en_US" "[[:alpha:]]" "[^[:alpha:]]" "[']" nil ("-d" "en_US") nil utf-8))))
(t (setq ispell-program-name nil)
(message "You need install either aspell or hunspell for ispell")))
;; `ispell-cmd-args' contains *extra* arguments appending to CLI process
;; when (ispell-send-string). Useless!
;; `ispell-extra-args' is *always* used when start CLI aspell process
(setq-default ispell-extra-args (flyspell-detect-ispell-args t))
;; (setq ispell-cmd-args (flyspell-detect-ispell-args))
(defadvice ispell-word (around my-ispell-word activate)
(let ((old-ispell-extra-args ispell-extra-args))
(ispell-kill-ispell t)
;; use emacs original arguments
(setq ispell-extra-args (flyspell-detect-ispell-args))
;; restore our own ispell arguments
(setq ispell-extra-args old-ispell-extra-args)
(ispell-kill-ispell t)))
(defadvice flyspell-auto-correct-word (around my-flyspell-auto-correct-word activate)
(let* ((old-ispell-extra-args ispell-extra-args))
(ispell-kill-ispell t)
;; use emacs original arguments
(setq ispell-extra-args (flyspell-detect-ispell-args))
;; restore our own ispell arguments
(setq ispell-extra-args old-ispell-extra-args)
(ispell-kill-ispell t)))
(defun text-mode-hook-setup ()
;; Turn off RUN-TOGETHER option when spell check text-mode
(setq-local ispell-extra-args (flyspell-detect-ispell-args)))
(add-hook 'text-mode-hook 'text-mode-hook-setup)
;; Add auto spell-checking in comments for all programming language modes
;; if and only if there is enough memory
;; You can use prog-mode-hook instead.
(defun can-enable-flyspell-mode ()
(and (not *no-memory*)
(executable-find ispell-program-name)))
(defun enable-flyspell-mode-conditionally ()
(if (can-enable-flyspell-mode)
(flyspell-mode 1)))
;; turn on flyspell-mode for programming languages
(if (can-enable-flyspell-mode)
(add-hook 'prog-mode-hook 'flyspell-prog-mode))
;; I don't use flyspell in text-mode because I often write Chinese.
;; I'd rather manually spell check the English text
;; you can also use "M-x ispell-word" or hotkey "M-$". It pop up a multiple choice
;; @see
(global-set-key (kbd "C-c s") 'flyspell-auto-correct-word)
;; {{ avoid spell-checking doublon (double word) in certain major modes
(defvar flyspell-check-doublon t
"Check doublon (double word) when calling `flyspell-highlight-incorrect-region'.")
(make-variable-buffer-local 'flyspell-check-doublon)
(defadvice flyspell-highlight-incorrect-region (around flyspell-highlight-incorrect-region-hack activate)
(if (or flyspell-check-doublon (not (eq 'doublon (ad-get-arg 2))))
;; }}
(defun my-clean-aspell-dict ()
"Clean ~/.aspell.pws (dictionary used by aspell)."
(let* ((dict (file-truename "~/.aspell.en.pws"))
(lines (read-lines dict))
;; sort words
(aspell-words (sort (cdr lines) 'string<)))
(with-temp-file dict
(insert (format "%s %d\n%s"
"personal_ws-1.1 en"
(length aspell-words)
(mapconcat 'identity aspell-words "\n"))))))
(provide 'init-spelling)