Emacs 使用ispell/aspell检查大小写单词的拼写
我需要检查一个包含许多大小写单词的大文件的拼写。我想让ispell或aspell检查每个单词是否拼写正确 因此,对于这个词: 科学进步 我希望它能提出以下建议: 科学进步Emacs 使用ispell/aspell检查大小写单词的拼写,emacs,aspell,camelcasing,ispell,Emacs,Aspell,Camelcasing,Ispell,我需要检查一个包含许多大小写单词的大文件的拼写。我想让ispell或aspell检查每个单词是否拼写正确 因此,对于这个词: 科学进步 我希望它能提出以下建议: 科学进步 有没有办法做到这一点?(我的意思是,在Emacs缓冲区上运行它时。)注意,我不一定希望它建议完整的替代方案。但是,如果它知道Progrez不被识别,我希望至少能够替换该部分,或者将该单词添加到我的私人词典中,而不是将每个大小写单词都包含在词典中。您应该解析大小写单词并将其拆分,然后检查每个标记的单个拼写,并根据每个拼写错误的标
有没有办法做到这一点?(我的意思是,在Emacs缓冲区上运行它时。)注意,我不一定希望它建议完整的替代方案。但是,如果它知道Progrez不被识别,我希望至少能够替换该部分,或者将该单词添加到我的私人词典中,而不是将每个大小写单词都包含在词典中。您应该解析大小写单词并将其拆分,然后检查每个标记的单个拼写,并根据每个拼写错误的标记的单个建议组合一个建议。考虑到每个拼写错误的代币都可能有多个建议,这对我来说有点低效。我接受了@phils的建议,并深入研究了一下。事实证明,如果您获得并重新配置某些ispell,如下所示:
(defun ispell-get-word (following)
(when following
(camelCase-forward-word 1))
(let* ((start (progn (camelCase-backward-word 1)
(point)))
(end (progn (camelCase-forward-word 1)
(point))))
(list (buffer-substring-no-properties start end)
start end)))
然后,在这种情况下,像thisone这样的单个驼峰大小写的单词实际上会被正确地拼写检查。(除非你在一个文档的开头——我刚刚发现。)
因此,这显然不是一个完整的解决方案,但至少它是某种东西 aspell中有“-run-together”选项。Hunspell无法检查大小写单词
如果您阅读aspell的代码,您会发现它的算法实际上并没有将camelcase单词拆分为子单词列表。也许这个算法更快,但它会错误地将包含两个字符子单词的单词报告为打字错误。不要浪费时间调整其他aspell选项。我试过了,但没有成功
所以我们有两个问题:
(defun split-camel-case (word)
"Split camel case WORD into a list of strings.
Ported from 'https://github.com/fatih/camelcase/blob/master/camelcase.go'."
(let* ((case-fold-search nil)
(len (length word))
;; ten sub-words is enough
(runes [nil nil nil nil nil nil nil nil nil nil])
(runes-length 0)
(i 0)
ch
(last-class 0)
(class 0)
rlt)
;; split into fields based on class of character
(while (< i len)
(setq ch (elt word i))
(cond
;; lower case
((and (>= ch ?a) (<= ch ?z))
(setq class 1))
;; upper case
((and (>= ch ?A) (<= ch ?Z))
(setq class 2))
((and (>= ch ?0) (<= ch ?9))
(setq class 3))
(t
(setq class 4)))
(cond
((= class last-class)
(aset runes
(1- runes-length)
(concat (aref runes (1- runes-length)) (char-to-string ch))))
(t
(aset runes runes-length (char-to-string ch))
(setq runes-length (1+ runes-length))))
(setq last-class class)
;; end of while
(setq i (1+ i)))
;; handle upper case -> lower case sequences, e.g.
;; "PDFL", "oader" -> "PDF", "Loader"
(setq i 0)
(while (< i (1- runes-length))
(let* ((ch-first (aref (aref runes i) 0))
(ch-second (aref (aref runes (1+ i)) 0)))
(when (and (and (>= ch-first ?A) (<= ch-first ?Z))
(and (>= ch-second ?a) (<= ch-second ?z)))
(aset runes (1+ i) (concat (substring (aref runes i) -1) (aref runes (1+ i))))
(aset runes i (substring (aref runes i) 0 -1))))
(setq i (1+ i)))
;; construct final result
(setq i 0)
(while (< i runes-length)
(when (> (length (aref runes i)) 0)
(setq rlt (add-to-list 'rlt (aref runes i) t)))
(setq i (1+ i)))
rlt))
(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."
;; force the English dictionary, support Camel Case spelling check (tested with aspell 0.6)
(let* ((args (list "--sug-mode=ultra" "--lang=en_US"))args)
(if run-together
(setq args (append args '("--run-together" "--run-together-limit=16"))))
args))
;; {{ for aspell only, hunspell does not need setup `ispell-extra-args'
(setq ispell-program-name "aspell")
(setq-default ispell-extra-args (flyspell-detect-ispell-args t))
;; }}
;; ;; {{ hunspell setup, please note we use dictionary "en_US" here
;; (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)))
;; ;; }}
(defvar extra-flyspell-predicate '(lambda (word) t)
"A callback to check WORD. Return t if WORD is typo.")
(defun my-flyspell-predicate (word)
"Use aspell to check WORD. If it's typo return t."
(let* ((cmd (cond
;; aspell: `echo "helle world" | aspell pipe`
((string-match-p "aspell$" ispell-program-name)
(format "echo \"%s\" | %s pipe"
word
ispell-program-name))
;; hunspell: `echo "helle world" | hunspell -a -d en_US`
(t
(format "echo \"%s\" | %s -a -d en_US"
word
ispell-program-name))))
(cmd-output (shell-command-to-string cmd))
rlt)
;; (message "word=%s cmd=%s" word cmd)
;; (message "cmd-output=%s" cmd-output)
(cond
((string-match-p "^&" cmd-output)
;; it's a typo because at least one sub-word is typo
(setq rlt t))
(t
;; not a typo
(setq rlt nil)))
rlt))
(defun js-flyspell-verify ()
(let* ((case-fold-search nil)
(font-matched (memq (get-text-property (- (point) 1) 'face)
'(js2-function-call
js2-function-param
js2-object-property
js2-object-property-access
font-lock-variable-name-face
font-lock-string-face
font-lock-function-name-face
font-lock-builtin-face
rjsx-text
rjsx-tag
rjsx-attr)))
subwords
word
(rlt t))
(cond
((not font-matched)
(setq rlt nil))
;; ignore two character word
((< (length (setq word (thing-at-point 'word))) 2)
(setq rlt nil))
;; handle camel case word
((and (setq subwords (split-camel-case word)) (> (length subwords) 1))
(let* ((s (mapconcat (lambda (w)
(cond
;; sub-word wholse length is less than three
((< (length w) 3)
"")
;; special characters
((not (string-match-p "^[a-zA-Z]*$" w))
"")
(t
w))) subwords " ")))
(setq rlt (my-flyspell-predicate s))))
(t
(setq rlt (funcall extra-flyspell-predicate word))))
rlt))
(put 'js2-mode 'flyspell-mode-predicate 'js-flyspell-verify)
(取消拆分驼峰格(word)
“将大小写单词拆分为字符串列表。
从https://github.com/fatih/camelcase/blob/master/camelcase.go'."
(let*((箱子折叠搜索无)
(len(长单词))
十个副词就足够了
(符文[零零零零零零零零零])
(符文长度0)
(i)第0条
中国
(最后一节课0)
(0级)
(rlt)
;;根据字符类别拆分为字段
(while(=ch?a)(=ch?a)(=ch?0)(小写顺序,例如。
“PDFL”、“加载程序”->“PDF”、“加载程序”
(setq i 0)
(while(=ch first?A)(=ch second?A)((长度(aref符文i))0)
(setq rlt(添加到列表'rlt(aref符文i)t)))
(setq i(1+i)))
(rlt)
(取消flyspell detect ispell参数(&可选一起运行)
如果RUN-TOGETHER为true,请检查CamelCase单词的拼写。
请注意,一起运行将降低aspell的能力。因此,它应仅用于prog模式挂钩。”
;强制使用英语词典,支持大小写拼写检查(使用aspell 0.6测试)
(let*((args(list--sug mode=ultra“--lang=en_US”)args)
(如果一起跑
(setq args(附加args'(“--run-house”“--run-house limit=16”))
args)
{{仅对于aspell,hunspell不需要设置“ispell额外参数”
(setq ispell程序名“aspell”)
(setq默认ispell额外参数(flyspell detect ispell args t))
;; }}
{{拼写设置,请注意我们在这里使用字典“en_US”
;;(setq ispell程序名“hunspell”)
(setq ispell本地词典“en_US”)
;(setq ispell local dictionary)
‘((“en_US”[[:alpha:][]”“[^[:alpha:][][']”无(“-d”en_US”)无utf-8)))
;; ;; }}
(defvar额外flyspell谓词(lambda(word)t)
“检查单词的回调。如果单词拼写错误,则返回t。”)
(取消我的flyspell谓词(word)
“使用aspell检查WORD。如果键入错误,请返回t。”
(让*)命令(条件)
;阿斯佩尔:`echo“helle world”|阿斯佩尔管`
((string-match-p“aspell$”ispell程序名)
(格式为“echo\%s\”|%s管道)
单词
ispell程序名)
|;hunspell:`echo“helle world”| hunspell-a-d en|u US`
(t
(格式为“echo\%s\”|%s-a-d en_US”
单词
ispell程序名)
(cmd输出(shell命令到字符串cmd))
(rlt)
;;(消息“word=%s cmd=%s”word cmd)
;;(消息“cmd output=%s”cmd output)
(续)
((string-match-p“^&”cmd输出)
这是一个拼写错误,因为至少有一个子词是拼写错误
(setq rlt)
(t
不是打字错误
(setq rlt nil)))
(rlt)
(defun js flyspell verify()
(let*((箱子折叠搜索无)
(字体匹配(memq(获取文本属性(-(点)1)”面)
'(js2函数调用
js2函数参数
js2对象属性
js2对象属性访问
字体锁定变量名面
字体锁定字符串面
字体锁定函数名面
字体锁定内置面
rjsx文本
rjsx标签
rjsx attr)
子词
单词
(rlt)
(续)
((字体不匹配)
(setq rlt零)
忽略两个字符的单词