script.Exec - no colours on stdout
indaco opened this issue · 6 comments
Executing system commands printing colourful messages on stdout, the output does not preserve the colours.
_, err:= script.Exec("npm install").Stdout()How to do that?
Thanks
Hi, @indaco, thanks for the report!
Most programs that produce coloured output can also detect whether or not they're talking to an interactive terminal (for example, gotestdox. If not, they reason, there is no point producing colour codes, since it only makes sense to set colours when the output goes to a terminal.
In this case, the output of npm install is not going to a terminal, so it has presumably decided not to use colour mode. There may be ways to change its mind. Have you tried setting the FORCE_COLOR variable as described here? nodejs/node#37404
Hi @bitfield thanks for the proper response.
For sure, I'm in wrong but...the reason why I am asking how to achieve it with script is simply because, using something like
package main
func ExecCmd(cmdName string, cmdOptions string, silentMode bool) error {
var cmd *exec.Cmd
args := strings.Split(cmdOptions, " ")
cmd = exec.Command(cmdName, args[0:]...)
cmd.Stderr = os.Stderr
if !silentMode {
cmd.Stdout = os.Stdout
}
err := cmd.Start()
if err != nil {
return err
}
return cmd.Wait()
}I got the output with colours preserved.
if you try it with e.g. pnpm install you will see the colours
err := ExecCmd("pnpm", "install", false)
if err != nil {
fmt.Println(err.Error())
}What am I missing?
Your code sets the command's Stdout stream to os.Stdout... which is a terminal! (At least, it will be when you run this program from the command line.) So when the program asks "Is my standard output an interactive terminal?", the answer is yes.
By contrast, in a script pipeline, the command's Stdout stream is always the pipe—which is the point of script, of course.
script is not doing anything special here; it just reads bytes and passes them on. If the originating command decides to send bytes corresponding to ANSI terminal control codes, script will faithfully reproduce them. If not, not. Does that help explain what's going on?
Got the point, I guess, thanks.
One more...
My initial thought was
pipe := script.NewPipe().WithStdout(os.Stdout)
pipe.exec("...").Stdout()would get the same result of my code, then going thought the documentation
func (p *Pipe) WithStdout(w io.Writer) *Pipe
sets the pipe's standard output to the writer w, instead of the default os.Stdout
Does it mean the default Stdout stream is set to os.Stdout, right? Is this not the same as set the command's Stdout stream to os.Stdout?
I am missing something, no doubts...buggy brain
WithStdout sets the pipe's standard output (that is, where things will go when you call Stdout). That already defaults to os.Stdout, which makes sense.
This has no effect on the standard output of commands run by Exec.
If setting FORCE_COLOR solves your problem, I'll be happy to hear about it.
yes, setting FORCE_COLOR solves the problem, I was sure about that!
I was trying to understand...anyhow, thanks for your time and for the script package. I'm going to replace my custom code with it.