From aac2406e195cedf50d67d89b4c8658e09d14b76c Mon Sep 17 00:00:00 2001 From: LaSombra Date: Tue, 6 Oct 2020 16:34:26 +0100 Subject: [PATCH] cmd: add --progress-terminal-title to print ETA to terminal title Adds a flag, --progress-terminal-title, that when used with --progress, will print the string `ETA: %s` to the terminal title. This also adds WriteTerminalTitle to lib/terminal --- cmd/cmd.go | 6 ++++++ docs/content/docs.md | 5 +++++ fs/accounting/stats.go | 6 ++++++ fs/config.go | 1 + fs/config/configflags/configflags.go | 1 + lib/terminal/terminal.go | 3 +++ lib/terminal/terminal_normal.go | 6 ++++++ lib/terminal/terminal_unsupported.go | 5 +++++ 8 files changed, 33 insertions(+) diff --git a/cmd/cmd.go b/cmd/cmd.go index 2535b5f94..ca01ecf1d 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -36,6 +36,7 @@ import ( "github.com/rclone/rclone/fs/rc/rcflags" "github.com/rclone/rclone/fs/rc/rcserver" "github.com/rclone/rclone/lib/atexit" + "github.com/rclone/rclone/lib/terminal" "github.com/spf13/cobra" "github.com/spf13/pflag" ) @@ -289,6 +290,11 @@ func Run(Retry bool, showStats bool, cmd *cobra.Command, f func() error) { } fs.Debugf(nil, "%d go routines active\n", runtime.NumGoroutine()) + if fs.Config.Progress && fs.Config.ProgressTerminalTitle { + // Clear terminal title + terminal.WriteTerminalTitle("") + } + // dump all running go-routines if fs.Config.Dump&fs.DumpGoRoutines != 0 { err := pprof.Lookup("goroutine").WriteTo(os.Stdout, 1) diff --git a/docs/content/docs.md b/docs/content/docs.md index 6ff3264c2..f08ecb64d 100644 --- a/docs/content/docs.md +++ b/docs/content/docs.md @@ -1108,6 +1108,11 @@ Note: On Windows until [this bug](https://github.com/Azure/go-ansiterm/issues/26 is fixed all non-ASCII characters will be replaced with `.` when `--progress` is in use. +### --progress-terminal-title ### + +This flag, when used with `-P/--progress`, will print the string `ETA: %s` +to the terminal title. + ### -q, --quiet ### This flag will limit rclone's output to error messages only. diff --git a/fs/accounting/stats.go b/fs/accounting/stats.go index fbea0114f..0c5ee2903 100644 --- a/fs/accounting/stats.go +++ b/fs/accounting/stats.go @@ -11,6 +11,7 @@ import ( "github.com/rclone/rclone/fs" "github.com/rclone/rclone/fs/fserrors" "github.com/rclone/rclone/fs/rc" + "github.com/rclone/rclone/lib/terminal" ) // MaxCompletedTransfers specifies maximum number of completed transfers in startedTransfers list @@ -282,6 +283,11 @@ func (s *StatsInfo) String() string { xfrchkString, ) + if fs.Config.ProgressTerminalTitle { + // Writes ETA to the terminal title + terminal.WriteTerminalTitle("ETA: " + etaString(currentSize, totalSize, speed)) + } + if !fs.Config.StatsOneLine { _, _ = buf.WriteRune('\n') errorDetails := "" diff --git a/fs/config.go b/fs/config.go index d1fe41102..7b10dce13 100644 --- a/fs/config.go +++ b/fs/config.go @@ -107,6 +107,7 @@ type ConfigInfo struct { StatsOneLineDateFormat string // If we want to customize the prefix ErrorOnNoTransfer bool // Set appropriate exit code if no files transferred Progress bool + ProgressTerminalTitle bool Cookie bool UseMmap bool CaCert string // Client Side CA diff --git a/fs/config/configflags/configflags.go b/fs/config/configflags/configflags.go index 08cd74b39..1933ab905 100644 --- a/fs/config/configflags/configflags.go +++ b/fs/config/configflags/configflags.go @@ -110,6 +110,7 @@ func AddFlags(flagSet *pflag.FlagSet) { flags.StringVarP(flagSet, &fs.Config.StatsOneLineDateFormat, "stats-one-line-date-format", "", fs.Config.StatsOneLineDateFormat, "Enables --stats-one-line-date and uses custom formatted date. Enclose date string in double quotes (\"). See https://golang.org/pkg/time/#Time.Format") flags.BoolVarP(flagSet, &fs.Config.ErrorOnNoTransfer, "error-on-no-transfer", "", fs.Config.ErrorOnNoTransfer, "Sets exit code 9 if no files are transferred, useful in scripts") flags.BoolVarP(flagSet, &fs.Config.Progress, "progress", "P", fs.Config.Progress, "Show progress during transfer.") + flags.BoolVarP(flagSet, &fs.Config.ProgressTerminalTitle, "progress-terminal-title", "", fs.Config.ProgressTerminalTitle, "Show progress on the terminal title. Requires -P/--progress.") flags.BoolVarP(flagSet, &fs.Config.Cookie, "use-cookies", "", fs.Config.Cookie, "Enable session cookiejar.") flags.BoolVarP(flagSet, &fs.Config.UseMmap, "use-mmap", "", fs.Config.UseMmap, "Use mmap allocator (see docs).") flags.StringVarP(flagSet, &fs.Config.CaCert, "ca-cert", "", fs.Config.CaCert, "CA certificate used to verify servers") diff --git a/lib/terminal/terminal.go b/lib/terminal/terminal.go index d29931380..b3007a93b 100644 --- a/lib/terminal/terminal.go +++ b/lib/terminal/terminal.go @@ -60,6 +60,9 @@ const ( HiMagentaBg = "\x1b[105m" HiCyanBg = "\x1b[106m" HiWhiteBg = "\x1b[107m" + + ChangeTitle = "\033]0;" + BEL = "\007" ) var ( diff --git a/lib/terminal/terminal_normal.go b/lib/terminal/terminal_normal.go index 787054eed..d8531ebf5 100644 --- a/lib/terminal/terminal_normal.go +++ b/lib/terminal/terminal_normal.go @@ -3,6 +3,7 @@ package terminal import ( + "fmt" "os" "golang.org/x/crypto/ssh/terminal" @@ -29,3 +30,8 @@ func IsTerminal(fd int) bool { func ReadPassword(fd int) ([]byte, error) { return terminal.ReadPassword(fd) } + +// WriteTerminalTitle writes a string to the terminal title +func WriteTerminalTitle(title string) { + fmt.Printf(ChangeTitle + title + BEL) +} diff --git a/lib/terminal/terminal_unsupported.go b/lib/terminal/terminal_unsupported.go index bd70d3409..d26fb6291 100644 --- a/lib/terminal/terminal_unsupported.go +++ b/lib/terminal/terminal_unsupported.go @@ -21,3 +21,8 @@ func IsTerminal(fd int) bool { func ReadPassword(fd int) ([]byte, error) { return nil, errors.New("can't read password") } + +// WriteTerminalTitle writes a string to the terminal title +func WriteTerminalTitle(title string) { + // Since there's nothing to return, this is a NOOP +}