如何在 TextMate 语言定义、tmLanguage 中将语法对象嵌入另一个对象

How to embed a syntax object in another in TextMate language definitions, 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 范围,因此我没有关键字着色。

有人知道怎么做吗?

您的 keyword 正则表达式以后视开头,要求关键字前必须有一个空格、([{ 字符。来自 #__ 不符合该要求。

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

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

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

请注意,此 still wouldn't work 原样用于您的 "#_:foo" 测试用例,因为末尾有类似的前瞻性。您可以在那里允许 $,使匹配成为可选的,或者更改测试用例。