<style>
(CSS)および
<script>
(JavaScriptなど)ブロックを強調表示するための単純なメジャーモードの概要を説明します。複数行のフォントロックを適切に機能させるには、まず、に設定
font-lock-multiline
しt
て追加する関数を記述し
font-lock-extend-region-functions
、関連する検索領域を拡張してより大きなテキストブロックを含めることにより、フォントロックを有効にする必要があります。次に、複数行のマッチャー(正規表現または関数)を記述し、それらをに追加する必要がありますfont-lock-defaults
。
これは、フォントロックキーワードリスト(ここでは、test-font-lock-keywords
)に名前を付け、複数行のフォントロックを有効にし、領域拡張機能を追加
する基本的なメジャーモード定義ですtest-font-lock-extend-region
。
(define-derived-mode test-mode html-mode "Test"
"Major mode for highlighting JavaScript and CSS blocks."
;; Basic font lock
(set (make-local-variable 'font-lock-defaults)
'(test-font-lock-keywords))
;; Multiline font lock
(set (make-local-variable 'font-lock-multiline) t)
(add-hook 'font-lock-extend-region-functions
'test-font-lock-extend-region))
領域拡張関数は次のようになります。
(defun test-font-lock-extend-region ()
"Extend the search region to include an entire block of text."
;; Avoid compiler warnings about these global variables from font-lock.el.
;; See the documentation for variable `font-lock-extend-region-functions'.
(eval-when-compile (defvar font-lock-beg) (defvar font-lock-end))
(save-excursion
(goto-char font-lock-beg)
(let ((found (or (re-search-backward "\n\n" nil t) (point-min))))
(goto-char font-lock-end)
(when (re-search-forward "\n\n" nil t)
(beginning-of-line)
(setq font-lock-end (point)))
(setq font-lock-beg found))))
この関数は、検索領域の開始位置と終了位置を含むグローバル変数font-lock-beg
とを
調べ、領域を拡張してテキストのブロック全体(空白行またはで区切る)を含めます。font-lock-end
"\n\n"
Emacsがより大きな地域で一致を検索するようになったので、リストを設定する必要がありtest-font-lock-keywords
ます。複数行の構成を一致させるには、2つの合理的に良い方法があります。行間で一致する正規表現と一致する関数です。両方の例を示します。このキーワードリストには、ブロックを照合するための正規表現<style>
と、ブロックを照合するための関数が含まれてい<script>
ます。
(defvar test-font-lock-keywords
(list
(cons test-style-block-regexp 'font-lock-string-face)
(cons 'test-match-script-blocks '((0 font-lock-keyword-face)))
)
"Font lock keywords for inline JavaScript and CSS blocks.")
リストの最初の項目は単純です。正規表現と、その正規表現の一致を強調表示するための面です。2つ目は少し複雑に見えますが、関数で指定された一致データで定義されたグループごとに異なる面を指定するように一般化できます。ここでは、を使用してグループゼロ(一致全体)を強調表示しfont-lock-keyword-face
ます。(これらのマッチャーに関連するドキュメントは、Emacsマニュアルの検索ベースのフォント化セクションにあります。)
<style>
ブロックを照合するための基本的な正規表現は次のとおりです。
(defconst test-style-block-regexp
"<style>\\(.\\|\n\\)*</style>"
"Regular expression for matching inline CSS blocks.")
改行と一致しない\n
ため、内側のグループに入れる必要があることに注意してください。.
一方、マッチング関数は
<script>
、ポイントから単一の指定された引数までの領域で最初のブロックを探す必要がありlast
ます。
(defun test-match-script-blocks (last)
"Match JavaScript blocks from the point to LAST."
(cond ((search-forward "<script" last t)
(let ((beg (match-beginning 0)))
(cond ((search-forward-regexp "</script>" last t)
(set-match-data (list beg (point)))
t)
(t nil))))
(t nil)))
この関数は、一致データを設定します。これは
begin-0 end-0 begin-1 end-1 ...
、0番目のグループ、最初のグループなどの開始と終了を示すフォームのリストです。ここでは、一致したブロック全体にのみ境界を設定しますが、タグとコンテンツに異なる面を設定するなど、より洗練された方法を実行できます。
このすべてのコードを1つのファイルにまとめて実行すると
M-x test-mode
、これら2つのタイプのブロックを強調表示するために機能するはずです。これでうまくいくと思いますが、もっと効率的または適切な方法があれば、私も知りたいと思います。