一、如何自定义函数列表
1. 解析器基础设置
id:该解析器的唯一标识,不可重复。
displayName:保留属性,暂未启用,供未来扩展使用。
comment(可选):可在该属性中填写正则表达式,用于识别文件中的注释区域。被识别的注释区域会被搜索忽略,避免误识别注释中的函数。
2. 解析器类型
函数解析器:适用于仅包含独立函数、无类定义的语言(如C语言),仅包含一个 <function> 节点。
类解析器:适用于函数仅定义在类内部、无类外函数的语言(如Java),仅包含一个 <classRange> 节点。
混合解析器:适用于类内、类外均有函数定义的语言(如C++),同时包含 <function> 和 <classRange> 两个节点。
3. 解析器正则表达式说明
不支持正则表达式的后向查找操作。
仅用于搜索函数名称,不支持正则替换或修改;若需删除匹配结果的开头或结尾内容,可使用 \K 重置匹配,或使用前瞻操作。
可使用 (?x) 修饰符,允许在正则表达式中添加额外空白和 # 前缀注释(详见“正则表达式搜索修饰符”文档)。
解析器默认开启“.”匹配换行(相当于正则中的 (?s));若需让“.”不匹配换行,需在正则表达式中添加 (?-s)。
可使用Notepad++的“搜索”对话框(搜索模式设为“正则表达式”)调试正则表达式。若使用其他工具调试,需注意不同正则实现存在细微差异,建议选择与Notepad++使用相同Boost库版本的工具,确保结果一致(最新版Notepad++使用的Boost库版本可参考“搜索:正则表达式”章节)。
二、各类解析器详细配置
1. 函数解析器
mainExpr(属性):用于匹配包含函数所有关键信息的完整字符串的正则表达式。
displayMode(属性):保留属性,暂未启用。
functionName(元素):定义一个或多个正则表达式,从 mainExpr 匹配的结果中提取函数名称。
nameExpr(元素):用于匹配函数名称,以 mainExpr 的匹配结果作为输入,其 expr 属性用于填写匹配函数名称的正则表达式。
className(元素):定义一个或多个正则表达式,从 mainExpr 的匹配结果中提取类名(即使是函数解析器,也可设置该元素)。
nameExpr(元素):用于提取类名,以 mainExpr 的匹配结果作为输入,其 expr 属性用于填写匹配类名的正则表达式。
2. 类解析器
mainExpr(属性):用于搜索类定义的核心正则表达式,匹配包含类所有关键信息的完整字符串。
displayMode(属性):保留属性,暂未启用。
openSymbole & closeSymbole(属性,可选):用于定义类的边界符号。解析器会从 mainExpr 匹配结果的最后一个字符开始,查找 openSymbole,再通过匹配对应的 closeSymbole 确定类的结束位置,支持多层嵌套(例如:{{{}{}}}{})。
className(元素):包含一个或多个 nameExpr 节点,用于从 mainExpr 的匹配结果中提取类名。
function(元素):用于查找类内部的函数,通过其 mainExpr 属性和 functionName 节点中的表达式实现匹配。
mainExpr(属性):用于匹配类内函数完整信息的正则表达式。
functionName(元素):用于封装和提取类内函数名称的容器。
functionNameExpr(元素):用于匹配类内函数名称的核心元素(区别于函数解析器的 nameExpr 元素),其 expr 属性用于填写匹配类内函数名称的正则表达式。
3. 混合解析器
三、解析器验证与使用
1. 手动验证解析器
2. 自定义内置语言或UDL的函数列表
3. 验证函数列表定义文件
四、贡献解析器规则到Notepad++代码库
仅当你希望自定义解析器规则随Notepad++安装包分发、供所有用户使用时,才需要创建拉取请求;仅个人使用无需操作。
为自己的UDL创建的函数列表,无需创建拉取请求(用户自定义语言及其函数列表不会随Notepad++分发)。
仅编辑现有解析器规则供个人使用,无需创建拉取请求。
拉取请求仅适用于:更新现有语言的解析器规则、为内置语言添加新的解析器规则;不符合以上条件无需继续操作。
1. 单元测试(必做)
创建或同步你分叉的Notepad++仓库。
将 [YOUR_SOURCES_DIR]\notepad-plus-plus\PowerEditor\installer\functionList\ 下的所有XML文件,复制到 [YOUR_SOURCES_DIR]\notepad-plus-plus\PowerEditor\bin\functionList\ 中。
将 [YOUR_SOURCES_DIR]\notepad-plus-plus\PowerEditor\installer\filesForTesting\ 下的所有XML文件,复制到 [YOUR_SOURCES_DIR]\notepad-plus-plus\PowerEditor\bin\functionList\ 中。
将你修改后的解析器XML文件,复制到 [YOUR_SOURCES_DIR]\notepad-plus-plus\PowerEditor\bin\functionList\ 中。
打开PowerShell,进入 [YOUR_SOURCES_DIR]\notepad-plus-plus\PowerEditor\Test\FunctionList\ 目录,运行 .\unitTestLauncher.ps1。
当显示“All tests are passed.”(所有测试均通过)时,即可提交拉取请求。
2. 单元测试文件缺失的处理
在 [YOUR_SOURCES_DIR]\notepad-plus-plus\PowerEditor\Test\FunctionList\ 中,添加一个以小写语言名命名的目录。
在该目录中添加测试文件,命名为 unitTest。
打开cmd,进入 [YOUR_SOURCES_DIR]\notepad-plus-plus\PowerEditor\Test\FunctionList\ 目录,执行命令:..\..\bin\notepad++.exe -export=functionList -l[langName] .\[langName]\unitTest(将[langName]替换为目标语言名)。
会生成名为 unitTest.result.json 的文件,将其重命名为 unitTest.expected.result。
运行单元测试(参考上方步骤),确保解析器规则不会导致回归问题。
3. 单元测试文件已存在的处理
(1)修改现有单元测试文件
运行单元测试,确保当前解析器规则无回归问题。
根据你的增强内容,修改 [YOUR_SOURCES_DIR]\notepad-plus-plus\PowerEditor\Test\FunctionList\[langName]\unitTest 文件(通常只需添加内容,无需删除现有内容)。
打开cmd,进入 [YOUR_SOURCES_DIR]\notepad-plus-plus\PowerEditor\Test\FunctionList\ 目录,执行命令:..\..\bin\notepad++.exe -export=functionList -l[langName] .\[langName]\unitTest。
生成 unitTest.result.json 文件后,删除原有的 unitTest.expected.result,再将 unitTest.result.json 重命名为 unitTest.expected.result。
(2)添加新的单元测试文件
运行单元测试,确保当前解析器规则无回归问题。
在 [YOUR_SOURCES_DIR]\notepad-plus-plus\PowerEditor\Test\FunctionList\[langName]\ 中,添加一个与测试类别相关的目录(名称可自定义)。
将测试文件命名为 unitTest,复制到该新目录中。
打开cmd,进入 [YOUR_SOURCES_DIR]\notepad-plus-plus\PowerEditor\Test\FunctionList\ 目录,执行命令:..\..\bin\notepad++.exe -export=functionList -l[langName] .\[langName]\[yourTestDir2]\unitTest(将[yourTestDir2]替换为新目录名)。
在新目录中会生成 unitTest.result.json 文件,将其重命名为 unitTest.expected.result。
4. 创建并提交拉取请求
创建一个GitHub问题,说明需要改进(已有解析器)或添加(无解析器)目标语言的函数列表,并注明你已准备好解析器规则,将提交拉取请求。
通过GitHub界面,从你的分叉仓库创建拉取请求,合并到主仓库。
等待开发者反馈,并根据反馈调整解析器规则,直至拉取请求被接受或拒绝。