【问题标题】:Emacs Major Mode - Keywords "special char" and "one char" KeywordsEmacs 主要模式 - 关键字“特殊字符”和“单字符”关键字
【发布时间】:2020-10-07 18:11:21
【问题描述】:

我想为 emacs 编写一个主要模式,它应该对 mml(音乐宏语言)关键字进行语法突出显示。我遵循了本教程: http://ergoemacs.org/emacs/elisp_syntax_coloring.html

这是我当前的代码 (在x-events下还有占位符,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) 如何指定找到这些单字母关键字? (最好和数字一起,但不是必须的)。

【问题讨论】:

    标签: emacs syntax-highlighting


    【解决方案1】:

    这两个问题都源于同一个问题:它与您构造正则表达式的方式有关:

    (regexp-opt x-blabla 'words)
    

    问题在于'words 参数。这样做是将生成的正则表达式包含在 \&lt; ... \&gt; 对中。根据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 意味着什么?那是模式相关的。事实上,每个主要模式都定义了自己的syntax-table,这是字符到语法代码的映射。有许多预定义的类,其中之一是"w",它将一个字符定义为一个词的组成部分。通常,基于文本的模式会将字母 a...zA...Z 定义为具有语法代码 "w",但可能还有其他字符(例如连字符 -)。

    好的,回到手头的问题。例如x-keywords,根据您的定义,生成的x-keywords-regexp 是:

    "\\<\\(#\\(?:author\\|comment\\|\\(?:gam\\|titl\\)e\\)\\)\\>"
    

    (请注意,在字符串内部,反斜杠是用于转义其他特殊字符的特殊字符,例如,\n\t。因此,为了编码一个简单的反斜杠本身,您必须用另一个反斜杠引用它。)

    如上所述,我们在正则表达式的开头和结尾分别看到\&lt;\&gt;(或者,用字符串的说法:"\\&lt;""\\&gt;")。但是,正如我们刚刚了解到的,为了让这个正则表达式匹配,潜在匹配的第一个和最后一个字符都需要具有单词组成语法。

    这些字母不重要,但让我们通过键入 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
    ...
    

    (显然被截断了。)

    你有它! # 字符具有单词组成语法,它被视为标点符号。

    但我们可以通过将以下行放入主模式的定义中来改变这一点:

    (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\\}\\>"))
    

    注意字符串参数开头的"\\|",这是替代匹配的正则表达式语法。

    【讨论】:

    • 哇,多么详细而好的答案。这让很多事情都清楚了。非常感谢你,我很感激!
    猜你喜欢
    • 1970-01-01
    • 2011-12-07
    • 1970-01-01
    • 1970-01-01
    • 2020-04-25
    • 2014-02-01
    • 2018-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多