file_regex for Cargo builds in Sublime Text 3












0















Question



What would be the right file_regex to capture Cargo / Rustc's error messages in a Sublime Text 3 build system? I'm asking specifically about relatively recent cargo/rustc versions (it seems that the older versions used a somewhat more easily parsable single-line error output format).



Example



Example output of cargo build on a broken hello-world project (default code autogenerated by cargo new --bin broken, with one double quote removed to create an error message):



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`.


The relative file path is src/main.rs, line-column is 2:14, the error message that I personally would prefer to see directly between the lines is



unterminated double quote string




1st Solution Attempt



This kind-of works, but it doesn't capture the error messages properly, because they are on a separate line that preceeds the line with the file path and line numbers:



    {
"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]+)()$"
},


2nd Solution Attempt



This funny regex here that uses this awesome lookahead-with-matching-groups-trick:



error(?:[Ed+])?: (?=.+n +--> +([a-zA-Z0-9_/.-]+):([d]+):([d]+))(.+)


would have solved the problem, but Sublime doesn't seem to work with multiline regexes.













share|improve this question

























  • Can you include a sample of an error output? Along with file_regex there is also line_regex that can be paired with it for situations where the error output is on two lines. However it works by matching line_regex and then going backwards to get the file, so if the outputs are in the wrong order it may not work.

    – OdatNurd
    Nov 13 '18 at 17:43











  • @OdatNurd I've updated the question with an example error message. Thanks for the hint with line_regex, will look up what that is, didn't know about it.

    – Andrey Tyukin
    Nov 13 '18 at 19:00











  • line_regex doesn't seem to help here: it's only for the cases where file name and line/column are on different lines, but it does not help me to permute the matched groups into the right order.

    – Andrey Tyukin
    Nov 13 '18 at 19:06













  • Indeed so, unfortunately. Only the file_regex can match the name of the file, while the line_regex can match everything BUT the file; in use the two merge together but since it matches line and then goes backwards to get the file, the output of this is in the wrong order.

    – OdatNurd
    Nov 13 '18 at 19:18











  • In such a case as far as I'm aware the only way to get it to be able to determine the error message in this case is to massage the output of the tool to conform to what Sublime expects. If you're only interested in inline build errors and not clickable build results, it's possible with some work to modify the internal exec command to handle something like this, but that's more involved.

    – OdatNurd
    Nov 13 '18 at 19:20
















0















Question



What would be the right file_regex to capture Cargo / Rustc's error messages in a Sublime Text 3 build system? I'm asking specifically about relatively recent cargo/rustc versions (it seems that the older versions used a somewhat more easily parsable single-line error output format).



Example



Example output of cargo build on a broken hello-world project (default code autogenerated by cargo new --bin broken, with one double quote removed to create an error message):



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`.


The relative file path is src/main.rs, line-column is 2:14, the error message that I personally would prefer to see directly between the lines is



unterminated double quote string




1st Solution Attempt



This kind-of works, but it doesn't capture the error messages properly, because they are on a separate line that preceeds the line with the file path and line numbers:



    {
"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]+)()$"
},


2nd Solution Attempt



This funny regex here that uses this awesome lookahead-with-matching-groups-trick:



error(?:[Ed+])?: (?=.+n +--> +([a-zA-Z0-9_/.-]+):([d]+):([d]+))(.+)


would have solved the problem, but Sublime doesn't seem to work with multiline regexes.













share|improve this question

























  • Can you include a sample of an error output? Along with file_regex there is also line_regex that can be paired with it for situations where the error output is on two lines. However it works by matching line_regex and then going backwards to get the file, so if the outputs are in the wrong order it may not work.

    – OdatNurd
    Nov 13 '18 at 17:43











  • @OdatNurd I've updated the question with an example error message. Thanks for the hint with line_regex, will look up what that is, didn't know about it.

    – Andrey Tyukin
    Nov 13 '18 at 19:00











  • line_regex doesn't seem to help here: it's only for the cases where file name and line/column are on different lines, but it does not help me to permute the matched groups into the right order.

    – Andrey Tyukin
    Nov 13 '18 at 19:06













  • Indeed so, unfortunately. Only the file_regex can match the name of the file, while the line_regex can match everything BUT the file; in use the two merge together but since it matches line and then goes backwards to get the file, the output of this is in the wrong order.

    – OdatNurd
    Nov 13 '18 at 19:18











  • In such a case as far as I'm aware the only way to get it to be able to determine the error message in this case is to massage the output of the tool to conform to what Sublime expects. If you're only interested in inline build errors and not clickable build results, it's possible with some work to modify the internal exec command to handle something like this, but that's more involved.

    – OdatNurd
    Nov 13 '18 at 19:20














0












0








0


1






Question



What would be the right file_regex to capture Cargo / Rustc's error messages in a Sublime Text 3 build system? I'm asking specifically about relatively recent cargo/rustc versions (it seems that the older versions used a somewhat more easily parsable single-line error output format).



Example



Example output of cargo build on a broken hello-world project (default code autogenerated by cargo new --bin broken, with one double quote removed to create an error message):



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`.


The relative file path is src/main.rs, line-column is 2:14, the error message that I personally would prefer to see directly between the lines is



unterminated double quote string




1st Solution Attempt



This kind-of works, but it doesn't capture the error messages properly, because they are on a separate line that preceeds the line with the file path and line numbers:



    {
"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]+)()$"
},


2nd Solution Attempt



This funny regex here that uses this awesome lookahead-with-matching-groups-trick:



error(?:[Ed+])?: (?=.+n +--> +([a-zA-Z0-9_/.-]+):([d]+):([d]+))(.+)


would have solved the problem, but Sublime doesn't seem to work with multiline regexes.













share|improve this question
















Question



What would be the right file_regex to capture Cargo / Rustc's error messages in a Sublime Text 3 build system? I'm asking specifically about relatively recent cargo/rustc versions (it seems that the older versions used a somewhat more easily parsable single-line error output format).



Example



Example output of cargo build on a broken hello-world project (default code autogenerated by cargo new --bin broken, with one double quote removed to create an error message):



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`.


