代码之家  ›  专栏  ›  技术社区  ›  Andrey Tyukin

文件\u regex for Cargo builds in Sublime Text 3

  •  0
  • Andrey Tyukin  · 技术社区  · 7 年前

    问题

    什么是正确的 file_regex

    例子

    cargo build 在中断的hello world项目上(默认代码由 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 .


    2 回复  |  直到 7 年前
        1
  •  2
  •   OdatNurd    7 年前

    TL;DR版本的答案是,不幸的是,我认为让Sublime识别问题中的错误输出的唯一方法是要么让工具以不同的格式生成输出(直接或通过位于中间的某个过滤器应用程序),要么为您的构建创建您自己的自定义构建目标,以便能够识别此错误错误输出(但它只适用于内联错误,见下文)。

    Sublime文本中的构建系统有两个正则表达式,可用于尝试匹配错误输出/构建结果, file_regex line_regex . 两者都应用于输出面板中的生成结果,以获得生成结果列表。

    文件\正则表达式 是用于匹配生成结果的“通用”正则表达式,应该包含2到4个捕获组,用于捕获适当的数据。捕获组(按顺序使用)是 filename line , column , message

    正则表达式行 , 消息

    在这两种情况下,捕获都是按照上面给出的顺序使用的,这可能需要有空的捕获组来确保事情按预期排列。

    在正常使用中,你只需要 其他什么都没有,这就为你捕捉到了结果。如果你也使用 正则表达式行 正则表达式行 文件\正则表达式

    从本质上说,这意味着对崇高能够捕捉到的结果有一些限制;文件名必须出现在有关错误的其他信息之前,以便捕获它。

    解决这个问题最常见的方法是修改工具的输出,以便将其重新加工成Sublime可以通过上述正则表达式检测到的格式。

    自定义生成目标

    虽然没有办法使用regex系统来完全匹配构建输出,但是如果您主要对显示的内联构建错误感兴趣,那么如果您想通过一点崇高的插件开发来弄脏您的手,还是有一些方法的。在这种情况下,您需要了解一点Python。有关于 custom build targets Sublime API 可用。

    在内部,当您运行构建时,Sublime从 sublime-build 文件,展开其中的任何变量,然后调用 exec 提供 作为论据(一些,如 selector ,因为Sublime会为您处理),这是 设置 设置到输出缓冲区。

    从这里开始,Sublime core直接使用应用的设置来对构建结果执行导航,例如通过单击结果打开文件,或者使用导航命令转到下一个和上一个错误。

    然而,这是 执行 命令,该命令负责使用这些相同的结果向您显示内联生成错误,因此仍然可以使内联错误消息正常工作,尽管结果导航只能将您带到文件中的位置。

    崇高的体格 文件是 target ,指定应执行生成的命令;默认为 执行 如果不给的话。

    通过创建自己的自定义命令来模仿 执行 是的,并且用在 你的指示 崇高的体格 ,您可以钩住构建过程以捕获适当的数据。

    这个 执行 Default/exec.py ,您可以使用 View Package File 命令选项板中的命令。

    下面的插件定义了一个名为 cargo_exec 执行 self.output_view.find_all_results_with_text() API调用,使Sublime core返回build output视图中的所有错误信息,该视图用于设置用于内联生成错误的幻影。

    通过修改代码来检查缓冲区的内容,并使用您对错误外观的自定义知识,核心中的代码的其余部分 执行 命令将为您显示内联错误。

    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})
    

    // Specify a custom build target to execute this build, and specify what
    // argument to the command will cause it to cancel a build that is currently
    // running.
    "target": "cargo_exec",
    "cancel": {"kill": true},
    
        2
  •  1
  •   Andrey Tyukin    7 年前

    此AWK脚本将错误消息与行号结合起来,并将其按升华所需的顺序排列:

    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 ,因此此生成配置捕获所有错误消息并以正确的行号显示它们:

    {
        "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}'",