Emacsでは、異なる文字をそれぞれ異なる構文カテゴリに属するものとして扱います。例えば、正規表現 ‘\\w+’ は、1つ以上の単語構成文字を指定するパターンです。単語構成文字は、ある一つの構文カテゴリに属します。その他の構文カテゴリには、ピリオドやカンマなどの句読点文字のクラスや、空白やタブ文字などの空白文字のクラスがあります。(詳細については、The GNU Emacs Lisp Reference Manualの構文テーブルを参照してください。)
構文表では、どの文字がどのカテゴリに属するかが規定されています。通常、ハイフンは単語構成文字としては指定されません。その代わりに、記号名の一部ではあるが単語ではない文字のクラスに属するものとして指定されます。つまり、count-words-example 関数はこれを単語間の空白と同様に扱うため、count-words-example は ‘multiply-by-seven’ を3つの単語としてカウントします。
Emacsに‘multiply-by-seven’を1つのシンボルとしてカウントさせるには、構文テーブルを変更するか、正規表現を変更するかの2通りの方法があります。
Emacsがモードごとに保持している構文テーブルを修正することで、ハイフンを単語構成文字として再定義することも可能です。この方法でも目的は達成できますが、ハイフンは単に記号の中で最も頻出する文字に過ぎず、通常は単語構成文字ではありません。他にも該当する文字は存在します。
あるいは、count-words-example
の定義で使用する正規表現を、記号を含めるように再定義することもできます。この手法は明快であるという利点がありますが、作業は少し手間がかかります。
前半部分はいたってシンプルです。パターンは、単語または記号の構成要素である文字のうち、少なくとも1文字に一致しなければなりません。したがって:
"\\(\\w\\|\\s_\\)+"
‘\\(’は、‘\\w’と‘\\s_’を代替候補として含み、それらを‘\\|’で区切ったグループ化構文の第1部分です。‘\\w’は任意の単語構成文字にマッチし、‘\\s_’は記号名の一部でありながら単語構成文字ではない任意の文字にマッチします。グループに続く‘+’は、単語または記号の構成文字が少なくとも1回はマッチしなければならないことを示します。
しかし、正規表現の後半部分の設計はより困難です。実現したいのは、前半部分に続いて、単語や記号の構成要素ではない文字を任意に1文字以上配置することです。当初は、次のように定義できると考えていました。
"\\(\\W\\|\\S_\\)*"
大文字の ‘W’ と ‘S’ は、単語や記号の構成要素ではない文字にマッチします。残念ながら、この式は単語の構成要素でも記号の構成要素でもないあらゆる文字にマッチしてしまいます。つまり、どんな文字にもマッチしてしまうのです!
そこで、テスト領域内のすべての単語や記号の後に、空白(スペース、タブ、または改行)が続いていることに気づきました。そこで、1つ以上の単語や記号の構成要素のパターンの後に、1つ以上の空白にマッチするパターンを配置してみました。しかし、これもうまくいきませんでした。単語や記号は多くの場合空白で区切られていますが、実際のコードでは、記号の後に括弧が続いたり、単語の後に句読点が続いたりすることがあります。そこで最終的に、単語や記号の構成要素の後に、任意で空白以外の文字が続き、さらにその後に任意で空白が続くというパターンを設計しました。
正規表現の全文は以下の通りです:
"\\(\\w\\|\\s_\\)+[^ \t\n]*[ \t\n]*"