【问题标题】:VSCode/TextMate syntax highlighting grammar -- matching code until end of lineVSCode/TextMate 语法高亮语法——匹配代码直到行尾
【发布时间】:2021-12-28 16:27:54
【问题描述】:

我正在编写一个 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"
        }
    ]
},

几乎有效:

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

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

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

不幸的是,没有什么能提供我想要的结果。 我怎样才能达到我想要的结果?

【问题讨论】:

  • 你可以使用积极的后视吗? (?<=@@\\$)

标签: visual-studio-code syntax-highlighting grammar vscode-extensions textmate


【解决方案1】:

要处理多行结构,我认为您还必须提供修改后的嵌入式语言 (JavaScript) 定义。最简单的方法是在 JavaScript 中将 @@$ 设为注释,这样就不会弄乱现有的结构。

我不知道 VScode syntax highlighting。我将尝试使用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>

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

在上面的代码中,我将@@$ &lt;jscontent&gt; \n 定义为我们的markdown 语言定义中的标签。并且内容将根据嵌入的语言 JavaScript 进行处理。
接下来我修改了默认的 JS 语言定义并添加了 @@$ 作为注释,这样它就不会对现有语法造成伤害。
现在我们只需要处理多行的模板文字。在文字定义中,我添加了@@$ 作为文字的一部分,但具有不同的范围/名称/样式选项msscripttag

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

【讨论】:

    【解决方案2】:

    尝试使用匹配...

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

    此代码匹配所有内容,直到一个“(”字符

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

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

    你也可以试试[^@@$]*(\\w)

    试试看here

    【讨论】:

    • 我更新了答案,粘贴时出错了......
    猜你喜欢
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 2013-09-06
    相关资源
    最近更新 更多