Thanks so much for the kind words, glad I could help!
When builds use shell_cmd
, behind the scenes the system’s command interpreter (bash
on Linux/MacOS or cmd
on Windows) is executed and told “please execute this command”. The command interpreter knows how to do things like chain multiple commands together and such.
In contrast, cmd
indicates that the first item in the list is the program to execute and the remainder of the items are arguments for that program when it’s executed. Terminus works the same way, and so unless the program being executed (here g++
) knows how to run multiple commands, that doesn’t work. Essentially you’re just providing extra arguments to g++
and it gets confused about what you meant.
The normal advice would be that if you want to run multiple commands or otherwise take advantage of the features of the command interpreter (such as piping output and input) you should use either shell_cmd
, or use cmd
and also provide "shell": true
in the build, which makes the internal exec
command convert the cmd
into a shell_cmd
behind the scenes (more or less).
Terminus only supports cmd
and doesn’t handle the "shell": true
part of the build, so to use Terminus like this you need to manually do behind the scenes what shell_cmd
is doing, which is to run the command interpreter for the system and give it a command to run.
An example of that would be:
{
"target": "terminus_open",
"cmd": ["/usr/bin/env", "bash", "-c", "g++ -o \"${file_path}/${file_base_name}\" \"${file}\" && \"${file_path}/${file_base_name}\""],
"working_dir": "${file_path}",
"auto_close": false,
"selector": "source.c, source.c++",
}
Here we’re telling Terminus to use /usr/bin/env
to locate the bash
interpreter, and then execute bash
and provide it two arguments; the first is -c
to tell it that it should execute the next argument as a command, and the second is the actual command line (essentially what you’d put into shell_cmd
). The /usr/bin/env
part is a safeguard that bash
will be found; you could leave that part out and start the command with bash
directly as well if you know that bash
is in the PATH
.
The example here uses ${file_path}/${file_base_name}
to create an executable that’s the same name and location as the input source file (but with no extension), and the &&
instructs bash to only try to execute the program if it compiled correctly. You can use a hardcoded name as in your example above as well; doing it as above ensures that if you’re working on multiple programs once you compile something, it remains there for you to run manually later.
The above example is for Linux; if you want to do something like this on MacOS you would instead use:
"cmd": ["/usr/bin/env", "bash", "-l", "-c", "....."]
Essentially the same as above with with the addition of an extra argument to tell Bash to run as a login shell so that on MacOS it will pick up the correct environment.
For windows, the command would be:
"cmd": ["cmd", "/c", "..."]