Emacs 中英日文字數計算

這是大學生寫報告交作業的必需品啊 XD

Update @ 20140524: 我稍微改進了一下,現在會忽略註解,也就是註解不算在字數內。

Emacs 內建的 count-words 不太方便,只能統計英文字數。一直以來都是調用 script 來計算,但實在太龜速(跑了好幾層的 awk 跟 sed…)、設定也太麻煩。之前一直很想用 Emacs Lisp 重寫這個功能,但一直不知該怎麼做,完全找不到有文章在講中日文的這類問題,大概很少有 Emacser 需要做這種事吧…。

不過今天才突然發現其實非常容易,而且速度比我之前用的方法快很多很多。關鍵在於 rx 這個函數,詳細資訊可用 C-h f查詢內建文檔。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
(defvar wc-regexp-chinese-char-and-punc
(rx (category chinese)))
(defvar wc-regexp-chinese-punc
"[。,!?;:「」『』()、【】《》〈〉※—]")
(defvar wc-regexp-english-word
"[a-zA-Z0-9-]+")

(defun wc ()
"「較精確地」統計中/日/英文字數。
- 文章中的註解不算在字數內。
- 平假名與片假名亦包含在「中日文字數」內,每個平/片假名都算單獨一個字(但片假
名不含連音「ー」)。
- 英文只計算「單字數」,不含標點。
- 韓文不包含在內。

※計算標準太多種了,例如英文標點是否算入、以及可能有不太常用的標點符號沒算入等
。且中日文標點的計算標準要看 Emacs 如何定義特殊標點符號如ヴァランタン・アルカン
中間的點也被 Emacs 算為一個字而不是標點符號。"
(interactive)
(let* ((v-buffer-string
(progn
(if (eq major-mode 'org-mode) ; 去掉 org 文件的 OPTIONS(以#+開頭)
(setq v-buffer-string (replace-regexp-in-string "^#\\+.+" ""
(buffer-substring-no-properties (point-min) (point-max))))
(setq v-buffer-string (buffer-substring-no-properties (point-min) (point-max))))
(replace-regexp-in-string (format "^ *%s *.+" comment-start) "" v-buffer-string)))
; 把註解行刪掉(不把註解算進字數)。
(chinese-char-and-punc 0)
(chinese-punc 0)
(english-word 0)
(chinese-char 0))
(with-temp-buffer
(insert v-buffer-string)
(goto-char (point-min))
;; 中文(含標點、片假名)
(while (re-search-forward wc-regexp-chinese-char-and-punc nil :no-error)
(setq chinese-char-and-punc (1+ chinese-char-and-punc)))
;; 中文標點符號
(goto-char (point-min))
(while (re-search-forward wc-regexp-chinese-punc nil :no-error)
(setq chinese-punc (1+ chinese-punc)))
;; 英文字數(不含標點)
(goto-char (point-min))
(while (re-search-forward wc-regexp-english-word nil :no-error)
(setq english-word (1+ english-word))))
(setq chinese-char (- chinese-char-and-punc chinese-punc))
(message
(format "中日文字數(不含標點):%s
中日文字數(包含標點):%s
英文字數(不含標點):%s
=======================
中英文合計(不含標點):%s"
chinese-char chinese-char-and-punc english-word
(+ chinese-char english-word)))))

M-x wc即可使用

[TODO] 看看能不能寫成 minor mode 即時顯示在 mode line 裡,但我不知該怎麼做。


[2014-01-18 土 01:49] 寫完共 1 小時 25 分。