generic mode (ジェネリックモード) について

  • generic mode (一般emacsモード) である.

  • 以下のことができる.

    • キーワード毎に、色付きのフォントロックを指定できる

    • モード起動時に関数を起動して、好きな設定を読み込んだりできる.

    • 拡張子に自動的に判別して、フックできる.

    • タブサイズやルールなどを指定できる.

    • スニペットを登録・呼び出しできる.

generic mode の作成

generic mode のサンプル (elmer.el)
;;; ========================================================================= ;;;
;;;   Elmer-mode ( .sif )       to edit .sif parameter files in Elmer         ;;;
;;; ========================================================================= ;;;
;; see https://uid0130.blogspot.com/2014/05/emacsgeneric-mode.html 

;; ------------------------------------------------------------------- ;;
;; ---  [1]   call generic-x mode.                                 --- ;;
;; ------------------------------------------------------------------- ;;
(require 'generic-x)

;; ------------------------------------------------------------------- ;;
;; ---  [2] リストインターリーブ関数の定義                          -- ;;
;; ------------------------------------------------------------------- ;;
(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))))

;; ------------------------------------------------------------------- ;;
;; ---  [3] リストインターリーブ関数を使用したキーワード群の定義    -- ;;
;; ------------------------------------------------------------------- ;;
;; -- 変数型群01 -- ;;
(defvar elmer-type-keywords01
  (apply 'concat (list-interleave
                  '("[Ss]tring" "[Rr]eal" "[Ll]ogical" "[Ii]nteger")
                  '() "\\|")))
;; -- 変数型群02 -- ;;
(defvar elmer-type-keywords02
  (apply 'concat (list-interleave
                  '("[Tt]rue" "[Ff]alse" "[Nn]one")
                  '() "\\|")))

;; --  演算子群01 -- ;;
(defvar elmer-operator-keywords01
  (apply 'concat (list-interleave
                  '("=" "(" ")" "<" ">")
                  '() "\\|")))
;; --  演算子群02 -- ;;
(defvar elmer-operator-keywords02
  (apply 'concat (list-interleave
                  '("#" "@.*" "\\$.*" )
                  '() "\\|")))
;; --  演算子群03 -- ;;
(defvar elmer-operator-keywords03
  (apply 'concat (list-interleave
                  '("!")
                  '() "\\|")))

;; --  セクション表題 01 -- ;;
(defvar elmer-section-keywords01
  (apply 'concat (list-interleave
                  '("^[Ee][Nn][Dd]" "^[Hh]eader" "^[Ss]imulation" "^[Cc]onstants"
                    "^[Ss]olver" "^[Bb]ody" "^[Ee]quation" "^[Mm]aterial"
                    "^[Bb]oundary [Cc]ondition" "^[Ii]nitial Condition" "^[Bb]ody [Ff]orce"
                    )
                  '() "\\|")))


;; ------------------------------------- ;;
;; --- [2]   define font-lock face   --- ;;
;; ------------------------------------- ;;
(defface font-lock-operator01
  '((t (:foreground "green")))  "Comment:: Font faces for operator01" )

(defface font-lock-operator02
  '((t (:foreground "pink")))   "Comment:: Font faces for operator02" )

(defface font-lock-operator03
  '((t (:foreground "blue1")))  "Comment:: Font faces for operator03" )

(defface font-lock-type01
  '((t (:foreground "grey")))   "Comment:: Font faces for type"       )

(defface font-lock-type02
  '((t (:foreground "orange"))) "Comment:: Font faces for type"       )

(defface font-lock-section01
  '((t (:foreground "yellow")))   "Comment:: Font faces for section"    )

(define-generic-mode 'elmer-mode    ;; name of the mode to create
  '("!!" "#" )                      ;; comments start with '!!'
  kw_list_elmer_mode                ;; Main Highlights. Defined as below ( must be unique name. )
  `(                                ;; back-quatation is needed here !!!!
    ;; Detailed Highlights..
    (,elmer-type-keywords01     . 'font-lock-type01    )
    (,elmer-type-keywords02     . 'font-lock-type02    )
    (,elmer-operator-keywords01 . 'font-lock-operator01)
    (,elmer-operator-keywords02 . 'font-lock-operator02)
    (,elmer-operator-keywords03 . 'font-lock-operator03)
    (,elmer-section-keywords01  . 'font-lock-section01 )
    )
  '("\\.sif$")                      ;; files for which to activate this mode 
  (setq-default tab-width 2 indent-tabs-mode nil) ;; other functions to call
  "A mode for elmer .sif files"     ;; doc string for this mode
  )

(setq kw_list_elmer_mode '( "define" "include" "postProcess" "filepath" ) )

(provide 'elmer-mode)

generic-x パッケージの呼び出し

  • generic-xパッケージを呼び出す.

    (require 'generic-x)
    

リストインタリーブ関数の定義

  • 文字列リストを展開する関数(リストインタリーブ関数)を定義する.

  • 次のキーワード群の定義にて使用する.

キーワード群の定義

  • 前述のリストインタリーブ関数を用いて、キーワード群を列挙する.

  • キーワード群は、例えば、 演算子 , キーワード , 括弧 , メタ命令 など.

  • リストインタリーブ関数の引数部 "'("[Tt]rue" "[Ff]alse" "[Nn]one")" を変更するだけ.

    • 正規表現でかけるので、大文字・小文字区別[Aa]や、行頭正規表現"^"などを使用できる.

    • 正規表現で使用する文字列 "" "." "*" "+" "?" "{}" "()" "{}" "[]" "^" "$" "-" "|" "/" には、エスケープシーケンスが必要.

    • エスケープ文字は "\" を使う ( e.g. "\.", "\$", "\$.*" etc. ).

フォントフェイスの作成

  • deffaceにて、faceを作成する.

  • 基本的には、foreground 文字色を変更すれば足りるはずである.

generic mode の定義

  • define-generic-mode 'elmer-mode にて、モードを定義する. (ここでは、elmer-mode を定義).

  • 指定箇所は、以下である.

    1. コメント文字

    2. メインのキーワード(赤とか、既に決まっている配色でキーワードが色つけられる).

    3. 詳細のキーワード設定 ( [重要] 文頭はバッククオートで始める:リストインタリーブ関数使用のため )

    4. 拡張子の設定: 正規表現で指定 "\.py$" など

    5. 起動時の実行関数:例のように与えても良いし、( my-function )のように、別途定義した関数を呼んでもよい.

    6. generic mode呼び出し時に表示されるコメント.:なんでもよい.

  • キーワードリスト(setqを使用して文字リストとして定義)は最後に付記してある.

mode の provide

  • おまじない.以下命令でprovideする.:

    (provide 'elmer-mode)
    

まとめ

  • 基本的には、色とキーワードリスト、最初に実行する関数(タブ幅など)を指定すれば良い.