major-mode のつくり方 -- 調査中 #1
major-mode というのは current buffer に対していろいろする関数。以下の「major-mode を適用するときに...」という部分はこの関数でやる。
(defun example-mode () (interactive) ...)
お約束: 既存の buffer-local 変数、モード名、buffer-mode 変数
関数 kill-all-local-variables でそれ以前に設定されてた buffer-local な変数は全部開放。
モード名(モードラインに表示される)は変数 mode-name にセットしておく。
buffer-mode 変数にその major-mode コマンドのシンボルを入れておくことになってる。これはどの major-mode でも実行される hook で、特定の major-mode だったときだけ何かしたい場合などに (eql buffer-mode 'lisp-mode) などと使う。
(kill-all-local-variables) (setq mode-name "Example" buffer-mode 'example-mode)
フック
事前に hook 変数として *example-mode-hook* を defvar しておく。初期値は nil でおk。
(defvar *example-mode-hook* nil)
major-mode を適用するときに、関数 run-hooks でその hook を起動する。これは major-mode command の最後でやる。
(run-hooks '*example-mode-hook*)
キーマップ
事前に make-sparse-keymap で keymap を作って(key-bindingsも設定して)おいて、 *example-mode-map* という special 変数に入れておく。ほとんどの場合は make-keymap じゃなくて make-sparse-keymap でいいと思う(よくわかってない)。
普通はこうする。この lisp code を最初に評価したときは keymap を作るけど、再評価したときに再定義はしない(ユーザが変更した key-bindings を元に戻さないように?)。
(defvar *example-mode-map* nil) (unless *example-mode-map* (setq *example-mode-map* (make-sparse-keymap)) (define-key *example-mode-map* #\KEY 'COMMAND) ...)
major-mode を適用するときに、関数 use-keymap でその keymap を使うようにする。
(use-keymap *example-mode-map*)
シンタックステーブル
事前に syntax-table を作って、*example-mode-syntax-table* という special 変数に入れておき、関数 set-syntax-* で syntax を定義しておく。
(defvar *example-mode-syntax-table* nil) (unless *example-mode-syntax-table* (setq *example-mode-syntax-table* (make-syntax-table)) (set-syntax-string *example-mode-syntax-table* #\") ...)
syntax を指定する関数たち:
- set-syntax-start-column-comment
- set-syntax-escape
- set-syntax-end-c++-comment
- set-syntax-start-c++-comment
- set-syntax-tag
- set-syntax-start-multi-comment
- set-syntax-start-comment
- set-syntax-end-multi-comment
- set-syntax-symbol-prefix
- set-syntax-comment-column
- set-syntax-whitespace
- set-syntax-word
- set-syntax-string
- set-syntax-junk
- set-syntax-symbol
- set-syntax-quote
- set-syntax-math
- set-syntax-option
- set-syntax-match
- set-syntax-punctuation
- set-syntax-end-comment
major-mode を適用するときに、関数 use-syntax-table でその syntax-table を使うようにする。
(use-syntax-table *example-mode-syntax-table*)
キーワードハイライト
まずキーワードファイルを用意しておき、special 変数 *example-keyword-file* にそのファイル名を設定しておく。
次にキーワードファイルから生成される keyword-hash-table を保存する special 変数 *example-keyword-hash-table* を用意しておく。この時点では値は nil でおk。
(defvar *example-mode-file* "Example") (defvar *example-keyword-hash-table* nil)
major-mode を適用するときに、キーワードファイルを読み込んで keyword-hash-table をつくって *example-keyword-hash-table* に保存しておく。既に保存してあったらやらない。
んでもってこの keyword-hash-table を buffer-local 変数 keyword-hash-table に入れることで適用する。
(when (and *example-keyword-file* (null *example-keyword-hash-table*)) (setq *example-keyword-hash-table* (load-keyword-file *example-keyword-file*))) (when *example-keyword-hash-table* (make-local-variable 'keyword-hash-table) (setq keyword-hash-table *example-keyword-hash-table*))
メモ: 関係ありそうなもの、調べなきゃならなさそうなもの
- regexp-keyword-list
- paragraph-separate, paragraph-start
- package と prefix と
- export するもの
- c-indent 関係