From 1774262106e03ab9315fdc750ecb396286030fb6 Mon Sep 17 00:00:00 2001 From: Scott Ames Date: Sun, 23 Apr 2023 11:33:10 -0700 Subject: [PATCH] feat: logger print command fit in term width --- README.md | 6 +++-- go.mod | 2 ++ go.sum | 4 ++++ pkg/log/logger.go | 58 ++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 67 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 49e235a..b95f648 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Additionally many of the tests can provide some example usage. ### Logging -Cmder logs all commands being run using the specified, using the `Logger` method, logger which implements the [`Logger`](https://github.com/scottames/cmder/blob/master/pkg/log/logger.go#L10-L27) interface. +Cmder logs all commands being run, using the `Logger` method, which implements the [`Logger`](https://github.com/scottames/cmder/blob/master/pkg/log/logger.go#L10-L27) interface: ```golang type Logger interface { @@ -43,12 +43,14 @@ type Logger interface { } ``` -By default (if none specified with the `Logger` method) the built-in logger will be used. See Additional `log.Logger*` variables for configuration +By default (if none specified with the `Cmder.Logger()` method) the built-in [logger](pkg/log/logger.go) will be used. See Additional `log.Logger*` variables for configuration options. Color is disabled by default, but can be enabled by setting either `MAGEFILE_ENABLE_COLOR` or `CMDER_ENABLE_COLOR` environment variables to true. +The default logger will check the terminal width and if the command to be printed is wider than the terminal width, it will be broken up into multiple lines, similar to a shell command represented on multiple lines. + ## Contributing See [CONTRIBUTING.md](CONTRIBUTING.md). Contributors should follow the [Go Community Code of Conduct diff --git a/go.mod b/go.mod index 9c245f1..26acf93 100644 --- a/go.mod +++ b/go.mod @@ -6,10 +6,12 @@ require ( github.com/go-test/deep v1.1.0 github.com/magefile/mage v1.14.0 github.com/stretchr/testify v1.8.2 + golang.org/x/term v0.7.0 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/sys v0.7.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index f9fcae2..1f124ef 100644 --- a/go.sum +++ b/go.sum @@ -14,6 +14,10 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/log/logger.go b/pkg/log/logger.go index 800352b..47734b3 100644 --- a/pkg/log/logger.go +++ b/pkg/log/logger.go @@ -4,7 +4,10 @@ import ( "fmt" "os" "strconv" + "strings" "time" + + "golang.org/x/term" ) // Logger is a generic logging interface @@ -176,12 +179,65 @@ func (l logger) Logf(format string, v ...interface{}) { fmt.Printf(s+format+timestamp+"\n", v...) } +// splitArgsToNewLine returns a new string formatted as a shell command as if being executed +// on multiple lines - padding between the [] of the command (slice) to be printed +func splitArgsToNewLine(s string) string { + var result string + + const ( + bBracket = "[" + eBracket = "]" + ) + + newArgs := []string{} + args := strings.Split(s, " ") + + for _, w := range args { + if strings.HasPrefix(w, bBracket) { + w = strings.Replace(w, bBracket, bBracket+"\n\n ", 1) + } + + if strings.HasSuffix(w, eBracket) { + i := strings.LastIndex(w, eBracket) + w = w[:i] + strings.Replace(w[i:], eBracket, "\n\n"+eBracket, 1) + } + + if strings.Contains(w, eBracket+string(LoggerColor)) { + w = strings.Replace(w, eBracket+string(LoggerColor), "\n\n"+eBracket+string(LoggerColor), 1) + } + + if strings.HasPrefix(w, "-") { + newArgs = append(newArgs, "\\\n "+w) + } else { + newArgs = append(newArgs, w) + } + } + + result = strings.Join(newArgs, " ") + + return result +} + +// stringLen returns the length of a given string +func stringLen(s string) int { + return len([]rune(s)) +} + // Log implements the Logger interface func (l logger) Log(v ...interface{}) { s := l.prependStr() timestamp := l.timestamp(string(LoggerDarkGrey)) + msg := fmt.Sprintf("%v", v...) + + termWidth, _, err := term.GetSize(int(os.Stdin.Fd())) + if err == nil { + absLen := stringLen(msg) + stringLen(s) + stringLen(timestamp) + if absLen > termWidth { + msg = splitArgsToNewLine(msg) + } + } - fmt.Printf(s+"%v"+timestamp+"\n", v...) + fmt.Printf(s+"%s"+timestamp+"\n", msg) } func (l logger) prependStr() string {