diff --git a/cslog/clearline.go b/cslog/clearline.go new file mode 100644 index 0000000..9af53ba --- /dev/null +++ b/cslog/clearline.go @@ -0,0 +1,24 @@ +package cslog + +import ( + log "github.com/sirupsen/logrus" +) + +// ClearLineFormatter is a logrus formatter that clears each line before printing +// used in cases where the log line is updated in place (e.g. progress bar) +// +// Make sure the logger is set to print on a terminal before using this or it will +// pollute the log with control characters. +type ClearLineFormatter struct { + log.TextFormatter +} + +func (f *ClearLineFormatter) Format(entry *log.Entry) ([]byte, error) { + const clearLine = "\r\033[K" + + result, err := f.TextFormatter.Format(entry) + if err != nil { + return nil, err + } + return append([]byte(clearLine), result...), nil +} diff --git a/cstty/tty.go b/cstty/tty.go new file mode 100644 index 0000000..8837346 --- /dev/null +++ b/cstty/tty.go @@ -0,0 +1,10 @@ +package cstty + +import ( + isatty "github.com/mattn/go-isatty" +) + +// IsTTY returns true if the given file is an interactive terminal. +func IsTTY(fd uintptr) bool { + return isatty.IsTerminal(fd) || isatty.IsCygwinTerminal(fd) +} diff --git a/cstty/vt_unix.go b/cstty/vt_unix.go new file mode 100644 index 0000000..d2e0ee4 --- /dev/null +++ b/cstty/vt_unix.go @@ -0,0 +1,7 @@ +//go:build unix + +package cstty + +func EnableVirtualTerminalProcessing(fd uintptr) error { + return nil +} diff --git a/cstty/vt_windows.go b/cstty/vt_windows.go new file mode 100644 index 0000000..9ac2e30 --- /dev/null +++ b/cstty/vt_windows.go @@ -0,0 +1,17 @@ +package cstty + +import ( + "golang.org/x/sys/windows" +) + +// EnableVirtualTerminalProcessing enables ANSI sequences on a given file descriptor. +// This only works on Windows 10+ but we can't do anything about older versions. +func EnableVirtualTerminalProcessing(fd uintptr) error { + var mode uint32 + handle := windows.Handle(fd) + if err := windows.GetConsoleMode(handle, &mode); err != nil { + return err + } + mode |= windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING + return windows.SetConsoleMode(handle, mode) +} diff --git a/go.mod b/go.mod index e944853..ce6774d 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.20 require ( github.com/coreos/go-systemd/v22 v22.5.0 + github.com/mattn/go-isatty v0.0.20 github.com/sirupsen/logrus v1.9.3 github.com/stretchr/testify v1.8.4 gopkg.in/yaml.v2 v2.4.0 diff --git a/go.sum b/go.sum index 16ddd2c..3b4b0b3 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= @@ -13,6 +15,7 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=