Processing math: 100%

2014/05/07

EmacsのGeneric Mode


自分のプログラミング言語を作ったのに, Emacsがシンタックスハイライトをしてくれないので(下図),
寂しいなと思っていたところ, Generic Modeというのがあったので, これを使ってハイライトしてみました.
その時のメモ.
Fig.1 : シンタックスハイライト前
define-generic-modeを呼ぶだけで簡単にシンタックスハイライト用のモードを作成することができます.
ほとんど, Schemeを関数型言語風にアレンジした見た目です. $x. xはラムダ抽象を表しています. 
ハイライトがないと, 全体的にのっぺりとしていて, シンタックスが読みづらい.
というわけで, Generic Modeを以下のように設定しました.
    (require 'generic-x)
    (defun list-interleave (ls res inserting)
    (cond
    ((not ls) (reverse res))
    ((not res) (list-interleave (cdr ls) (cons (car ls) res) inserting))
    (t (list-interleave
    (cdr ls)
    (cons (car ls) (cons inserting res))
    inserting))))
    (defvar infinterp-operators
    (apply 'concat (list-interleave
    '("\\+" "-" "*" "=" ";" "<" ">")
    '() "\\|")))
    (defvar infinterp-builtins
    (mapcar (function (lambda (x) `(,x . font-lock-builtin-face)))
    '("mod" "div" "round" "display" "cons" "car" "cdr" "null" )))
    ;; 文字列リテラル分の\と正規表現用の\で \\|がorを表す.
    (define-generic-mode 'infinterp-mode
    ;; 1. comment
    '("#")
    ;; 2. highlights for keywords
    '("let" "in" "if" "then" "else")
    ;; 3. highlights for each element
    `(("\\(define\\)\\|\\(<-\\)\\|\\;"
    . font-lock-type-face)
    (,infinterp-operators
    . font-lock-builtin-face)
    ("\sw"
    . font-lock-string-face)
    ;; define
    ("^\\s-*define\\s-+\\([A-Za-z0-9_/]+\\)"
    (1 font-lock-function-name-face))
    ;; mu operator
    ("mu\\s-+\\([A-Za-z0-9_/]+\\)\\s-*\\."
    (1 font-lock-function-name-face))
    ;; lambda operator
    ("\\$\\s-*\\([A-Za-z0-9_/ ]+\\)\\s-*\\."
    (1 font-lock-function-name-face))
    . ,infinterp-builtins)
    ;; 4. file name
    '("\\.lil$")
    ;; 5. hook function
    nil
    ;; 6. explanation
    "infinterp mode")
    view raw mylang-mode.el hosted with ❤ by GitHub


    define-generic-modeへは, モード名以外に6つのパラメータを渡します.
    1. 最初の要素はコメントの開始文字列, Lispのセミコロンや, Pythonの#, C++の//など.
    2. 次の要素はハイライトするキーワードの要素
    3. そして, 各種キーワードや型, 文字列など, 細かいハイライトの指定.
      1. ハイライトするトークンの正規表現とそれに対応するfont-lock-faceを指定します.
      2. "ダブルクオーテーションによる文字列"は, 便利な"\\sw"で一発指定できます.
    4. 4番目の要素はファイル名(正規表現を用いて拡張子などを指定).
      1. 今回は".lil"で終わるファイルの時にこのモードを起動するような設定.
    5. 5番目の要素は, hook functionで, モードの起動時に実行される関数. 不要ならnilでもよい.
    6. 最後にモードの説明を入れます.
    上記のように設定すると, 以下のようにハイライトされました.
    Fig.2 : シンタックスハイライト後
    若干読みやすくなったように思えます.
    Web上の設定サンプルは, logファイルのハイライトの例が多かったのですが, オレオレ言語を作った時にも使えました.