VSCode/TextMate语法高亮语法——匹配代码直到行尾

问题描述 投票:0回答:3

我正在编写一个 TextMate 语法来在 VSCode 中实现语法突出显示,以实现自定义的 Markdown 风格。我希望

@@$ 
之后同一行上的所有内容都突出显示为 Javascript。

这就是我想到的:

"majsdown_execute_statement": {
    "begin": "(.*?)(@@\\$)",
    "name": "test",
    "end": "(\\r\\n|\\r|\\n)",
    "beginCaptures": {
        "2": {
            "name": "keyword.control.majsdown"
        }
    },
    "patterns": [
        {
            "include": "source.js"
        }
    ]
},

几乎有效:

what happens

但我希望

@@$
部分始终突出显示为关键字。这是我想要的结果的模型(编辑后的图像):

what I would like

我尝试了很多不同的

"begin"
"end"
组合,并且我还尝试了许多嵌套模式,如下所示:

"patterns": [
    {
        "begin": "\\s",
        "while": "^(\\r\\n|\\r|\\n)",
        "patterns": [
            {
                "include": "source.js"
            }
        ]
    }
]

不幸的是,没有任何东西能提供我想要的结果。 怎样才能达到我想要的结果?

visual-studio-code syntax-highlighting grammar vscode-extensions textmate
3个回答
0
投票

要处理多行构造,我认为您还必须提供修改后的嵌入式语言(JavaScript)定义。最简单的方法是在 JavaScript 中添加

@@$
注释,这样就不会弄乱现有的结构。

我不知道 VScode 语法高亮。我将尝试使用 HighlightJs 来演示这个想法。它具有非常相似的定义语言的方式。
演示:以全页模式查看。

hljs.debugMode();

    // default code for the demo
    src.innerText = `
My custom markdown highlighted with custom rules.
Here is how javascript code looks:
@@$ function test()
@@$ {
@@$   // TODO: stuff
@@$   let rand = Math
@@$                  .random()
@@$                  .toFixed(2);
@@$ }
@@$ var string = "hello";
@@$ const string2 = \`some long
@@$ string\`;

Leave one empty line to get out of the code block.
Here is some more code:
@@$ var rand = Math.random();
@@$ console.log(rand);

We are out of the second code block now.
`;

    // define our markup language, say 'mdown'
    let langDef = {
      name: 'Mdown',
      aliases: ['mdown'],
      case_insensitive: true,
      contains: [
        {
          className: 'mscript',
          begin: /@@/,
          end: /\$/,
          keywords: { name: 'mscript' },
          contains: [],
          starts: {
            end: /^\s*$/, // end on empty line
            returnEnd: true,
            subLanguage: ['js'],  //embedded language
          },
        },
      ],
    };
    hljs.registerLanguage('mscript', () => langDef);

    // patch javascript multiline structures
    let js = hljs.getLanguage('javascript');
    for (let c of js.contains) {
      if (c.begin === "`") {  // handle templet literals
        c.contains.unshift({
          begin: /^@@/, 
          "relevance": 0,
          end: /\$/,
          contains: [],
          scope: 'mscripttag'
        })
      }
    }
    // console.log(js);

    // make '@@$' a comment :)
    // So it'll not mess existing styling
    js.contains.push(hljs.COMMENT(/@@/, /\$/, { scope: 'mscripttag', relevance: 10 }));


    // for demo update highlighted code on user input
    let handleChange = (event) => {
      let html = hljs.highlight(src.innerText, { language: 'mscript', ignoreIllegals: true }).value;
      code.innerHTML = html;
    };
    // javascript patching done

    document.addEventListener('DOMContentLoaded', handleChange);
    src.addEventListener('input', handleChange);
body { font-size: .8rem; }

.input {
  width: 46%;
  background-color: #eee;
  display: inline-block;
  overflow: auto;
}

.output {
  width: 50%;
  display: block;
  float: right;
  background-color: #ccc;
}

/* add extra theme for our tag @@$ */
.hljs { color: #bbb !important; }

.hljs-mscript,
.hljs-mscripttag { color: red; }
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/styles/base16/snazzy.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.4.0/highlight.min.js"></script>

<div>Edit below markdown code.</div>
<pre class="input"><div id="src" contenteditable></div></pre>

<pre class="output"><code id="code" class="javascript hljs">abcd</code></pre>

如果库不可用,输出如下:

enter image description here

在上面的代码中,我已将

@@$ <jscontent> \n
定义为 Markdown 语言定义中的标签。并且内容将根据嵌入语言JavaScript进行处理。
接下来,我修改了默认的 JS 语言定义并添加了
@@$
作为注释,因此它对现有语法无害。
现在我们只需要处理多行模板文字。在文字定义中,我添加了
@@$
作为文字的一部分,但具有不同的范围/名称/样式选项
msscripttag


我希望您能够在 TextMate 中为 VSCode 定义类似的语法。


0
投票

尝试使用匹配来代替...

"patterns": [
        {
          "name": "keyword.control.factory",
          "match": "(\\w|-)[^(]*"
        }
      ]

此代码匹配“(”字符之前的所有内容

所以你的代码看起来像这样:

"majsdown_execute_statement": {
    "patterns": [
        {
          "name": "keyword.control.majsdown",
          "match": "(?<=@@\$)\\w*"
        }
      ]
    }

你也可以试试

[^@@$]*(\\w)

尝试一下这里


0
投票

begin
/
while
将是正确的选择。
它是逐行工作的
您只需匹配
@@$
并像平常一样捕获它即可。

"majsdown_execute_statement": {
    "begin": "@@\\$",
    "while": "@@\\$",
    "captures": { "0": { "name": "keyword.control.majsdown" } },
    "name": "meta.embedded.block.javascript",
    "patterns": [ { "include": "source.js" } ]
}
© www.soinside.com 2019 - 2024. All rights reserved.