Emacs-lisp の Major Mode 記述のサンプル

Emacs で拡張子毎に 動作を規定することができる.これを Major Mode と言い、以下の Emacs-Lisp のサンプルを示す. Emacs-Lisp はとても難解な言語なので、詳しい解説等は他に譲り、ここでは、コピペと最小限の変更で、世に言う 「オレオレモード」 をインスタントに実現することを目指す.

ここで、要求する動作としては、次の通りである.

  • 拡張子を自動判別し、モードを開く.

  • 好きなワードをハイライトする.

ほぼ、ハイライトのためだけの最小限構成としている.今後の改良に期待する.

Emacs-Lisp Major Mode の サンプルコード

以下にコードサンプルを示す.

ハイライト用 Major Mode のサンプルコード
 1;; ========================================================= ;;
 2;; === .sif mode Emacs Major Mode                        === ;;
 3;; ========================================================= ;;
 4
 5;; -- generic mode として定義                    -- ;;
 6(require 'generic-x)
 7
 8;; -- リストインターリーブ関数の定義             -- ;;
 9(defun list-interleave (ls res inserting)
10  (cond
11   ((not ls)  (reverse res))
12   ((not res) (list-interleave (cdr ls) (cons (car ls) res) inserting))
13   (t (list-interleave
14       (cdr ls)
15       (cons (car ls) (cons inserting res))
16       inserting))))
17
18;; -- .sif 変数型群の定義 ( 変数グループの定義 ) -- ;;
19(defvar sif-variables-type-operators
20  (apply 'concat (list-interleave
21                  '("String" "Real" "Logical" "Integer" "None")
22                  '() "\\|")))
23
24;; -- .sif 読み込み時の動作を指定する関数        -- ;;
25(defun sif-initial-call ()
26  '( (setq indent-tabs-mode nil)
27     (setq tab-width 2)
28     )
29  )
30
31;; ------------------------------------------------ ;;
32;; -- .sif Major Mode の定義                     -- ;;
33;; ------------------------------------------------ ;;
34
35;; -- generic-mode 名 :: sif-mode                -- ;;
36(define-generic-mode 'sif-mode
37  ;; 1. コメント行の印
38  '("!" "#")
39  ;; 2. とりあえずハイライトするキーワード群     -- ;;
40  '("Header" "Constants" "Material" "End" "Solver" "Boundary Condition"
41    "Simulation" "Body" "Body Force" "Initial Condition" "Equation" "Components")
42  ;; 3. 詳細な区別でハイライトするキーワード群   -- ;;
43  `( ("\sw"
44      . font-lock-string-face)
45     (,sif-variables-type-operators
46      . font-lock-type-face)
47     )
48  ;; -- 3.1 :: ダブルクォーテーションされた文字 :: string-face として表示 -- ;;
49  ;; -- 3.2 :: 上の関数に示した文字列           :: type-face   として表示 -- ;;
50  ;; -- 
51  ;; 4. file name ( 拡張子の指定 => \\.***$ )
52  '("\\.sif$")
53  ;; 5. hook function ( 起動時に実行する関数 無ければ nil, もしくは、上記関数で定義. )
54  '( sif-initial-call )
55  ;; 6. explanation   ( モードの説明書、呼び出された時になんて表示されるか. )
56  "sif mode for elmer FEM environment"
57  )
58
59;; ------------------------------------------------ ;;
60;; -- 拡張子との連想                             -- ;;
61;; ------------------------------------------------ ;;
62
63;; (add-to-list 'auto-mode-alist '("\\.sif\\'" . sif-mode))

サンプルコード の動作

基本的に Major Mode の定義は、 ( define-generic-mode ... ) を書けば良い. この関数は、次の7つを指定することで定義できる.

  1. モード名 ( sif-mode )

  2. コメント行の開始文字

  3. とりあえずハイライトする文字列群の指定

  4. 詳細なハイライト文字列の指定

  5. 反応する拡張子の指定

  6. ファイルが開かれた際の自動実行する関数

  7. モードの説明文 ( ミニバッファに表示される )

前後には、これに付随する関数を記述している.

モード定義部分内部で変更できる箇所は、上記の7つである.

モード定義部分以外で変更する必要がある箇所は、次の2つ.

  • 変数グループを返却する関数 ( sif-variables-type-operators )

  • 読み込み時の動作を定義する関数 ( sif-initial-call )

変数グループは、関数名 ( グループ名 )と中身の文字列リスト ( '() としてリストを定義 )を変更する. 動作を定義する関数は好きなように変更して良い.何かパラメータを設定したければ、

(setq パラメータ名 )

というようにすれば良い.何も動作する必要が無ければ、sif-initial-call の代わりに nil (何もしない)を書いておいても良い.

末尾の拡張子へのフックは書かなくでも、ファイルを開いた時に自動的に判別される.一応、一般のモードフックの方法を示すためにコメントにて記述している.