Я выделю простой основной режим для выделения <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
. Есть два
достаточно хорошие способы сопоставления многострочных конструкций:
регулярное выражение, которое будет соответствовать между строками и соответствием
функция. Я приведу примеры обоих. Этот список ключевых слов содержит
регулярное выражение для сопоставления <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.")
Первый элемент в списке прост: регулярное выражение
и лицо для выделения совпадений этого регулярного выражения.
Второй выглядит немного сложнее, но может быть обобщен
указать разные лица для разных групп, определенных в
сопоставить данные, указанные функцией. Здесь мы просто выделяем
группа ноль (полное совпадение), используя 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 ...
дает начало и конец
нулевая группа, первая группа и так далее. Здесь мы даем только ограничения на
весь блок, который был сопоставлен, но вы могли бы сделать что-то еще
сложные, такие как установка различных граней для тегов и
содержание.
Если вы объедините весь этот код в один файл и запустите
M-x test-mode
, это должно работать для выделения этих двух типов
блоков. Хотя я считаю, что это делает работу, если есть более
эффективный или правильный способ сделать это, я также хотел бы
знаю также.