Saturday, December 27, 2014

Emacs Syntax Table の変更

丁度 M-uM-lM-c みたく、単語をキャメルケース、スネークケース、スパイナルケースに変換したい案件あり。

まずは単語の抜き出にトライ。

単語の抜き出しは word-at-point を活用できそう。だけど _ とか - が含まれてこない。 それらを単語として解釈してもらうにはどう設定すればいいか。

そこで EmacsWiki: Emacs Syntax Table を斜め読み。

結論、諸々解るも、基底(?)のシンタックステーブルを変更する手法だと術が見つからないため断念。

だけど modify-syntax-entry でカレントバッファのシンタックステーブルを変更できるため、 代わりにこれを prog-mode-hooktext-mode-hook に追加して事なきを得ましたと。

init.el に以下。

(defun my-syntax-table ()
  (modify-syntax-entry ?- "w")
  (modify-syntax-entry ?_ "w"))
(add-hook 'prog-mode-hook 'my-syntax-table)
(add-hook 'text-mode-hook 'my-syntax-table)

新しい挙動に慣れないせいか使いにくくなった気がしなくもないですけど。

以降、 EmacsWiki: Emacs Syntax Table の読みメモ。

Emacs Syntax Table

シンタックステーブルは、ワードごとの前後カーソル移動などに使用される。

シンタックスはバッファごとに異なり、メジャーモードでコントロールされる。

シンタックステーブルは standard syntax table を継承する。

Working with Syntax table

C-h s (describe-syntax) でカレントバッファのシンタックステーブルを参照できる。

シンタックステーブルには、各キャラクタやキャラクタレンジと、シンタックスクラスとの対応がリストされる。

シンタックスクラスは以下のシンボルで識別される。

-   whitespace character        /   character quote character
w   word constituent            $   paired delimiter
_   symbol constituent          '   expression prefix
.   punctuation character       <   comment starter
(   open delimiter character    >   comment ender
)   close delimiter character   !   generic comment delimiter
"   string quote character      |   generic string delimiter
\   escape character            @   inherit from `standard-syntax-table'

カレントシンタックステーブルにおける + のシンタックスを参照するには以下。

(char-to-string (char-syntax ?+))

How to define a new syntax table

シンタックステーブルは make-char-table で定義する。

新しいシンタックステーブルは、通常、基本的なシンタックステーブルを継承し、置き換えることで定義する。

スタンダードシンタックステーブルから設定していくには以下。

(setq my-table (make-syntax-table))

text-mode シンタックステーブルからだと以下。

(setq my-table (make-syntax-table text-mode-syntax-table))

Hacking the syntax table

キャラクタのシンタックスは modify-syntax-entry で変更する。

クォータキャラクタにエクスプレッションプレフィックスクラスをセットする例。(Lisp モードでのデフォルト)

(modify-syntax-entry ?' "'")

ブラケット [] にワードクラスをセットし、デリミタとしての解釈を除去する例。

(modify-syntax-entry ?[ "w")
(modify-syntax-entry ?] "w")

などなど、他にも述べられているが本件ではスルー。

カレントシンタックステーブルを変更し、新しいシンタックステーブルを定義するには以下。 (と記載があるけど、この場合 make-syntax-table は standard-syntax-table を戻すのでは)

(defvar my-wacky-syntax-table
     (let ((table (make-syntax-table)))
       (modify-syntax-entry ?[ "w" table)
       (modify-syntax-entry ?] "w" table)
       table))

text-mode のデフォルトテーブルとして my-wacky-syntax-table を指定できる。

(add-hook 'text-mode-hook (lambda ()
            (set-syntax-table my-wacky-syntax-table)))