The relative file path is src/main.rs, line-column is 2:14, the error message that I personally would prefer to see directly between the lines is



unterminated double quote string




1st Solution Attempt



This kind-of works, but it doesn't capture the error messages properly, because they are on a separate line that preceeds the line with the file path and line numbers:



    {
"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]+)()$"
},


2nd Solution Attempt



This funny regex here that uses this awesome lookahead-with-matching-groups-trick:



error(?:[Ed+])?: (?=.+n +--> +([a-zA-Z0-9_/.-]+):([d]+):([d]+))(.+)


would have solved the problem, but Sublime doesn't seem to work with multiline regexes.










regex sublimetext3 rust-cargo






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 14 '18 at 0:28







Andrey Tyukin

















asked Nov 13 '18 at 17:21









Andrey TyukinAndrey Tyukin

27.2k42349




27.2k42349













  • Can you include a sample of an error output? Along with file_regex there is also line_regex that can be paired with it for situations where the error output is on two lines. However it works by matching line_regex and then going backwards to get the file, so if the outputs are in the wrong order it may not work.

    – OdatNurd
    Nov 13 '18 at 17:43











  • @OdatNurd I've updated the question with an example error message. Thanks for the hint with line_regex, will look up what that is, didn't know about it.

    – Andrey Tyukin
    Nov 13 '18 at 19:00











  • line_regex doesn't seem to help here: it's only for the cases where file name and line/column are on different lines, but it does not help me to permute the matched groups into the right order.

    – Andrey Tyukin
    Nov 13 '18 at 19:06













  • Indeed so, unfortunately. Only the file_regex can match the name of the file, while the line_regex can match everything BUT the file; in use the two merge together but since it matches line and then goes backwards to get the file, the output of this is in the wrong order.

    – OdatNurd
    Nov 13 '18 at 19:18











  • In such a case as far as I'm aware the only way to get it to be able to determine the error message in this case is to massage the output of the tool to conform to what Sublime expects. If you're only interested in inline build errors and not clickable build results, it's possible with some work to modify the internal exec command to handle something like this, but that's more involved.

    – OdatNurd
    Nov 13 '18 at 19:20



















  • Can you include a sample of an error output? Along with file_regex there is also line_regex that can be paired with it for situations where the error output is on two lines. However it works by matching line_regex and then going backwards to get the file, so if the outputs are in the wrong order it may not work.

    – OdatNurd
    Nov 13 '18 at 17:43











  • @OdatNurd I've updated the question with an example error message. Thanks for the hint with line_regex, will look up what that is, didn't know about it.

    – Andrey Tyukin
    Nov 13 '18 at 19:00











  • line_regex doesn't seem to help here: it's only for the cases where file name and line/column are on different lines, but it does not help me to permute the matched groups into the right order.

    – Andrey Tyukin
    Nov 13 '18 at 19:06













  • Indeed so, unfortunately. Only the file_regex can match the name of the file, while the line_regex can match everything BUT the file; in use the two merge together but since it matches line and then goes backwards to get the file, the output of this is in the wrong order.

    – OdatNurd
    Nov 13 '18 at 19:18











  • In such a case as far as I'm aware the only way to get it to be able to determine the error message in this case is to massage the output of the tool to conform to what Sublime expects. If you're only interested in inline build errors and not clickable build results, it's possible with some work to modify the internal exec command to handle something like this, but that's more involved.

    – OdatNurd
    Nov 13 '18 at 19:20

















Can you include a sample of an error output? Along with file_regex there is also line_regex that can be paired with it for situations where the error output is on two lines. However it works by matching line_regex and then going backwards to get the file, so if the outputs are in the wrong order it may not work.

– OdatNurd
Nov 13 '18 at 17:43





Can you include a sample of an error output? Along with file_regex there is also line_regex that can be paired with it for situations where the error output is on two lines. However it works by matching line_regex and then going backwards to get the file, so if the outputs are in the wrong order it may not work.

– OdatNurd
Nov 13 '18 at 17:43













@OdatNurd I've updated the question with an example error message. Thanks for the hint with line_regex, will look up what that is, didn't know about it.

– Andrey Tyukin
Nov 13 '18 at 19:00





@OdatNurd I've updated the question with an example error message. Thanks for the hint with line_regex, will look up what that is, didn't know about it.

– Andrey Tyukin
Nov 13 '18 at 19:00













line_regex doesn't seem to help here: it's only for the cases where file name and line/column are on different lines, but it does not help me to permute the matched groups into the right order.

– Andrey Tyukin
Nov 13 '18 at 19:06







line_regex doesn't seem to help here: it's only for the cases where file name and line/column are on different lines, but it does not help me to permute the matched groups into the right order.

– Andrey Tyukin
Nov 13 '18 at 19:06















Indeed so, unfortunately. Only the file_regex can match the name of the file, while the line_regex can match everything BUT the file; in use the two merge together but since it matches line and then goes backwards to get the file, the output of this is in the wrong order.

– OdatNurd
Nov 13 '18 at 19:18





