From 3641993fab4741be4cc0bdd3f2c06021d96d53c5 Mon Sep 17 00:00:00 2001 From: albertony <12441419+albertony@users.noreply.github.com> Date: Wed, 1 Mar 2023 23:27:41 +0100 Subject: [PATCH] tree: fix colored output on windows Since rclone version 1.61.0 the tree command uses ANSI color sequences in output by default, but this lead to issues in Windows terminals that were not handling these (#6668). This commit ensures the tree command uses the terminal package for output. It relies on go-colorable to properly handle ANSI color sequences: If stdout is connected to a terminal the escape sequences are decoded and the text are written with color formatting using Windows Console API. If stdout is not connected to a terminal, e.g. redirected to file, the escape sequences are stripped off. The tree command has its own method for writing directly to a file, specified with flag --output, and then the output is not passed through the terminal package and must therefore be written without ansi codes. --- cmd/tree/tree.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/cmd/tree/tree.go b/cmd/tree/tree.go index ca2999aac..967270b8c 100644 --- a/cmd/tree/tree.go +++ b/cmd/tree/tree.go @@ -18,6 +18,7 @@ import ( "github.com/rclone/rclone/fs/dirtree" "github.com/rclone/rclone/fs/log" "github.com/rclone/rclone/fs/walk" + "github.com/rclone/rclone/lib/terminal" "github.com/spf13/cobra" ) @@ -100,22 +101,26 @@ For a more interactive navigation of the remote see the RunE: func(command *cobra.Command, args []string) error { cmd.CheckArgs(1, 1, command, args) fsrc := cmd.NewFsSrc(args) - outFile := os.Stdout + ci := fs.GetConfig(context.Background()) + var outFile io.Writer if outFileName != "" { var err error outFile, err = os.Create(outFileName) if err != nil { return fmt.Errorf("failed to create output file: %w", err) } + opts.Colorize = false + } else { + terminal.Start() + outFile = terminal.Out + opts.Colorize = true } opts.VerSort = opts.VerSort || sort == "version" opts.ModSort = opts.ModSort || sort == "mtime" opts.CTimeSort = opts.CTimeSort || sort == "ctime" opts.NameSort = sort == "name" opts.SizeSort = sort == "size" - ci := fs.GetConfig(context.Background()) opts.UnitSize = ci.HumanReadable - opts.Colorize = ci.TerminalColorMode != fs.TerminalColorModeNever if opts.DeepLevel == 0 { opts.DeepLevel = ci.MaxDepth }