GtkSourceView语言定义:如何匹配双换行作为结束元素?
解决GtkSourceView语言定义中@LI块的匹配与样式问题
嘿,我之前也踩过GtkSourceView正则匹配的类似坑,给你梳理下可行的解决方案:
首先,你当前的问题主要出在两个地方:一是双换行的正则没考虑文件结尾的情况,二是首行和后续内容的样式区分逻辑不够精准。下面是调整后的完整代码片段,我会逐点解释:
<style id="li" name="Listing" map-to="def:identifier"/> <style id="kt" name="Kastentitel" map-to="def:type"/> <!-- 这里保留你其他的上下文定义 --> <context id="li"> <start>@LI:</start> <!-- 匹配所有双换行格式 + 文件结尾,覆盖不同系统换行和块在末尾的情况 --> <end>(\r\n\r\n|\r\r|\n\n|\Z)</end> <contexts> <!-- 匹配@LI:后面的首行内容,应用Kastentitel样式 --> <context style-ref="kt"> <match>(?<=@LI:).*?(?=\r|\n|\Z)</match> </context> <!-- 匹配首行之后的所有内容,应用Listing样式,同时兼容其他基础语法 --> <context style-ref="li"> <match>(?<=\r|\n).*?(?=(\r\n\r\n|\r\r|\n\n)|\Z)</match> <include> <context ref="default-text"/> </include> </context> </contexts> </context>
关键调整点说明:
修复
的匹配问题
你之前用的[\r\n]{2,}太宽泛,GtkSourceView的正则引擎对换行匹配需要更明确的规则,而且没考虑当@LI块刚好在文件末尾(无双换行)的终止情况。新的正则(\r\n\r\n|\r\r|\n\n|\Z):- 覆盖了Windows(
\r\n\r\n)、Unix(\n\n)、旧Mac(\r\r)的双换行格式 \Z专门匹配文件结束位置,确保块在末尾也能正确终止
- 覆盖了Windows(
精准区分首行与后续内容的样式
原来的<include>逻辑没法精准拆分首行和后续内容,我改成了两个嵌套上下文:- 第一个上下文用正向预查
(?<=@LI:)锁定@LI:之后的内容,匹配到第一个换行或文件结尾为止,应用标题样式kt - 第二个上下文用
(?<=\r|\n)匹配首行之后的所有内容,直到双换行或文件结尾,应用列表样式li - 加入
<include><context ref="default-text"/></include>是为了保证如果你的语言还有其他语法(比如注释、字符串),在@LI块里也能正常解析,不会冲突
- 第一个上下文用正向预查
正则预查不生效的替代方案
要是你的GtkSourceView版本对正则预查支持有限,可以试试这种拆分写法:<context id="li"> <start>@LI:</start> <end>(\r\n\r\n|\r\r|\n\n|\Z)</end> <!-- 给@LI:本身应用标题样式 --> <context sub-pattern="0" where="start" style-ref="kt"/> <!-- 匹配首行文本 --> <context> <start>(?<=@LI:)</start> <end>(\r|\n)</end> <style-ref="kt"/> </context> <!-- 匹配后续内容 --> <context> <start>(\r|\n)</start> <end>(\r\n\r\n|\r\r|\n\n|\Z)</end> <style-ref="li"/> <include> <context ref="default-text"/> </include> </context> </context>
你可以用你的测试文本试试,不管@LI块在文件中间还是末尾,应该都能正确匹配,首行和后续内容的样式也能分开应用了。
内容的提问来源于stack exchange,提问作者Chrissss
相关产品推荐
相关产品推荐

