我正在尝试在html文件的脚本标签中为glsl片段着色器进行语法突出显示/着色。
即使我在Sublime Text中安装了所有相关的Shader Syntax packages,我仍然没有突出显示语法。我相信这些只能解决外部文件或非HTML文件的问题。但是我正在使用内部脚本标签。
有人碰到这个吗?
答案 0 :(得分:4)
事实上,在Sublime中,语法定义通常指的是基于外部条件的文件的特定类型:文件的扩展名,文件的第一行(例如bash shebang)或用户专门覆盖的,这是正确的自动检测。
一种语法有可能允许另一种语法暂时“控制”语法突出显示,但是这需要基础语法定义的作者有意识地做出决定。系统需要知道什么时候应该输入新的语法,什么时候应该退回到前一个语法,以及(最重要的是)在两者之间实际使用什么语法。
例如,Sublime附带了自己适用于.js
文件的JavaScript语法,但附带的HTML语法还包括允许适当的<script>
标签内容的规则通过将控制权交给该语法将其突出显示为JavaScript,并在出现</script>
标记时将其取回。
因此,在您的情况下,您想做的事在技术上是可能的,但可以说“开箱即用”是行不通的。您需要一种HTML语法,该语法应专门处理该类型的脚本标记。包控制中可能已经存在这样的语法。如果您愿意,这也是可以进行的修改。该答案的其余部分将告诉您如何执行此操作(底部也有指向已修改文件的链接)。
基本思想是,我们将创建Sublime随附的HTML语法文件的override
。顾名思义,这意味着将始终使用我们正在创建的文件代替Sublime随附的文件。但是请注意,即使基础文件得到更新,更改后的文件仍将被使用(并且不会收到直接警告)。 OverrideAudit程序包的功能之一(免责声明:我是作者)是告诉您何时发生这种情况,因此可以确保您不会错过基础文件中的新功能或错误修复。
这些说明还假定您使用的是Sublime的最新稳定版本,目前为3176。新版本通常会带来新的语法,因此,如果您现在运行的是旧版本(如果您来自神秘的未来,则为新版本),基本说明将保持不变,但文件的内容可能会有所不同。正如我们将看到的,我们的更改基于复制现有功能。
如果尚未安装,请安装PackageResourceViewer软件包,然后从命令面板中使用命令PackageResourceViewer: Open Resource
(请确保您不小心选择了{{1} }变体),然后首先选择extract
程序包,然后选择HTML
文件。这将打开文件以供编辑;保存文件时,将自动为您创建替代。
在幕后,这是在HTML.sublime-syntax
文件夹中创建一个名为HTML
的文件夹(使用Packages
查找该文件夹),并在其中存储资源文件的副本。删除该文件将恢复原始语法。
您可以使用内置的Preferences > Browse Packages...
命令打开View Package File
资源并将其保存在适当的位置,以手动创建替代。如果这样做,则需要关闭并重新打开该文件,因为它将以只读方式打开。
打开的语法文件的顶部附近是一组HTML/HTML.sublime-syntax
,它们在语法上是一种提供命名正则表达式的方法,以使以下步骤更易于阅读。变量列表中有一个名为variables
的变量,其定义如下:
javascript_mime_type
在此之后,我们将创建我们自己的变量,该变量包含正则表达式以匹配script标记的 javascript_mime_type: |-
(?ix)(?:
# https://mimesniff.spec.whatwg.org/#javascript-mime-type
(?:application|text)/(?:x-)?(?:java|ecma)script
| text/javascript1\.[0-5]
| text/jscript
| text/livescript
)
属性的内部。以下是一个示例:
type
这可能需要扩展,也可能不需要扩展(我不熟悉此标签如何用于WebGL)。如果可能的内容存在多种变体,则可以像上面的JavaScript示例中一样扩展它,以包括其他内容。
在文件中进一步向下(在内部版本3176中,在进行上述更改之后大约在315行左右)是名为 shader_mime_type: |-
(?ix)(?:
x-shader/x-fragment
)
的上下文,该上下文包含用于了解如何突出显示基于javascript的内容的语法规则script-javascript
标签,看起来像这样:
<script>
前几行包含语法逻辑,以突出显示 script-javascript:
- meta_content_scope: meta.tag.script.begin.html
- include: script-common
- match: '>'
scope: punctuation.definition.tag.end.html
set:
- include: script-close-tag
- match: (?=\S)
embed: scope:source.js
embed_scope: source.js.embedded.html
escape: (?i)(?=(?:-->\s*)?</script)
属性之后的<script>
中的其余属性。 type
的内容很神奇。他们说,如果标记的主体不为空,则应该通过set
突出显示Javascript语法来突出显示内容,而结束的embed
标记是逃离</script>
并转到回到常规HTML。
在这里,我们将创建自己的部分以挂起embed
脚本:
glsl
我们可以看到,这几乎与上面的相同,但是使用了不同的范围(更多内容见下文)。
script-glsl:
- meta_content_scope: meta.tag.script.begin.html
- include: script-common
- match: '>'
scope: punctuation.definition.tag.end.html
set:
- include: script-close-tag
- match: (?=\S)
embed: scope:source.glsl
embed_scope: source.glsl.embedded.html
escape: (?i)(?=(?:-->\s*)?</script)
标签有关我们的新规则我们奠定了基础,现在将所有内容捆绑在一起。在文件的下方(在3176中,经过上述更改,这大约是第390行),有一组名为script
的规则。在这种情况下,有五个匹配规则,为简洁起见,我们仅在此处显示第一个规则。
script-type-decider
此上下文列出了在 script-type-decider:
- match: (?i)(?={{javascript_mime_type}}(?!{{unquoted_attribute_value}})|'{{javascript_mime_type}}'|"{{javascript_mime_type}}")
set:
- script-javascript
- tag-generic-attribute-meta
- tag-generic-attribute-value
标签的<script>
属性中应用的规则,以查看该特定标签的内容应如何处理。这里专门引用的规则使用上面概述的变量来确定这是一个JavaScript标记,并使用我们刚刚看过的规则嵌入JavaScript语法。
在此type
的正下方(规则的顺序很重要),我们将使用我们自己的变量和规则集添加自己的match
来模仿这一点:
match
在完成所有更改后,您要做的只是 - match: (?i)(?={{shader_mime_type}}(?!{{unquoted_attribute_value}})|'{{shader_mime_type}}'|"{{shader_mime_type}}")
set:
- script-glsl
- tag-generic-attribute-meta
- tag-generic-attribute-value
该文件以使它们处于活动状态。一旦这样做,Sublime将立即重新编译已更改的语法文件并将其生效。 Sublime控制台(save
)执行此操作时将说出View > Show Console
。如果您没有看到任何错误消息,就可以开始:
this gist中提供了讨论了更改的完整版本的文件,用于比较目的,并用于生成上述图像。设计要点的基本文件版本为修订版1,修改版本为版本2,因此可以很容易地确切看到对该文件进行了哪些更改。
值得一提的是,所讨论的软件包实际上提供了三种不同的语法(generating syntax summary
,Cg
和HLSL
)。上面的语法修改仅处理GLSL
语法嵌入,我猜这正是您想要的。
按照与上述相同的说明,您可以交换使用的语法或为其他语法添加规则(假设您知道GLSL
标记中应该包含什么type
以区分它们)。如果存在另一种可以提供主观“更好”突出显示体验的语法,则同样的规则也将适用。
难题的重要部分是嵌入式语法中使用的<script>
。在上面的示例中,我们使用了scope
,它是直接在您使用的包中为此文件类型的语法定义中定义的。
该软件包中的其他范围是source.glsl
和source.cg
。确定适当范围的最简单方法是创建一个新文件,在命令面板中使用适当的source.hlsl
项设置空缓冲区的语法,然后使用Set Syntax:
获得一个弹出窗口,该弹出窗口将告诉你。
答案 1 :(得分:1)
不是直接答案,而是替代解决方案。
使用ES6 import
,您可以将着色器存储在单独的文件中
// some-vertex-shader.glsl
export default `
void main() {
gl_Position = vec4(0, 0, 0, 1);
}
`;
然后在您的JavaScript中可以这样包含它
import someVertexShaderSource from 'path/to/some-shader-source.glsl';
...
这样您就可以设置Sublime以突出显示.glsl文件中的代码
如果您想支持较旧的浏览器,则可以使用类似rollup的格式将所有文件合并为一个文件。
three.js就是这样。
同样在VSCode中(抱歉,不是sublimetext),我相信您可以使用一种语言标记模板文字以使其突出显示
const shaderSource = /* glsl */`
void main() {
gl_Position = vec4(0, 0, 0, 1);
}
答案 2 :(得分:0)
与我的懒惰相比,答案有些复杂:
更改:
<script type="x-shader/x-fragment">
// glsl code here not syntax highlighting
</script>
收件人:
<script>
// glsl code here now with syntax highlighting
</script>
然后javascript在glsl的第一行失败,但是我们不需要js进行解析,所以没关系。因此您只会在浏览器中看到该脚本标记的一个错误。
但是所有其他脚本标签都运行。并且语法高亮适用于glsl。 Sublime认为它是javascript,但似乎在颜色方面做得很好。我主要需要用于调试和测试的颜色,因此我可以以这种方式使用它,只需在发布产品时添加type='x-shader/x-fragment'
。