Indeed so, unfortunately. Only the file_regex can match the name of the file, while the line_regex can match everything BUT the file; in use the two merge together but since it matches line and then goes backwards to get the file, the output of this is in the wrong order.

– OdatNurd
Nov 13 '18 at 19:18













In such a case as far as I'm aware the only way to get it to be able to determine the error message in this case is to massage the output of the tool to conform to what Sublime expects. If you're only interested in inline build errors and not clickable build results, it's possible with some work to modify the internal exec command to handle something like this, but that's more involved.

– OdatNurd
Nov 13 '18 at 19:20





In such a case as far as I'm aware the only way to get it to be able to determine the error message in this case is to massage the output of the tool to conform to what Sublime expects. If you're only interested in inline build errors and not clickable build results, it's possible with some work to modify the internal exec command to handle something like this, but that's more involved.

– OdatNurd
Nov 13 '18 at 19:20












2 Answers
2






active

oldest

votes


















1














The TL;DR version of the answer is that unfortunately I think the only way to get Sublime to recognize the error output in your question is to either make the tool generate output in a different format (either directly or by way of some filter app that sits in the middle) or by creating your own custom build target for your build that can recognize this error output (but it would only work for inline errors, see below).



Background



Build systems in Sublime Text have two regular expressions that can be applied to try and match error output/build results, file_regex and line_regex. Both are applied to the results of the build in the output panel in order to obtain the list of build results.



file_regex is the "general purpose" regex for matching build results, and should contain anywhere from 2 to 4 capture groups that capture the appropriate data. The capture groups (used in order) are filename, line, column, message.



line_regex is used in cases where the information about location of the error is on a different line than the error message/location. Here the captures are in the order line, column, message and you can use anywhere from 1 to 3 of them.



In both cases the captures are used in the order given above, which can necessitate having empty capture groups to make sure things line up as expected.



In normal use you just use file_regex and nothing else, and that captures the results for you. If you also use line_regex, then internally Sublime matches on line_regex instead, and then if it finds a match, it looks backwards through the result output for the first line that matches file_regex, and combines the results from the captures together.



Inherently this means that there are some restrictions placed on the sort of results that Sublime can capture; the file name has to appear prior to the other information about the error in order for it to be captured.



Massaging the output



In your example above, the error is displayed first and the location for the error is displayed second, so inherently there's no way to correctly associate the two regular expression matches together.



The most common way around this is to modify the output of the tool in order to rework it into a format that Sublime can detect with the above regular expressions.



For example you might change your build so that it executes your command and pipes the result to another shell script or program that can alter the information on the fly as it goes through. Another example would be to alter your build so that it invokes a script/batch file that executes the tool and does the output alteration internally, so that the final output matches what Sublime expects.



Custom build targets



Although there's no way to use the regex system to match your build output fully, if you're primarily interested in inline build errors being displayed, there is some recourse if you want to get your hands dirty with a little Sublime plugin development. In this case you need to know a bit of Python. There is documentation on custom build targets as well as the Sublime API available.



Internally, when you run a build, Sublime gathers the information from the sublime-build file, expands any variables in it, and then invokes the exec internal command to actually perform the build providing the keys in the sublime-build as arguments (some, such as selector, are not provided because Sublime handles that for you), and it's the exec command that sets the file_regex and line_regex settings into the output buffer.



From here, the applied settings are used by the Sublime core directly to perform navigation on build results, such as by clicking on the results to open the file, or using the navigation commands to go to the next and previous errors.



However, it's the exec command that is responsible for using those same results to show you the inline build errors, so it's possible to still get inline error messages working, although result navigation can only take you to the location in the file.



One of the keys that you can provide in a sublime-build file is target, which specifies the command that should execute the build; this defaults to exec if not given.



By creating your own custom command that mimics what exec does and using it in the target directive of your sublime-build, you can hook into the build process to capture the appropriate data.



The exec command is stored in Default/exec.py, which you can view by using the View Package File command from the command palette.



As a minimal example, the following plugin defines a new command named cargo_exec which exactly mimics what the exec command does. The call to self.output_view.find_all_results_with_text() is the API call that makes the Sublime core return all of the error information from the build output view, which is used to set up the phantoms used for inline build errors.



By modifying that code to examine the contents of the buffer and use your custom knowledge of what errors look like, the remainder of the code in the core exec command will display the inline errors for you.



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


To use this as a custom build target, you need to add a couple of extra keys to your sublime-build file:



// 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},





share|improve this answer
























  • That's impressive, but I somehow expected that passing four strings from one program to another shouldn't take much more than a single line of configuration. It even almost works without any massaging of the output: if rustc used print instead of println, it would work; likewise, had Sublime allowed to use multiline regex, then it would work too. I decided to use an AWK script to rewrite the error messages into the format that Sublime wants. It's ugly, but it fits into the said one (long) line, and it has no chance of sprawling into a "pet project" that will haunt me forever.

    – Andrey Tyukin
    Nov 14 '18 at 0:41













  • Indeed, this is one of the pitfalls of the current way this works and many are unhappy with it to some degree or another (including myself). Other failings include that even with the current system, items must appear in a certain order in file_regex or the capture groups don't capture what you expect.

    – OdatNurd
    Nov 14 '18 at 0:47











  • The order is not the problem: you can work around it using lookaheads, Sublime's regex flavor supports it (see second solution attempt in the question for an example: it reorders 4 1 2 3 into 1 2 3 4). Still, writing an entire plugin simply because of a whim of some compiler-writer who decided to add too many line breaks seems like a disproportionally heavyweight solution. I think it's not even really sublime's responsibility: configuring parsing is much harder than configuring formatted printout. It would be much easier to fix on the side that emits the error messages.

    – Andrey Tyukin
    Nov 14 '18 at 0:51













  • Anyway, I thank you for your effort and the detailed explanation. I will keep this answer in mind as a possible entry point into sublime plugin development.

    – Andrey Tyukin
    Nov 14 '18 at 0:53



















