首页 > 解决方案 > 如何在 TextMate 语言定义中嵌入另一个语法对象,tmLanguage

问题描述

我试图在 VS Code 中支持 Clojure 的忽略文本形式, #_, (一种注释),它使用 tmLanguage 进行语法定义。由于使用 禁用代码块很常见#_,因此我希望禁用的代码块保留其语法突出显示并仅将其斜体化,以指示其状态。

但是我缺乏使用 tmLanguage 的技能似乎阻止了我。这是失败的尝试之一(的片段cson):

  'comment-constants':
    'begin': '#_\\s*(?=\'?#?[^\\s\',"\\(\\)\\[\\]\\{\\}]+)'
    'beginCaptures':
      '0':
        'name': 'punctuation.definition.comment.begin.clojure'
    'end': '(?=[\\s\',"\\(\\)\\[\\]\\{\\}])'
    'name': 'meta.comment-expression.clojure'
    'patterns':
      [
        {
          'include': '#constants'
        }
      ]

通过constants定义一些 Clojure 常量对象,例如keyword

  'keyword':
    'match': '(?<=(\\s|\\(|\\[|\\{)):[\\w\\#\\.\\-\\_\\:\\+\\=\\>\\<\\/\\!\\?\\*]+(?=(\\s|\\)|\\]|\\}|\\,))'
    'name': 'constant.keyword.clojure'

我想要发生的是constants定义将在注释“内部”使用。对于关键字,我有这个(失败的)规范:

  it "tokenizes keywords", ->
    tests =
      "meta.expression.clojure": ["(:foo)"]
      "meta.map.clojure": ["{:foo}"]
      "meta.vector.clojure": ["[:foo]"]
      "meta.quoted-expression.clojure": ["'(:foo)", "`(:foo)"]
      "meta.comment-expression.clojure": ["#_:foo"]

    for metaScope, lines of tests
      for line in lines
        {tokens} = grammar.tokenizeLine line
        expect(tokens[1]).toEqual value: ":foo", scopes: ["source.clojure", metaScope, "constant.keyword.clojure"]

(该列表中的最后一个测试)。它失败并显示此消息:

Expected
{  value : ':foo',
  scopes : [ 'source.clojure', 'meta.comment-expression.clojure' ] }
to equal
{  value : ':foo',
  scopes : [ 'source.clojure', 'meta.comment-expression.clojure', 'constant.keyword.clojure' ] }.

这意味着我没有得到constant.keyword.clojure适当的范围,因此对我来说没有关键字着色。

任何人都知道如何做到这一点?

标签: syntaxvisual-studio-codetokenizevscode-extensionstmlanguage

解决方案


您的正则表达式以lookbehind 开头,要求关键字之前keyword必须有一个空格([或字符。from不符合该要求{_#_

(?<=(\\s|\\(|\\[|\\{))

您可以简单地添加_到允许的字符列表中:

(?<=(\\s|\\(|\\[|\\{|_))

请注意,这对于您的测试用例仍然无法正常工作,因为最后有类似的前瞻。"#_:foo"您可能会$在那里允许,使匹配成为可选,或更改测试用例。


推荐阅读