我正在编写一个 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"
}
]
}
]
不幸的是,没有任何东西能提供我想要的结果。 怎样才能达到我想要的结果?
要处理多行构造,我认为您还必须提供修改后的嵌入式语言(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>
如果库不可用,输出如下:
在上面的代码中,我已将
@@$ <jscontent> \n
定义为 Markdown 语言定义中的标签。并且内容将根据嵌入语言JavaScript进行处理。 @@$
作为注释,因此它对现有语法无害。@@$
作为文字的一部分,但具有不同的范围/名称/样式选项 msscripttag
。
尝试使用匹配来代替...
"patterns": [
{
"name": "keyword.control.factory",
"match": "(\\w|-)[^(]*"
}
]
此代码匹配“(”字符之前的所有内容
所以你的代码看起来像这样:
"majsdown_execute_statement": {
"patterns": [
{
"name": "keyword.control.majsdown",
"match": "(?<=@@\$)\\w*"
}
]
}
你也可以试试
[^@@$]*(\\w)
尝试一下这里
begin
/while
将是正确的选择。@@$
并像平常一样捕获它即可。
"majsdown_execute_statement": {
"begin": "@@\\$",
"while": "@@\\$",
"captures": { "0": { "name": "keyword.control.majsdown" } },
"name": "meta.embedded.block.javascript",
"patterns": [ { "include": "source.js" } ]
}