1














This AWK script combines the error message with the line numbers, and brings it into the order that Sublime wants:



awk 'BEGIN { errmsg="" } /error([E[0-9]+])?:.*/ {errmsg=$0; next} / *--> *.*/ { printf "%s::::%sn", $0, errmsg; next} {print $0}'


The output is trivially matched by the following regex:



error(?:[Ed+])?: (?=.+n +--> +([a-zA-Z0-9_/.-]+):([d]+):([d]+))(.+)


You can use | and AWK scripts inside the shell_cmd, so this build config captures all the error messages and displays them at the correct line numbers:



{
"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+)::::(.*)"
}


This also treats warnings in the same way:



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





share|improve this answer

























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53286429%2ffile-regex-for-cargo-builds-in-sublime-text-3%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    The TL;DR version of the answer is that unfortunately I think the only way to get Sublime to recognize the error output in your question is to either make the tool generate output in a different format (either directly or by way of some filter app that sits in the middle) or by creating your own custom build target for your build that can recognize this error output (but it would only work for inline errors, see below).



    Background



    Build systems in Sublime Text have two regular expressions that can be applied to try and match error output/build results, file_regex and line_regex. Both are applied to the results of the build in the output panel in order to obtain the list of build results.



    file_regex is the "general purpose" regex for matching build results, and should contain anywhere from 2 to 4 capture groups that capture the appropriate data. The capture groups (used in order) are filename, line, column, message.



    line_regex is used in cases where the information about location of the error is on a different line than the error message/location. Here the captures are in the order line, column, message and you can use anywhere from 1 to 3 of them.



    In both cases the captures are used in the order given above, which can necessitate having empty capture groups to make sure things line up as expected.



    In normal use you just use file_regex and nothing else, and that captures the results for you. If you also use line_regex, then internally Sublime matches on line_regex instead, and then if it finds a match, it looks backwards through the result output for the first line that matches file_regex, and combines the results from the captures together.



    Inherently this means that there are some restrictions placed on the sort of results that Sublime can capture; the file name has to appear prior to the other information about the error in order for it to be captured.



    Massaging the output



    In your example above, the error is displayed first and the location for the error is displayed second, so inherently there's no way to correctly associate the two regular expression matches together.



    The most common way around this is to modify the output of the tool in order to rework it into a format that Sublime can detect with the above regular expressions.



    For example you might change your build so that it executes your command and pipes the result to another shell script or program that can alter the information on the fly as it goes through. Another example would be to alter your build so that it invokes a script/batch file that executes the tool and does the output alteration internally, so that the final output matches what Sublime expects.



    Custom build targets



    Although there's no way to use the regex system to match your build output fully, if you're primarily interested in inline build errors being displayed, there is some recourse if you want to get your hands dirty with a little Sublime plugin development. In this case you need to know a bit of Python. There is documentation on custom build targets as well as the Sublime API available.



    Internally, when you run a build, Sublime gathers the information from the sublime-build file, expands any variables in it, and then invokes the exec internal command to actually perform the build providing the keys in the sublime-build as arguments (some, such as selector, are not provided because Sublime handles that for you), and it's the exec command that sets the file_regex and line_regex settings into the output buffer.



    From here, the applied settings are used by the Sublime core directly to perform navigation on build results, such as by clicking on the results to open the file, or using the navigation commands to go to the next and previous errors.



    However, it's the exec command that is responsible for using those same results to show you the inline build errors, so it's possible to still get inline error messages working, although result navigation can only take you to the location in the file.



    One of the keys that you can provide in a sublime-build file is target, which specifies the command that should execute the build; this defaults to exec if not given.



    By creating your own custom command that mimics what exec does and using it in the target directive of your sublime-build, you can hook into the build process to capture the appropriate data.



    The exec command is stored in Default/exec.py, which you can view by using the View Package File command from the command palette.



    As a minimal example, the following plugin defines a new command named cargo_exec which exactly mimics what the exec command does. The call to self.output_view.find_all_results_with_text() is the API call that makes the Sublime core return all of the error information from the build output view, which is used to set up the phantoms used for inline build errors.



    By modifying that code to examine the contents of the buffer and use your custom knowledge of what errors look like, the remainder of the code in the core exec command will display the inline errors for you.



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


    To use this as a custom build target, you need to add a couple of extra keys to your sublime-build file:



    // 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},





    share|improve this answer
























    • That's impressive, but I somehow expected that passing four strings from one program to another shouldn't take much more than a single line of configuration. It even almost works without any massaging of the output: if rustc used print instead of println, it would work; likewise, had Sublime allowed to use multiline regex, then it would work too. I decided to use an AWK script to rewrite the error messages into the format that Sublime wants. It's ugly, but it fits into the said one (long) line, and it has no chance of sprawling into a "pet project" that will haunt me forever.

      – Andrey Tyukin
      Nov 14 '18 at 0:41













    • Indeed, this is one of the pitfalls of the current way this works and many are unhappy with it to some degree or another (including myself). Other failings include that even with the current system, items must appear in a certain order in file_regex or the capture groups don't capture what you expect.

      – OdatNurd
      Nov 14 '18 at 0:47











    • The order is not the problem: you can work around it using lookaheads, Sublime's regex flavor supports it (see second solution attempt in the question for an example: it reorders 4 1 2 3 into 1 2 3 4). Still, writing an entire plugin simply because of a whim of some compiler-writer who decided to add too many line breaks seems like a disproportionally heavyweight solution. I think it's not even really sublime's responsibility: configuring parsing is much harder than configuring formatted printout. It would be much easier to fix on the side that emits the error messages.

      – Andrey Tyukin
      Nov 14 '18 at 0:51













    • Anyway, I thank you for your effort and the detailed explanation. I will keep this answer in mind as a possible entry point into sublime plugin development.

      – Andrey Tyukin
      Nov 14 '18 at 0:53
















    1














    The TL;DR version of the answer is that unfortunately I think the only way to get Sublime to recognize the error output in your question is to either make the tool generate output in a different format (either directly or by way of some filter app that sits in the middle) or by creating your own custom build target for your build that can recognize this error output (but it would only work for inline errors, see below).



    Background



    Build systems in Sublime Text have two regular expressions that can be applied to try and match error output/build results, file_regex and line_regex. Both are applied to the results of the build in the output panel in order to obtain the list of build results.



    file_regex is the "general purpose" regex for matching build results, and should contain anywhere from 2 to 4 capture groups that capture the appropriate data. The capture groups (used in order) are filename, line, column, message.



    line_regex is used in cases where the information about location of the error is on a different line than the error message/location. Here the captures are in the order line, column, message and you can use anywhere from 1 to 3 of them.



    In both cases the captures are used in the order given above, which can necessitate having empty capture groups to make sure things line up as expected.



    In normal use you just use file_regex and nothing else, and that captures the results for you. If you also use line_regex, then internally Sublime matches on line_regex instead, and then if it finds a match, it looks backwards through the result output for the first line that matches file_regex, and combines the results from the captures together.



    Inherently this means that there are some restrictions placed on the sort of results that Sublime can capture; the file name has to appear prior to the other information about the error in order for it to be captured.



    Massaging the output



    In your example above, the error is displayed first and the location for the error is displayed second, so inherently there's no way to correctly associate the two regular expression matches together.



    The most common way around this is to modify the output of the tool in order to rework it into a format that Sublime can detect with the above regular expressions.



    For example you might change your build so that it executes your command and pipes the result to another shell script or program that can alter the information on the fly as it goes through. Another example would be to alter your build so that it invokes a script/batch file that executes the tool and does the output alteration internally, so that the final output matches what Sublime expects.



    Custom build targets



    Although there's no way to use the regex system to match your build output fully, if you're primarily interested in inline build errors being displayed, there is some recourse if you want to get your hands dirty with a little Sublime plugin development. In this case you need to know a bit of Python. There is documentation on custom build targets as well as the Sublime API available.



    Internally, when you run a build, Sublime gathers the information from the sublime-build file, expands any variables in it, and then invokes the exec internal command to actually perform the build providing the keys in the sublime-build as arguments (some, such as selector, are not provided because Sublime handles that for you), and it's the exec command that sets the file_regex and line_regex settings into the output buffer.



    From here, the applied settings are used by the Sublime core directly to perform navigation on build results, such as by clicking on the results to open the file, or using the navigation commands to go to the next and previous errors.



    However, it's the exec command that is responsible for using those same results to show you the inline build errors, so it's possible to still get inline error messages working, although result navigation can only take you to the location in the file.



    One of the keys that you can provide in a sublime-build file is target, which specifies the command that should execute the build; this defaults to exec if not given.



    By creating your own custom command that mimics what exec does and using it in the target directive of your sublime-build, you can hook into the build process to capture the appropriate data.



    The exec command is stored in Default/exec.py, which you can view by using the View Package File command from the command palette.



    As a minimal example, the following plugin defines a new command named cargo_exec which exactly mimics what the exec command does. The call to self.output_view.find_all_results_with_text() is the API call that makes the Sublime core return all of the error information from the build output view, which is used to set up the phantoms used for inline build errors.



    By modifying that code to examine the contents of the buffer and use your custom knowledge of what errors look like, the remainder of the code in the core exec command will display the inline errors for you.



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


    To use this as a custom build target, you need to add a couple of extra keys to your sublime-build file:



    // 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},





    share|improve this answer
























    • That's impressive, but I somehow expected that passing four strings from one program to another shouldn't take much more than a single line of configuration. It even almost works without any massaging of the output: if rustc used print instead of println, it would work; likewise, had Sublime allowed to use multiline regex, then it would work too. I decided to use an AWK script to rewrite the error messages into the format that Sublime wants. It's ugly, but it fits into the said one (long) line, and it has no chance of sprawling into a "pet project" that will haunt me forever.

      – Andrey Tyukin
      Nov 14 '18 at 0:41













    • Indeed, this is one of the pitfalls of the current way this works and many are unhappy with it to some degree or another (including myself). Other failings include that even with the current system, items must appear in a certain order in file_regex or the capture groups don't capture what you expect.

      – OdatNurd
      Nov 14 '18 at 0:47











    • The order is not the problem: you can work around it using lookaheads, Sublime's regex flavor supports it (see second solution attempt in the question for an example: it reorders 4 1 2 3 into 1 2 3 4). Still, writing an entire plugin simply because of a whim of some compiler-writer who decided to add too many line breaks seems like a disproportionally heavyweight solution. I think it's not even really sublime's responsibility: configuring parsing is much harder than configuring formatted printout. It would be much easier to fix on the side that emits the error messages.

      – Andrey Tyukin
      Nov 14 '18 at 0:51













    • Anyway, I thank you for your effort and the detailed explanation. I will keep this answer in mind as a possible entry point into sublime plugin development.

      – Andrey Tyukin
      Nov 14 '18 at 0:53














    1












    1








    1







    The TL;DR version of the answer is that unfortunately I think the only way to get Sublime to recognize the error output in your question is to either make the tool generate output in a different format (either directly or by way of some filter app that sits in the middle) or by creating your own custom build target for your build that can recognize this error output (but it would only work for inline errors, see below).



    Background



    Build systems in Sublime Text have two regular expressions that can be applied to try and match error output/build results, file_regex and line_regex. Both are applied to the results of the build in the output panel in order to obtain the list of build results.



    file_regex is the "general purpose" regex for matching build results, and should contain anywhere from 2 to 4 capture groups that capture the appropriate data. The capture groups (used in order) are filename, line, column, message.



    line_regex is used in cases where the information about location of the error is on a different line than the error message/location. Here the captures are in the order line, column, message and you can use anywhere from 1 to 3 of them.



    In both cases the captures are used in the order given above, which can necessitate having empty capture groups to make sure things line up as expected.



    In normal use you just use file_regex and nothing else, and that captures the results for you. If you also use line_regex, then internally Sublime matches on line_regex instead, and then if it finds a match, it looks backwards through the result output for the first line that matches file_regex, and combines the results from the captures together.



    Inherently this means that there are some restrictions placed on the sort of results that Sublime can capture; the file name has to appear prior to the other information about the error in order for it to be captured.



    Massaging the output



    In your example above, the error is displayed first and the location for the error is displayed second, so inherently there's no way to correctly associate the two regular expression matches together.



    The most common way around this is to modify the output of the tool in order to rework it into a format that Sublime can detect with the above regular expressions.



    For example you might change your build so that it executes your command and pipes the result to another shell script or program that can alter the information on the fly as it goes through. Another example would be to alter your build so that it invokes a script/batch file that executes the tool and does the output alteration internally, so that the final output matches what Sublime expects.



    Custom build targets



    Although there's no way to use the regex system to match your build output fully, if you're primarily interested in inline build errors being displayed, there is some recourse if you want to get your hands dirty with a little Sublime plugin development. In this case you need to know a bit of Python. There is documentation on custom build targets as well as the Sublime API available.



    Internally, when you run a build, Sublime gathers the information from the sublime-build file, expands any variables in it, and then invokes the exec internal command to actually perform the build providing the keys in the sublime-build as arguments (some, such as selector, are not provided because Sublime handles that for you), and it's the exec command that sets the file_regex and line_regex settings into the output buffer.



    From here, the applied settings are used by the Sublime core directly to perform navigation on build results, such as by clicking on the results to open the file, or using the navigation commands to go to the next and previous errors.



    However, it's the exec command that is responsible for using those same results to show you the inline build errors, so it's possible to still get inline error messages working, although result navigation can only take you to the location in the file.



    One of the keys that you can provide in a sublime-build file is target, which specifies the command that should execute the build; this defaults to exec if not given.



    By creating your own custom command that mimics what exec does and using it in the target directive of your sublime-build, you can hook into the build process to capture the appropriate data.



    The exec command is stored in Default/exec.py, which you can view by using the View Package File command from the command palette.



    As a minimal example, the following plugin defines a new command named cargo_exec which exactly mimics what the exec command does. The call to self.output_view.find_all_results_with_text() is the API call that makes the Sublime core return all of the error information from the build output view, which is used to set up the phantoms used for inline build errors.



    By modifying that code to examine the contents of the buffer and use your custom knowledge of what errors look like, the remainder of the code in the core exec command will display the inline errors for you.



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


    To use this as a custom build target, you need to add a couple of extra keys to your sublime-build file:



    // 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},





    share|improve this answer













    The TL;DR version of the answer is that unfortunately I think the only way to get Sublime to recognize the error output in your question is to either make the tool generate output in a different format (either directly or by way of some filter app that sits in the middle) or by creating your own custom build target for your build that can recognize this error output (but it would only work for inline errors, see below).



    Background



    Build systems in Sublime Text have two regular expressions that can be applied to try and match error output/build results, file_regex and line_regex. Both are applied to the results of the build in the output panel in order to obtain the list of build results.



    file_regex is the "general purpose" regex for matching build results, and should contain anywhere from 2 to 4 capture groups that capture the appropriate data. The capture groups (used in order) are filename, line, column, message.



    line_regex is used in cases where the information about location of the error is on a different line than the error message/location. Here the captures are in the order line, column, message and you can use anywhere from 1 to 3 of them.



    In both cases the captures are used in the order given above, which can necessitate having empty capture groups to make sure things line up as expected.



    In normal use you just use file_regex and nothing else, and that captures the results for you. If you also use line_regex, then internally Sublime matches on line_regex instead, and then if it finds a match, it looks backwards through the result output for the first line that matches file_regex, and combines the results from the captures together.



    Inherently this means that there are some restrictions placed on the sort of results that Sublime can capture; the file name has to appear prior to the other information about the error in order for it to be captured.



    Massaging the output



    In your example above, the error is displayed first and the location for the error is displayed second, so inherently there's no way to correctly associate the two regular expression matches together.



    The most common way around this is to modify the output of the tool in order to rework it into a format that Sublime can detect with the above regular expressions.



    For example you might change your build so that it executes your command and pipes the result to another shell script or program that can alter the information on the fly as it goes through. Another example would be to alter your build so that it invokes a script/batch file that executes the tool and does the output alteration internally, so that the final output matches what Sublime expects.



    Custom build targets



    Although there's no way to use the regex system to match your build output fully, if you're primarily interested in inline build errors being displayed, there is some recourse if you want to get your hands dirty with a little Sublime plugin development. In this case you need to know a bit of Python. There is documentation on custom build targets as well as the Sublime API available.



    Internally, when you run a build, Sublime gathers the information from the sublime-build file, expands any variables in it, and then invokes the exec internal command to actually perform the build providing the keys in the sublime-build as arguments (some, such as selector, are not provided because Sublime handles that for you), and it's the exec command that sets the file_regex and line_regex settings into the output buffer.



    From here, the applied settings are used by the Sublime core directly to perform navigation on build results, such as by clicking on the results to open the file, or using the navigation commands to go to the next and previous errors.



    However, it's the exec command that is responsible for using those same results to show you the inline build errors, so it's possible to still get inline error messages working, although result navigation can only take you to the location in the file.



    One of the keys that you can provide in a sublime-build file is target, which specifies the command that should execute the build; this defaults to exec if not given.



    By creating your own custom command that mimics what exec does and using it in the target directive of your sublime-build, you can hook into the build process to capture the appropriate data.



    The exec command is stored in Default/exec.py, which you can view by using the View Package File command from the command palette.



    As a minimal example, the following plugin defines a new command named cargo_exec which exactly mimics what the exec command does. The call to self.output_view.find_all_results_with_text() is the API call that makes the Sublime core return all of the error information from the build output view, which is used to set up the phantoms used for inline build errors.



    By modifying that code to examine the contents of the buffer and use your custom knowledge of what errors look like, the remainder of the code in the core exec command will display the inline errors for you.



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


    To use this as a custom build target, you need to add a couple of extra keys to your sublime-build file:



    // 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},






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Nov 13 '18 at 20:38









    OdatNurdOdatNurd

    8,96522335




    8,96522335













    • That's impressive, but I somehow expected that passing four strings from one program to another shouldn't take much more than a single line of configuration. It even almost works without any massaging of the output: if rustc used print instead of println, it would work; likewise, had Sublime allowed to use multiline regex, then it would work too. I decided to use an AWK script to rewrite the error messages into the format that Sublime wants. It's ugly, but it fits into the said one (long) line, and it has no chance of sprawling into a "pet project" that will haunt me forever.

      – Andrey Tyukin
      Nov 14 '18 at 0:41













    • Indeed, this is one of the pitfalls of the current way this works and many are unhappy with it to some degree or another (including myself). Other failings include that even with the current system, items must appear in a certain order in file_regex or the capture groups don't capture what you expect.

      – OdatNurd
      Nov 14 '18 at 0:47











    • The order is not the problem: you can work around it using lookaheads, Sublime's regex flavor supports it (see second solution attempt in the question for an example: it reorders 4 1 2 3 into 1 2 3 4). Still, writing an entire plugin simply because of a whim of some compiler-writer who decided to add too many line breaks seems like a disproportionally heavyweight solution. I think it's not even really sublime's responsibility: configuring parsing is much harder than configuring formatted printout. It would be much easier to fix on the side that emits the error messages.

      – Andrey Tyukin
      Nov 14 '18 at 0:51













    • Anyway, I thank you for your effort and the detailed explanation. I will keep this answer in mind as a possible entry point into sublime plugin development.

      – Andrey Tyukin
      Nov 14 '18 at 0:53



















    • That's impressive, but I somehow expected that passing four strings from one program to another shouldn't take much more than a single line of configuration. It even almost works without any massaging of the output: if rustc used print instead of println, it would work; likewise, had Sublime allowed to use multiline regex, then it would work too. I decided to use an AWK script to rewrite the error messages into the format that Sublime wants. It's ugly, but it fits into the said one (long) line, and it has no chance of sprawling into a "pet project" that will haunt me forever.

      – Andrey Tyukin
      Nov 14 '18 at 0:41













    • Indeed, this is one of the pitfalls of the current way this works and many are unhappy with it to some degree or another (including myself). Other failings include that even with the current system, items must appear in a certain order in file_regex or the capture groups don't capture what you expect.

      – OdatNurd
      Nov 14 '18 at 0:47











    • The order is not the problem: you can work around it using lookaheads, Sublime's regex flavor supports it (see second solution attempt in the question for an example: it reorders 4 1 2 3 into 1 2 3 4). Still, writing an entire plugin simply because of a whim of some compiler-writer who decided to add too many line breaks seems like a disproportionally heavyweight solution. I think it's not even really sublime's responsibility: configuring parsing is much harder than configuring formatted printout. It would be much easier to fix on the side that emits the error messages.

      – Andrey Tyukin
      Nov 14 '18 at 0:51













    • Anyway, I thank you for your effort and the detailed explanation. I will keep this answer in mind as a possible entry point into sublime plugin development.

      – Andrey Tyukin
      Nov 14 '18 at 0:53

















    That's impressive, but I somehow expected that passing four strings from one program to another shouldn't take much more than a single line of configuration. It even almost works without any massaging of the output: if rustc used print instead of println, it would work; likewise, had Sublime allowed to use multiline regex, then it would work too. I decided to use an AWK script to rewrite the error messages into the format that Sublime wants. It's ugly, but it fits into the said one (long) line, and it has no chance of sprawling into a "pet project" that will haunt me forever.

    – Andrey Tyukin
    Nov 14 '18 at 0:41







    That's impressive, but I somehow expected that passing four strings from one program to another shouldn't take much more than a single line of configuration. It even almost works without any massaging of the output: if rustc used print instead of println, it would work; likewise, had Sublime allowed to use multiline regex, then it would work too. I decided to use an AWK script to rewrite the error messages into the format that Sublime wants. It's ugly, but it fits into the said one (long) line, and it has no chance of sprawling into a "pet project" that will haunt me forever.

    – Andrey Tyukin
    Nov 14 '18 at 0:41















    Indeed, this is one of the pitfalls of the current way this works and many are unhappy with it to some degree or another (including myself). Other failings include that even with the current system, items must appear in a certain order in file_regex or the capture groups don't capture what you expect.

    – OdatNurd
    Nov 14 '18 at 0:47





    Indeed, this is one of the pitfalls of the current way this works and many are unhappy with it to some degree or another (including myself). Other failings include that even with the current system, items must appear in a certain order in file_regex or the capture groups don't capture what you expect.

    – OdatNurd
    Nov 14 '18 at 0:47













    The order is not the problem: you can work around it using lookaheads, Sublime's regex flavor supports it (see second solution attempt in the question for an example: it reorders 4 1 2 3 into 1 2 3 4). Still, writing an entire plugin simply because of a whim of some compiler-writer who decided to add too many line breaks seems like a disproportionally heavyweight solution. I think it's not even really sublime's responsibility: configuring parsing is much harder than configuring formatted printout. It would be much easier to fix on the side that emits the error messages.

    – Andrey Tyukin
    Nov 14 '18 at 0:51







    The order is not the problem: you can work around it using lookaheads, Sublime's regex flavor supports it (see second solution attempt in the question for an example: it reorders 4 1 2 3 into 1 2 3 4). Still, writing an entire plugin simply because of a whim of some compiler-writer who decided to add too many line breaks seems like a disproportionally heavyweight solution. I think it's not even really sublime's responsibility: configuring parsing is much harder than configuring formatted printout. It would be much easier to fix on the side that emits the error messages.

    – Andrey Tyukin
    Nov 14 '18 at 0:51















    Anyway, I thank you for your effort and the detailed explanation. I will keep this answer in mind as a possible entry point into sublime plugin development.

    – Andrey Tyukin
    Nov 14 '18 at 0:53





    Anyway, I thank you for your effort and the detailed explanation. I will keep this answer in mind as a possible entry point into sublime plugin development.

    – Andrey Tyukin
    Nov 14 '18 at 0:53













    1














    This AWK script combines the error message with the line numbers, and brings it into the order that Sublime wants:



    awk 'BEGIN { errmsg="" } /error([E[0-9]+])?:.*/ {errmsg=$0; next} / *--> *.*/ { printf "%s::::%sn", $0, errmsg; next} {print $0}'


    The output is trivially matched by the following regex:



    error(?:[Ed+])?: (?=.+n +--> +([a-zA-Z0-9_/.-]+):([d]+):([d]+))(.+)


    You can use | and AWK scripts inside the shell_cmd, so this build config captures all the error messages and displays them at the correct line numbers:



    {
    "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+)::::(.*)"
    }


    This also treats warnings in the same way:



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





    share|improve this answer






























      1














      This AWK script combines the error message with the line numbers, and brings it into the order that Sublime wants:



      awk 'BEGIN { errmsg="" } /error([E[0-9]+])?:.*/ {errmsg=$0; next} / *--> *.*/ { printf "%s::::%sn", $0, errmsg; next} {print $0}'


      The output is trivially matched by the following regex:



      error(?:[Ed+])?: (?=.+n +--> +([a-zA-Z0-9_/.-]+):([d]+):([d]+))(.+)


      You can use | and AWK scripts inside the shell_cmd, so this build config captures all the error messages and displays them at the correct line numbers:



      {
      "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+)::::(.*)"
      }


      This also treats warnings in the same way:



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





      share|improve this answer




























        1












        1








        1







        This AWK script combines the error message with the line numbers, and brings it into the order that Sublime wants:



        awk 'BEGIN { errmsg="" } /error([E[0-9]+])?:.*/ {errmsg=$0; next} / *--> *.*/ { printf "%s::::%sn", $0, errmsg; next} {print $0}'


        The output is trivially matched by the following regex:



        error(?:[Ed+])?: (?=.+n +--> +([a-zA-Z0-9_/.-]+):([d]+):([d]+))(.+)


        You can use | and AWK scripts inside the shell_cmd, so this build config captures all the error messages and displays them at the correct line numbers:



        {
        "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+)::::(.*)"
        }


        This also treats warnings in the same way:



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





        share|improve this answer















        This AWK script combines the error message with the line numbers, and brings it into the order that Sublime wants:



        awk 'BEGIN { errmsg="" } /error([E[0-9]+])?:.*/ {errmsg=$0; next} / *--> *.*/ { printf "%s::::%sn", $0, errmsg; next} {print $0}'


        The output is trivially matched by the following regex:



        error(?:[Ed+])?: (?=.+n +--> +([a-zA-Z0-9_/.-]+):([d]+):([d]+))(.+)


        You can use | and AWK scripts inside the shell_cmd, so this build config captures all the error messages and displays them at the correct line numbers:



        {
        "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+)::::(.*)"
        }


        This also treats warnings in the same way:



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






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 15 '18 at 22:02

























        answered Nov 14 '18 at 0:27









        Andrey TyukinAndrey Tyukin

        27.2k42349




        27.2k42349






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53286429%2ffile-regex-for-cargo-builds-in-sublime-text-3%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            這個網誌中的熱門文章

            Post-Redirect-Get with Spring WebFlux and Thymeleaf

            Xamarin.form Move up view when keyboard appear

            JBPM : POST request for execute process go wrong