現行 (2) - 基本モード作成 ひな型 -

  • 独自の Emacs メジャーモード(major-mode)の作成方法.

  • 特に、どこを変更すればよいのか、を記載.


ひな型 ( 例: MAD-X )

  1;; ================================================== ;;
  2;; ===   madx mode                                === ;;
  3;; ================================================== ;;
  4
  5;; ---------------------------------------- ;;
  6;;    [1] MADX モード定義                   ;;
  7;; ---------------------------------------- ;;
  8(define-derived-mode madx-mode prog-mode "MAD-X"
  9  "Major mode for editing MAD-X files with comments"
 10  (setq-local indent-tabs-mode nil)
 11  (setq-local comment-start "//")            ;; comment
 12  (setq-local comment-start-skip "//+\\s-*") ;;
 13  (setq-local font-lock-defaults             ;; font-lock-defaults を case-insensitive 設定
 14              '((madx-font-lock-keywords)    ;; キーワード群
 15                nil t nil nil))              ;; keywords-only, case-fold,syntax-alist,syntax-begin
 16  (setq-local indent-line-function 'madx-indent-line)
 17  ;; -- highlight functions -- ;;
 18  (highlight-comments-override-in-madx)
 19  (highlight-at-variables-in-madx)
 20  (highlight-numbers-in-madx)
 21  (highlight-numbers-inside-strings-in-madx)
 22  (highlight-strings-in-madx)
 23  (highlight-operators-in-madx)
 24  (highlight-keywords-in-madx)
 25  )
 26
 27;; ---------------------------------------- ;;
 28;;    [2] 演算子記号 定義                   ;;
 29;; ---------------------------------------- ;;
 30(defface madx-operator-face
 31  '((t (:foreground "wheat" :weight bold)))
 32  "Face for MAD-X operators.")
 33
 34(defun highlight-operators-in-madx ()
 35  "Highlight common operators in MAD-X."
 36  (font-lock-add-keywords
 37   nil
 38   '(("[:=;+\\-*/]" (0 'madx-operator-face prepend)))))
 39
 40;; ---------------------------------------- ;;
 41;;    [3] キーワード ハイライト 定義        ;;
 42;; ---------------------------------------- ;;
 43;;    -- [3-1] フォントフェイスの定義  --   ;; 
 44(defface madx-keyword-face-1
 45  '((t (:foreground "orchid" :weight bold)))
 46  "Face for MAD-X controls commands.")
 47(defface madx-keyword-face-2
 48  '((t (:foreground "darkorange" :weight bold)))
 49  "Face for MAD-X fundamental commands.")
 50(defface madx-keyword-face-3
 51  '((t (:foreground "palegreen1" :weight bold)))
 52  "Face for MAD-X beamline components keywords.")
 53(defface madx-keyword-face-4
 54  '((t (:foreground "darkturquoise" :weight bold)))
 55  "Face for MAD-X parameters keywords.")
 56(defface madx-keyword-face-5
 57  '((t (:foreground "wheat" :weight bold)))
 58  "Face for MAD-X analysis and control keywords.")
 59
 60;;    -- [3-2] キーワード群の列挙  --       ;; 
 61(setq madx-keywords-1   ;; 1 - controls ;;
 62      '( "if" "elseif" "else" "while" "macro" "error" "ealign" "efcomp" "seterr" ":=" "->" ))
 63(setq madx-keywords-2   ;; 2 - commands ;;
 64      '("plot" "table" "tabindex" "tabstring" "twiss" "ibs" "line" "makethin" "aperture" "sixtrack" "dynap" "emit" "match" "endmatch" "vary" "constraint" "weight" "global" "gweight" "ptc_twiss" "ptc_printparametric" "ptc_normal" "select_ptc_normal" "ptc_track" "ptc_track_line" "ptc_create_universe" "ptc_create_layout" "ptc_read_errors" "ptc_move_to_layout" "ptc_align" "ptc_end" "ptc_track_end" "start" "run" "ptc_observe" "observe" "ptc_start" "ptc_setswitch" "ptc_knob" "ptc_setknobvalue" "match withptcknobs" "ptc_printframes" "ptc_select" "ptc_select_moment" "ptc_dumpmaps" "ptc_eplacement" "ptc_varyknob" "end_match" "ptc_moments" "ptc_setcavities" "ptc_setdebuglevel" "ptc_setaccel_method" "ptc_setexactmis" "ptc_setradiation" "ptc_settotalpath" "ptc_settime" "ptc_setfringe" "exit" "quit" "stop" "help" "show" "value" "option" "exec" "set" "system" "title" "use" "select" "assign" "call" "return" "print" "printf" "renamefile" "copyfile" "removefile" "create" "delete" "readtable" "readmytable" "write" "setvars" "setvars_lin" "fill" "shrink" "beam" "resbeam" "seqedit" "flatten" "cycle" "reflect" "install" "move" "remove" "replace" "extract" "endedit" "save" "dumpsequ" "savebeta" "coguess" "const" "eoption" "esave" "real" "lmdif" "migrad" "simplex" "jacobian" "use_macro" "correct" "usemonitor" "usekick" "csave" "setcorr" "coption" "sodd" "survey" "sxfread" "sxfwrite" "touschek" "track" "endtrack" ))
 65(setq madx-keywords-3    ;; 3 - beamlines ;;
 66      '("drift" "quadrupole" "sextupole" "octupole" "solenoid" "crabcavity" "rfcavity" "dipedge" "multipole" "collimator" "ecollimator" "rcollimator" "yrotation" "srotation" "translation" "changeref" "marker" "rbend" "sbend" "hkicker" "vkicker" "kicker" "tkicker" "elseparator" "hmonitor" "vmonitor" "monitor" "instrument" "placeholder" "beambeam" "matrix" "nllens" "rfmultipole"))
 67(setq madx-keywords-4    ;; 4 - parameters ;;
 68      '("file" "sequence" "endsequence" "refer" "particle" "energy" "flag" "haxis" "vaxis" "column" "betx" "bety" "positron" "electron" "proton" "antiproton" "posmuon" "negmuon" "ion" "pi" "twopi" "degrad" "raddeg" "e" "emass" "pmass" "nmass" "mumass" "clight" "qelect" "hbar" "erad" "prad" "true" "false" "simple" "collim" "teapot" "hybrid" "entry" "centre" "exit" "circle" "rectangle" "ellipse" "lhcscreen" "marguerite" "rectellipse" "racetrack" "octagon" "terminal"))
 69(setq madx-keywords-5    ;; 5 - math ;;
 70      '("sqrt" "log" "log10" "exp" "sin" "cos" "tan" "asin" "acos" "atan" "sinh" "cosh" "tanh" "sinc" "abs" "erf" "erfc" "floor" "ceil" "round" "ranf" "gauss" "tgauss" "flat5" "flat56"))
 71
 72;;    -- [3-3] キーワードとフェイスを対応 (case-insensitive)  --  ;;
 73(defvar madx-font-lock-keywords
 74  `((,(regexp-opt madx-keywords-1 'words) . 'madx-keyword-face-1)
 75    (,(regexp-opt madx-keywords-2 'words) . 'madx-keyword-face-2)
 76    (,(regexp-opt madx-keywords-3 'words) . 'madx-keyword-face-3)
 77    (,(regexp-opt madx-keywords-4 'words) . 'madx-keyword-face-4)
 78    (,(regexp-opt madx-keywords-5 'words) . 'madx-keyword-face-5)))
 79
 80
 81;; ---------------------------------------- ;;
 82;;    [4] @var #var  (マクロ記号)           ;;
 83;; ---------------------------------------- ;;
 84(defface at-variables-face-in-madx
 85  '((t (:foreground "orange" :weight bold)))
 86  "Face for @var identifiers inside strings.")
 87
 88(defun highlight-at-variables-in-madx ()
 89  "Highlight @variable (#variable) patterns inside strings."
 90  (font-lock-add-keywords
 91   nil
 92   '(("[@#][a-zA-Z0-9_.]+"
 93      (0 'at-variables-face-in-madx prepend)))))
 94
 95;; ---------------------------------------- ;;
 96;;    [5] 文字列 ハイライト                 ;;
 97;; ---------------------------------------- ;;
 98(defface strings-face-in-madx
 99  '((t (:foreground "BurlyWood" :weight normal)))
100  "Custom face for strings in madx-mode")
101
102(defun highlight-strings-in-madx ()
103  "Highlight strings in MADX with custom face."
104  (font-lock-add-keywords
105   nil
106   '(("\"\\([^\"\\]\\|\\\\.\\)*\""
107      (0 'strings-face-in-madx prepend)))))
108
109;; ---------------------------------------- ;;
110;;     [6] 数字  ハイライト                 ;;
111;; ---------------------------------------- ;;
112(defface numbers-face-in-madx
113  '((t (:foreground "Cyan" :weight normal)))
114  "Face for numbers in MADX.")
115
116(defun highlight-numbers-in-madx ()
117  "Highlight numbers in MADX with a custom face."
118  (font-lock-add-keywords
119   nil
120   '(("\\(?:^\\|[^a-zA-Z0-9_.]\\)\\(-?[0-9]+\\(?:\\.[0-9]+\\)?\\(?:[eE][-+]?[0-9]+\\)?\\)"
121      (1 'numbers-face-in-madx prepend)))))
122
123(defun highlight-numbers-inside-strings-in-madx ()
124  "Highlight numbers even inside strings."
125  (font-lock-add-keywords
126   nil
127   '(("\"[^\"]*?\\([0-9]+\\(?:\\.[0-9]+\\)?\\(?:[eE][-+]?[0-9]+\\)?\\)[^\"]*?\""
128      (1 'numbers-face-in-madx prepend)))))
129
130(defun highlight-comments-override-in-madx ()
131  "Forcefully highlight comments to override other face rules."
132  (font-lock-add-keywords
133   nil
134   '(("//\\(.*\\)$"  ; キャプチャグループ1に色をつける
135      (0 'font-lock-comment-face prepend)))))
136
137
138;; ---------------------------------------- ;;
139;;     [7] フックする拡張子 の設定          ;;
140;; ---------------------------------------- ;;
141(add-to-list 'auto-mode-alist '("\\.madx\\'" . madx-mode))
142
143;; ---------------------------------------- ;;
144;;     [8] インデント                       ;;
145;; ---------------------------------------- ;;
146;; --- 全部スペースでインデント         --- ;;
147(add-hook 'javascript-mode-hook '(lambda() (setq indent-tabs-mode nil)))
148
149;; --- 全部スペースでインデント         --- ;;
150(defun madx-inside-sequence-p ()
151  "Return non-nil if the current line is inside a SEQUENCE...ENDSEQUENCE block."
152  (save-excursion
153    (let ((seq-pos nil)
154          (endseq-pos nil))
155      ;; 現在行より前の SEQUENCE を探す
156      (when (re-search-backward "^[ \t]*SEQUENCE\\b" nil t)
157        (setq seq-pos (point)))
158      (goto-char (point-at-bol))
159      ;; 現在行より後の ENDSEQUENCE を探す
160      (when (re-search-forward "^[ \t]*ENDSEQUENCE\\b" nil t)
161        (setq endseq-pos (point)))
162      ;; どちらも見つかり、かつ現在位置がその間なら t
163      (and seq-pos endseq-pos
164           (> endseq-pos (point))
165           (< seq-pos (point))))))
166
167(defun madx-indent-line ()
168  "Indent current line if inside SEQUENCE...ENDSEQUENCE block."
169  (interactive)
170  (let ((indent (if (madx-inside-sequence-p) tab-width 0)))
171    (save-excursion
172      (beginning-of-line)
173      (delete-horizontal-space)
174      (indent-to indent))
175    (when (looking-back "^[ \t]*" (line-beginning-position))
176      (back-to-indentation))))
177
178;; ---------------------------------------- ;;
179;;         provide                          ;;
180;; ---------------------------------------- ;;
181(provide 'madx-mode)

作成の要点

[1] モード定義部分

  • define-derived-mode より、 prog-mode 等から派生モードを作成.

  • コメント記号を // などから変更

  • highlight 関数を増やした場合、追加.

[2] 演算子記号 ハイライト

  • 含める 演算子記号 を変更

[3] キーワード ハイライト

  • [3-1] : フォントフェイス = と説明書きを変更

  • [3-2] : キーワード群 = キーワードを小文字 で列挙 ( case-insensitive にしている.)

  • [3-3] : キーワードとフェイスを対応.

[4] @var マクロ記号 ハイライト

  • マクロ指定にする記号( @var1 などをマクロとして、後ほど置換するのに使用 )を変更

[5] 文字列ハイライト

[6] 数字ハイライト

[7] 拡張子

  • フックする拡張子を指定

[8] インデント

  • 現状、うまく機能していない(工事必要).


まとめ

  • 上記項目の変更により、手早くハイライトシンタックスを作成する.