わさっきhb

大学(教育研究)とか ,親馬鹿とか,和歌山とか,とか,とか.

count-lines-regionに語数カウント機能をつける

じんもんこん2010の原稿は,なんとか投函できました.終盤はやっぱり,ギリギリのダメダメでした.私が「これを入れてくれ」と指示した文章には,次の日*1のミーティングで,アホみたいなミスが見つかりました.発行されたら,自分のWebページにErrataを作ることにします.ちなみに,2年前の論文誌の中では,謝辞で科研費の課題番号を間違えたという,もっと恥ずかしいミスをしています.
日本語概要,英語アブストラクトも,内容がほぼ確定した時点で,実験とりまとめをしている学生と並列に,こちらで書きました.日本語概要は300字程度,英語のほうは100語程度とのこと.日本語の字数は,NTEmacs上でリージョンを指定してM-=とすれば求められることを知り,喜んで何度も使ったのですが,英文で同じようにすると,語数までは教えてくれません.実のところ,M-=に紐付けられているcount-lines-regionは,行数と字数しか教えてくれないのです.
語数を知るには,シェルでwcコマンドを使わないといけないのか….いや,Emacs Lispでできそうな気がしてきました.
まずは調査です.リージョンの語数を数える関数の定義は,探すと出てきました.

(defun djcb-count-words (&optional begin end)
  "count words between BEGIN and END (region); if no region defined, count words in buffer"
  (interactive "r")
  (let ((b (if mark-active begin (point-min)))
      (e (if mark-active end (point-max))))
    (message "Word count: %s" (how-many "\\w+" b e))))
emacs-fu: counting words

領域を選択して,M-x djcb-count-wordsとすると,「Word count: 72」と表示されます.領域を指定せずに,M-x djcb-count-wordsだと,バッファ全体の語数です.なるほど.
いやいや,単機能なのはいいけど,のちのち,これをするために~/.emacsを見直して関数名を確認するというのは手間です.M-=とすれば,wcコマンドをNTEmacsで実行できるかのように,リージョンまたはバッファ全体の行数・語数・文字数*2を求めることを目指しましょう.
もう一つ,調べておきたいのは,M-=に紐付けをされている関数の所在です.M-x help-for-helpのあと,kそしてM-=を押して出てくるメッセージによると,(Emacsのパス)/lisp/simple.elにあると言います.覗いてみました.

(defun count-lines-region (start end)
  "Print number of lines and characters in the region."
  (interactive "r")
  (message "Region has %d lines, %d characters"
	   (count-lines start end) (- end start)))

では,2つの関数をくっつけましょう.

(defun tm-count-lines-region (&optional begin end)
  "Print number of lines, words and characters in the region."
  (interactive "r")
  (let ((b (if mark-active begin (point-min)))
      (e (if mark-active end (point-max))))
    (message "Region has %d lines, %s words, %d characters"
             (count-lines b e) (how-many "\\w+" b e) (- e b))))
(global-set-key "\M-=" 'tm-count-lines-region)

tmはTrade MarkでもTaMaでもなく,単純に自分のイニシャルです.startとend,beginとendのどちらでもいいのですが,djcb-count-wordsのほうに合わせました.説明・表示の英語は,count-lines-regionのほうをベースにしています.
範囲を選択してM-=とすると…めでたく,「Region has 1 lines, 121 words, 727 characters」と出ました.
余談:これによって,概要作成の手順 - わさっきで書いた『20字改行,マルチバイト化』が不要になったかというと,そうは思っていません.この強制改行は,何に関する記述でどれだけを占めているかが見て分かるという効果があります.今回の概要・アブストラクトでは,自作関数に興奮するあまり,使いませんでしたが.

*1:17日必着なので,16日の昼間にお城そばの中央郵便局まで,学生にひとっ走りしてもらいました.http://search.post.japanpost.jp/deli_days/index.htmlは,ありがたかったですねえ.

*2:結果オーライ(死語か)ですが,wcは行数・語数・バイト数が出力されます.字数制限のかかった文章を編集しているとき,バイト数よりも文字数を知りたいのは,言うまでもありませんね.