在Sublime Text 3构建系统中捕获Cargo / Rustc的错误消息的权利file_regex
是什么?我要特别询问的是相对较新的cargo / rustc版本(似乎较旧的版本使用了更容易解析的单行错误输出格式)。
在中断的hello-world项目上输出cargo build
的示例(cargo new --bin broken
自动生成的默认代码,其中删除了双引号以创建错误消息):
error: unterminated double quote string
--> src/main.rs:2:14
|
2 | println!("Hello, world!);
| ______________^
3 | | }
| |__^
error: aborting due to previous error
error: Could not compile `broken`.
相对文件路径为src/main.rs
,行列为2:14
,我个人更希望直接在行之间看到的错误消息是
unterminated double quote string
这种方法有效,但不能正确捕获错误消息,因为它们位于之前带有文件路径和行号的行:
{
"name": "cargo build",
"shell_cmd": "cargo build",
"working_dir":
"/home/you/path/to/cargo/project/with/the/toml",
"file_regex":
"^ *--> *([a-zA-Z0-9_/.]+):([0-9]+):([0-9]+)()$"
},
使用funny regex here的this awesome lookahead-with-matching-groups-trick:
error(?:\[E\d+\])?: (?=.+\n +--> +([a-zA-Z0-9_\/.-]+):([\d]+):([\d]+))(.+)
本可以解决问题,但是Sublime doesn't seem to work with multiline regexes。
答案 0 :(得分:2)
不幸的是,答案的TL; DR版本是,我认为让Sublime识别问题中的错误输出的唯一方法是使工具生成不同格式的输出(直接或通过某种方式生成)。过滤器应用(位于中间)或通过为您的构建创建自己的自定义构建目标来识别此错误输出(但仅适用于内联错误,请参见下文)。
Sublime Text中的构建系统具有两个可用于尝试和匹配错误输出/构建结果的正则表达式file_regex
和line_regex
。两者都将应用于输出面板中的构建结果,以获得构建结果列表。
file_regex
是用于匹配构建结果的“通用”正则表达式,并且应包含2到4个捕获适当数据的捕获组中的任意一个。捕获组(按顺序使用)是filename
,line
,column
,message
。
line_regex
用于有关错误位置的信息与错误消息/位置不在同一行的情况。在这里,捕获按照line
,column
,message
的顺序进行,您可以使用其中任意1到3个。
在两种情况下,捕获都按照上面给定的顺序使用,这可能需要有空的捕获组来确保一切按预期进行。
在正常使用情况下,您仅使用file_regex
而不使用其他任何内容,即可为您捕获结果。如果您还使用line_regex
,则在内部line_regex
上进行Sublime匹配,然后,如果找到匹配项,它将在结果输出中向后查找与file_regex
匹配的第一行,并将捕获的结果结合在一起。
从本质上讲,这意味着Sublime可以捕获的结果类型受到一些限制;该文件名必须出现在有关该错误的其他信息之前,以便被捕获。
在上面的示例中,首先显示错误,然后显示错误的位置,因此,固有地,没有办法将两个正则表达式匹配正确地关联在一起。
最常见的解决方法是修改工具的输出,以便将其重新加工为Sublime可以使用上述正则表达式检测到的格式。
例如,您可能会更改构建,以使其执行命令并将结果通过管道传输到另一个Shell脚本或程序,这些脚本或程序可以在运行过程中即时更改信息。另一个示例是更改构建,以使其调用执行该工具的脚本/批处理文件,并在内部进行输出更改,以使最终输出与Sublime期望的结果匹配。
尽管无法使用regex系统完全匹配您的构建输出,但是如果您主要对显示的内联构建错误感兴趣,那么如果您想通过一点Sublime插件开发来使自己的手变得肮脏,则可以采取一些措施。在这种情况下,您需要了解一些Python。有custom build targets和Sublime API上的文档。
在内部,当您运行构建时,Sublime从sublime-build
文件中收集信息,展开其中的所有变量,然后调用exec
内部命令来实际执行构建,并提供密钥sublime-build
作为参数(由于Sublime会为您处理,因此未提供诸如selector
之类的参数),并且exec
命令设置了file_regex
和{{ 1}}设置进入输出缓冲区。
从此处开始,Sublime核心将直接使用应用的设置对构建结果进行导航,例如,通过单击结果以打开文件,或使用导航命令来查找下一个和上一个错误。
但是,line_regex
命令负责使用相同的结果向您显示内联构建错误,因此尽管结果导航只能将您带到该位置,但仍可能使内联错误消息正常工作在文件中。
可以在exec
文件中提供的键之一是sublime-build
,它指定应执行构建的命令;如果未提供,则默认为target
。
通过创建自己的模仿exec
的自定义命令并在exec
的{{1}}指令中使用它,您可以进入构建过程以捕获适当的数据。
target
命令存储在sublime-build
中,您可以使用命令面板中的exec
命令进行查看。
作为一个最小的示例,以下插件定义了一个名为Default/exec.py
的新命令,该命令准确地模仿了View Package File
命令的作用。对cargo_exec
的调用是使Sublime核心从构建输出视图返回所有错误信息的API调用,该视图用于设置用于内联构建错误的模型。
通过修改该代码以检查缓冲区的内容并使用您对错误的外观的自定义知识,核心exec
命令中的其余代码将为您显示内联错误。
self.output_view.find_all_results_with_text()
要将其用作自定义构建目标,您需要在exec
文件中添加几个额外的键:
import sublime
import sublime_plugin
from Default.exec import ExecCommand
# Subclass the exec command to hook into the output processing.
class CargoExecCommand(ExecCommand):
def run(self, **kwargs):
# If we are being told to kill a running build, kill it right away
# and leave.
if kwargs.get("kill", False):
return super().run(kill=True)
# Use our super class to execute the build from this point.
super().run(**kwargs)
# override the super class method so we can handle output as it
# arrives in the output panel.
def service_text_queue(self):
is_empty = False
with self.text_queue_lock:
if len(self.text_queue) == 0:
# this can happen if a new build was started, which will clear
# the text_queue
return
characters = self.text_queue.popleft()
is_empty = (len(self.text_queue) == 0)
self.output_view.run_command(
'append',
{'characters': characters, 'force': True, 'scroll_to_end': True})
if self.show_errors_inline and characters.find('\n') >= 0:
errs = self.output_view.find_all_results_with_text()
errs_by_file = {}
for file, line, column, text in errs:
if file not in errs_by_file:
errs_by_file[file] = []
errs_by_file[file].append((line, column, text))
self.errs_by_file = errs_by_file
self.update_phantoms()
if not is_empty:
sublime.set_timeout(self.service_text_queue, 1)
# Use the latest build results to add inline errors to newly opened files.
class CargoExecEventListener(sublime_plugin.EventListener):
def on_load(self, view):
w = view.window()
if w is not None:
w.run_command('cargo_exec', {'update_phantoms_only': True})
答案 1 :(得分:1)
此AWK脚本将错误消息与行号结合在一起,并将其带入Sublime所需的顺序:
awk 'BEGIN { errmsg="" } /error(\[E[0-9]+\])?:.*/ {errmsg=$0; next} /\ *-->\ *.*/ { printf "%s::::%s\n", $0, errmsg; next} {print $0}'
输出与following regex轻松匹配:
error(?:\[E\d+\])?: (?=.+\n +--> +([a-zA-Z0-9_\/.-]+):([\d]+):([\d]+))(.+)
您可以在|
内使用shell_cmd
和AWK脚本,因此此构建配置将捕获所有错误消息并以正确的行号显示它们:
{
"name": "cargo build",
"working_dir": "/wherever/your/project",
"shell_cmd": "cargo build 2>&1 | awk 'BEGIN { errmsg=\"\" } /error(\\[E[0-9]+\\])?:.*/ {errmsg=\\$0; next} /\\ *-->\\ *.*/ { printf \"%s::::%s\\n\", \\$0, errmsg; next} {print \\$0}'",
"file_regex": " +--> +([a-zA-Z_\\/.-]+):(\\d+):(\\d+)::::(.*)"
}
这也以相同的方式对待warning
:
"shell_cmd": "cargo build 2>&1 | awk 'BEGIN { errmsg=\"\" } /(error|warning)(\\[E[0-9]+\\])?:.*/ {errmsg=\\$0; next} /\\ *-->\\ *.*/ { printf \"%s::::%s\\n\", \\$0, errmsg; next} {print \\$0}'",