Emacs 主要模式 - 关键字 "special char" 和 "one char" 关键字
Emacs Major Mode - Keywords "special char" and "one char" Keywords
我想为 emacs 编写一个主要模式,它应该为 mml(音乐宏语言)关键字进行语法高亮显示。我遵循了本教程:
http://ergoemacs.org/emacs/elisp_syntax_coloring.html
这是我当前的代码
(x-events下还有placeholders,x-functions我还没有调整从教程接过来):
;;
;; to install this mode, put the following lines
;; (add-to-list 'load-path "~/.emacs.d/lisp/")
;; (load "mml-mode.el")
;; into your init.el file and activate it with
;; ALT+X mml-mode RET
;;
;; create the list for font-lock.
;; each category of keyword is given a particular face
(setq mml-font-lock-keywords
(let* (
;; define several category of keywords
(x-keywords '("#author" "#title" "#game" "#comment"))
(x-types '("&" "?" "/" "=" "[" "]" "^" "<" ">"))
(x-constants '("w" "t" "o" "@" "v" "y" "h" "q" "p" "n" "*" "!"))
(x-events '("@" "@@" "ooo" "oooo"))
(x-functions '("llAbs" "llAcos" "llAddToLandBanList"
"llAddToLandPassList"))
;; generate regex string for each category of keywords
(x-keywords-regexp (regexp-opt x-keywords 'words))
(x-types-regexp (regexp-opt x-types 'words))
(x-constants-regexp (regexp-opt x-constants 'words))
(x-events-regexp (regexp-opt x-events 'words))
(x-functions-regexp (regexp-opt x-functions 'words)))
`(
(,x-types-regexp . font-lock-type-face)
(,x-constants-regexp . font-lock-constant-face)
(,x-events-regexp . font-lock-builtin-face)
(,x-functions-regexp . font-lock-function-name-face)
(,x-keywords-regexp . font-lock-keyword-face)
)))
;;;###autoload
(define-derived-mode mml-mode text-mode "mml mode"
"Major mode for editing mml (Music Macro Language)"
;; code for syntax highlighting
(setq font-lock-defaults '((mml-font-lock-keywords))))
;; add the mode to the `features' list
(provide 'mml-mode)
但是现在有两个问题:
首先,我有几个以 #
开头的关键字(例如 #author
)。但是 #
似乎不起作用,因为如果我把它去掉,它就起作用了。
(x-keywords '("#author"))
不起作用。
(x-keywords '("author"))
有效,但 #
没有颜色。 @
也会出现同样的问题。也可能与其他人一起工作,但我会尝试让他们一个一个地工作。
其次,一个关键词好像至少需要两个字母。
(x-keywords '("o"))
不起作用。
(x-keywords '("oo"))
有效。
但我有几个“关键字”,后面只有一个字母和两个(任意)十六进制数字 (0-F)(例如 o7D
)
如何指定找到这些一个字母的关键字? (最好和数字一起,但不是必须的)。
这两个问题都源于同一个问题:它与构造正则表达式的方式有关:
(regexp-opt x-blabla 'words)
问题是 'words
参数。这样做的目的是将生成的正则表达式包含在 \<
... \>
对中。根据Emacs manual,这些特殊字符类定义如下:
\<
matches the empty string, but only at the beginning of a word.
‘\<’ matches at the beginning of the buffer only if a word-constituent
character follows.
\>
matches the empty string, but only at the end of a word.
‘\>’ matches at the end of the buffer only if the contents end with a
word-constituent character.
现在,“单词的开头” 对 Emacs 意味着什么?即mode-dependent。事实上,每个主要模式都定义了自己的 syntax-table ,它是字符到语法代码的映射。有许多pre-defined 类,其中之一是"w"
,它将字符定义为单词的组成部分。通常,text-based 模式会将字母 a...z
和 A...Z
定义为具有语法代码 "w"
,但可能还有其他字符(例如连字符 -
) .
好了,回到手头的问题。因为,假设 x-keywords
,根据您的定义,得到的 x-keywords-regexp
是:
"\<\(#\(?:author\|comment\|\(?:gam\|titl\)e\)\)\>"
(请注意,在字符串内部,反斜杠是用于转义其他特殊字符的特殊字符,例如 \n
或 \t
。所以为了编码一个简单的 反斜杠本身,你必须用另一个反斜杠引用它。)
如上所述,我们在正则表达式的开头和结尾看到 \<
和 \>
(或者用字符串的说法:"\<"
和 "\>"
)分别。但是,正如我们刚刚了解到的,为了使这个正则表达式匹配,潜在匹配的第一个和最后一个字符都需要具有 word-constituent 语法。
这些字母并不重要,但让我们通过键入 C-h s:
来检查 #
的语法代码
The parent syntax table is:
C-@ .. C-h . which means: punctuation
TAB .. C-j which means: whitespace
C-k . which means: punctuation
C-l .. RET which means: whitespace
C-n .. C-_ . which means: punctuation
SPC which means: whitespace
! . which means: punctuation
" " which means: string
# . which means: punctuation
...
(明显被截断了。)
给你! #
字符 没有 单词构成语法,它被认为是标点符号。
但我们可以通过将以下行放入您的 major-mode 的定义中来更改它:
(modify-syntax-entry ?# "w" mml-mode-syntax-table)
?#
是字符在 Emacs lisp 中的编码方式(想想 C 中的 '#'
)。
关于你问题的第二部分,为了匹配 o75
之类的东西,我们必须做类似的事情:将所有数字定义为单词成分:
(modify-syntax-entry '(?0 . ?9) "w" mml-mode-syntax-table)
但是,我们还需要编写一个合适的正则表达式来匹配这些关键字。正则表达式本身并不难:
"o[0-9A-F]\{2\}"
但是,放在哪里呢?由于它已经是一个正则表达式,我们不能简单地将它添加到 x-keywords
,因为那是一个简单字符串列表。
但是,我们可以将它连接到 x-keywords-regexp
,方法是将上面代码中的相应行更改为如下所示:
(x-keywords-regexp (concat (regexp-opt x-keywords 'words)
"\|\<[o][0-9A-F]\{2\}\>"))
注意字符串参数开头的 "\|"
,这是替代匹配的正则表达式语法。
我想为 emacs 编写一个主要模式,它应该为 mml(音乐宏语言)关键字进行语法高亮显示。我遵循了本教程:
http://ergoemacs.org/emacs/elisp_syntax_coloring.html
这是我当前的代码 (x-events下还有placeholders,x-functions我还没有调整从教程接过来):
;;
;; to install this mode, put the following lines
;; (add-to-list 'load-path "~/.emacs.d/lisp/")
;; (load "mml-mode.el")
;; into your init.el file and activate it with
;; ALT+X mml-mode RET
;;
;; create the list for font-lock.
;; each category of keyword is given a particular face
(setq mml-font-lock-keywords
(let* (
;; define several category of keywords
(x-keywords '("#author" "#title" "#game" "#comment"))
(x-types '("&" "?" "/" "=" "[" "]" "^" "<" ">"))
(x-constants '("w" "t" "o" "@" "v" "y" "h" "q" "p" "n" "*" "!"))
(x-events '("@" "@@" "ooo" "oooo"))
(x-functions '("llAbs" "llAcos" "llAddToLandBanList"
"llAddToLandPassList"))
;; generate regex string for each category of keywords
(x-keywords-regexp (regexp-opt x-keywords 'words))
(x-types-regexp (regexp-opt x-types 'words))
(x-constants-regexp (regexp-opt x-constants 'words))
(x-events-regexp (regexp-opt x-events 'words))
(x-functions-regexp (regexp-opt x-functions 'words)))
`(
(,x-types-regexp . font-lock-type-face)
(,x-constants-regexp . font-lock-constant-face)
(,x-events-regexp . font-lock-builtin-face)
(,x-functions-regexp . font-lock-function-name-face)
(,x-keywords-regexp . font-lock-keyword-face)
)))
;;;###autoload
(define-derived-mode mml-mode text-mode "mml mode"
"Major mode for editing mml (Music Macro Language)"
;; code for syntax highlighting
(setq font-lock-defaults '((mml-font-lock-keywords))))
;; add the mode to the `features' list
(provide 'mml-mode)
但是现在有两个问题:
首先,我有几个以 #
开头的关键字(例如 #author
)。但是 #
似乎不起作用,因为如果我把它去掉,它就起作用了。
(x-keywords '("#author"))
不起作用。
(x-keywords '("author"))
有效,但 #
没有颜色。 @
也会出现同样的问题。也可能与其他人一起工作,但我会尝试让他们一个一个地工作。
其次,一个关键词好像至少需要两个字母。
(x-keywords '("o"))
不起作用。
(x-keywords '("oo"))
有效。
但我有几个“关键字”,后面只有一个字母和两个(任意)十六进制数字 (0-F)(例如 o7D
)
如何指定找到这些一个字母的关键字? (最好和数字一起,但不是必须的)。
这两个问题都源于同一个问题:它与构造正则表达式的方式有关:
(regexp-opt x-blabla 'words)
问题是 'words
参数。这样做的目的是将生成的正则表达式包含在 \<
... \>
对中。根据Emacs manual,这些特殊字符类定义如下:
\<
matches the empty string, but only at the beginning of a word.
‘\<’ matches at the beginning of the buffer only if a word-constituent
character follows.
\>
matches the empty string, but only at the end of a word.
‘\>’ matches at the end of the buffer only if the contents end with a
word-constituent character.
现在,“单词的开头” 对 Emacs 意味着什么?即mode-dependent。事实上,每个主要模式都定义了自己的 syntax-table ,它是字符到语法代码的映射。有许多pre-defined 类,其中之一是"w"
,它将字符定义为单词的组成部分。通常,text-based 模式会将字母 a...z
和 A...Z
定义为具有语法代码 "w"
,但可能还有其他字符(例如连字符 -
) .
好了,回到手头的问题。因为,假设 x-keywords
,根据您的定义,得到的 x-keywords-regexp
是:
"\<\(#\(?:author\|comment\|\(?:gam\|titl\)e\)\)\>"
(请注意,在字符串内部,反斜杠是用于转义其他特殊字符的特殊字符,例如 \n
或 \t
。所以为了编码一个简单的 反斜杠本身,你必须用另一个反斜杠引用它。)
如上所述,我们在正则表达式的开头和结尾看到 \<
和 \>
(或者用字符串的说法:"\<"
和 "\>"
)分别。但是,正如我们刚刚了解到的,为了使这个正则表达式匹配,潜在匹配的第一个和最后一个字符都需要具有 word-constituent 语法。
这些字母并不重要,但让我们通过键入 C-h s:
来检查#
的语法代码
The parent syntax table is:
C-@ .. C-h . which means: punctuation
TAB .. C-j which means: whitespace
C-k . which means: punctuation
C-l .. RET which means: whitespace
C-n .. C-_ . which means: punctuation
SPC which means: whitespace
! . which means: punctuation
" " which means: string
# . which means: punctuation
...
(明显被截断了。)
给你! #
字符 没有 单词构成语法,它被认为是标点符号。
但我们可以通过将以下行放入您的 major-mode 的定义中来更改它:
(modify-syntax-entry ?# "w" mml-mode-syntax-table)
?#
是字符在 Emacs lisp 中的编码方式(想想 C 中的 '#'
)。
关于你问题的第二部分,为了匹配 o75
之类的东西,我们必须做类似的事情:将所有数字定义为单词成分:
(modify-syntax-entry '(?0 . ?9) "w" mml-mode-syntax-table)
但是,我们还需要编写一个合适的正则表达式来匹配这些关键字。正则表达式本身并不难:
"o[0-9A-F]\{2\}"
但是,放在哪里呢?由于它已经是一个正则表达式,我们不能简单地将它添加到 x-keywords
,因为那是一个简单字符串列表。
但是,我们可以将它连接到 x-keywords-regexp
,方法是将上面代码中的相应行更改为如下所示:
(x-keywords-regexp (concat (regexp-opt x-keywords 'words)
"\|\<[o][0-9A-F]\{2\}\>"))
注意字符串参数开头的 "\|"
,这是替代匹配的正则表达式语法。