regexp-keyword-list

指定した正規表現にマッチする文字列に色をつける機能。reference によればこんな風に使う。

;; regexp-keyword-list に使う list を用意しておいて
(defvar *hoge-regexp-keyword-list*
  (compile-regexp-keyword-list
   '(("regexp" CASE-FOLD COLOR *CONTEXT *BEGIN *END)
     ...)))

;; 適用する buffer で local に regexp-keyword-list を bind
(make-local-variable 'regexp-keyword-list)
(setq regexp-keyword-list *hoge-regexp-keyword-list*)

このやり方だと一箇所で全部の regexp-keyword を定義しておかなきゃならんので、バラバラに regexp-keyword を定義しつつ、まとめて適用できないもんかと調べてみた。

見たのは re-kwd.l。compile-regexp-keyword-list は与えられた

("regexp" CASE-FOLD COLOR *CONTEXT *BEGIN *END)

こんなやつ(めんどいので regexp-keyword と勝手に命名)の list を mapcar で compile-regexp-keyword という関数に渡す*1だけだった。compile-regexp-keyword はそれぞれの要素をごにょごにょして

(REGEXP COLOR CONTEXT begin end)

みたいな list を返す。またまた compiled-regexp-keyword と勝手に命名。要素は左から

  • REGEXP: compile 済み regexp
  • COLOR: どの色にするかを示すと思しき number
  • CONTEXT: どこでなら色をつけるかを示すと思しき number
  • あとの begin と end は最初に指定した数そのまま

で、COLOR と CONTEXT の number はビット演算してるらしいので flag とかみたい。正直よくわからん。

でー、要は buffer-local にして regexp-keyword-list を「compiled-regexp-keyword の list」に bind しておけばいい。なので、好きなだけ compile-regexp-keyword-list で作っておいて、buffer に適用するときにそれらをまとめてしまえばだいじょぶなはず。

;;; *scratch* にて

(setf rekwd-list-foo
      (compile-regexp-keyword-list
       '(("^FOO:[ \t]*.+$" nil (:color 3))))
      rekwd-list-bar
      (compile-regexp-keyword-list
       '(("^BAR:[ \t]*.+$" nil (:color 4))))
      rekwd-list-baz
      (compile-regexp-keyword-list
       '(("^BAZ:[ \t]*.+$" nil (:color 5)))))
=> ((#<compiled regular expression: ^BAZ:[ 	]*.+$> 2561 1 0 0))

(make-local-variable 'regexp-keyword-list)
=> t

(setq regexp-keyword-list
      (append rekwd-list-foo rekwd-list-bar rekwd-list-baz))
=> ((#<compiled regular expression: ^FOO: ;長いので略
;;; ↓みたいなのに色が付く
FOO: ho
BAR: b
BAZ: te

というわけで、compiled-regexp-keyword の list をいくつか取って、それをまとめて適用する関数。

(defun use-regexp-keyword-list (&rest rekwd-lists)
  "与えられた compile 済み regexp-keyword-list 全てを現在のバッファに適用する。"
  (when (or (local-variable-p 'regexp-keyword-list)
            (make-local-variable 'regexp-keyword-list))
    (setq regexp-keyword-list
          (apply 'append regexp-keyword-list rekwd-lists))))

こうやって使う。

(add-hook '*hoge-mode-hook*
          (partial use-regxp-keyword-list
                   *foo-rekwds*
                   *bar-rekwds*
                   *baz-rekwds*))

;; 参考
(defmacro partial (fn &rest args)
  (let ((more-args (gensym)))
    `(lambda (&rest ,more-args)
       (apply #',fn ,@args ,more-args))))

*1:list のまま渡すんじゃなくて、各要素を引数として渡すために regexp-keyword を compile-regexp-keyword に apply する lambda 式になってる