我有Smalltalk sublime-syntax file (YAML)用于Sublime Text 3,我想为嵌入式C代码添加突出显示支持。
smalltalk代码中的inline C
代码(始终以^%\{
开头,以%\}$
结尾)。
一个简单的示例(C
不多,但需要一个简单的案例):
sigABRT
"return the signal number for SIGABRT - 0 if not supported by OS
(the numeric value is not the same across unix-systems)"
%{ /* NOCONTEXT */
#ifdef SIGABRT
RETURN ( __mkSmallInteger(SIGABRT) );
#else
RETURN ( __mkSmallInteger(0) );
#endif
%}
!
Sublime文本(甚至还有example)中都有新功能embed
。
我试图做这样的事情:
- match: '^%\{'
embed: scope:source.c
embed_scope: meta.environment.embedded.c.smalltalk source.c.embedded
escape: '%\}$'
但是,我无法将其正确地合并到我的current highlighting file中。
有人知道如何正确地将一种语言嵌入另一种语言吗?
答案 0 :(得分:1)
这个问题有点棘手,因为您提供了一个示例语法定义和一些Smalltalk源代码示例,但是由于语法结构不正确,因此所提供的代码未在所提供的语法中突出显示。
出于此处的目的,我们假设您提供的Smalltalk示例为以下示例。这可能是正确的,也可能是无效的(自从我与Smalltalk合作以来已经有很长时间了),但是它突出显示了您的语法,因此,请对其进行足够的调用以进行测试。
Object subclass: Test [
sigABRT
"return the signal number for SIGABRT - 0 if not supported by OS
(the numeric value is not the same across unix-systems)"
%{ /* NOCONTEXT */
#ifdef SIGABRT
RETURN ( __mkSmallInteger(SIGABRT) );
#else
RETURN ( __mkSmallInteger(0) );
#endif
%}
!
].
上面提供的语法匹配是可以使用的正确语法,所以我猜测您的问题出在语法中的位置。
因此,假设在语法定义中可能有多个地方需要匹配这些C块之一;在这种情况下,我们可能想使用包含匹配项的语法创建一个新的context
,以便我们可以在需要的地方include
进行匹配:
c-block:
- match: '%\{'
embed: scope:source.c
embed_scope: meta.environment.embedded.c.smalltalk source.c.embedded
escape: '%\}$'
这与您上面提供的摘录相同,但置于上下文中。因此,可以说,这样的块可以出现的第一个位置是在块的主体中。您的语法中有一个block-body
上下文,因此我们在其末尾添加一个include
来包含以下新上下文:
block-body:
- include: pragma
- include: selector
- include: literal
- include: block
- include: comment
- include: c-block
但是,这没有理想的结果;突出显示不正确:
很明显,至少从C注释开始(可能更早)开始,突出显示错误。如果在光标位于注释上的同时使用Tools > Developer > Show Scope Name
,则可以看到分配的范围为source.smalltalk entity.name.function
,这意味着该语法将C注释开始视为方法名。
看起来%{
构造没有正确突出显示,并且检查显示%
字符的范围是source.smalltalk keyword.other
。
因此,实际上,当前的问题是使用上述定义,而不是将%{
视为C块的开始,而是将其视为关键字,如果是关键字,则匹配a的规则C块根本没有触发。
如果您查看语法,则main
上下文如下:
main:
- match: '([a-zA-Z][a-zA-Z0-9]*)\s*(subclass:)\s*([a-zA-Z][a-zA-Z0-9]*)\s*\['
captures:
1: entity.other.inherited-class
2: keyword.other
3: entity.name.type
push:
- match: '\]'
pop: true
- include: pragma
- match: '(([a-zA-Z][a-zA-Z0-9]*:)|[+\-\/\\*~<>=@%|&?!.,:;^]+)\s*([a-zA-Z][a-zA-Z0-9]*)'
captures:
1: entity.name.function
3: variable.other
- match: "([a-zA-Z][a-zA-Z0-9]*)"
scope: entity.name.function
- include: block
- include: comment
- include: block-body
这些规则说,当我们看到以BaseClass subclass: SubClass [
之类的开头的行时,我们正在进入一个匿名上下文(通过push
)来处理类主体(或块)的内容。等等)。
匿名上下文包含规则,当它看到结束]
字符,两个不同的匹配项以查找函数名称时弹出,然后在include
的上下文中出现block
,分别为comment
和block-body
。
在include
中,Sublime从该上下文中获取所有match
规则,并在插入位置插入它们的副本,就像您刚刚在此处手动输入它们一样。
此外,当context
中有多个规则可能匹配时,上下文中的第一个match
规则就是所应用的规则(即,它“赢得”了平局) )。
范围keyword.other
适用于pragma
上下文以及selector
上下文中的规则,并且selector
上下文可以匹配单个%
字符作为关键字。
因此,这里的问题是,由于include c-block
出现在selector
上下文的包含列表中的block-body
之后,因此selector
上下文正在查找并匹配{{ 1}}字符可以在C块的规则之前找到。
然后的解决方案是将%
的位置移到该项目之前,以确保它首先匹配:
include c-block
在适当的位置,该块突出显示了更多我们期望的样子:
答案 1 :(得分:1)
我能够通过 Regex 前瞻和后视来解决类似的问题
- match: ' (?=\{")'
embed: scope:source.json
escape: '(?<=\})$'