From 73f03c94432f0e8a8ed1298e837d78470589d41d Mon Sep 17 00:00:00 2001 From: Gabe Cook Date: Mon, 23 Sep 2024 16:04:02 -0500 Subject: [PATCH] chore: Migrate logger from zerolog to slog --- cmd/cmd.go | 14 ++- go.mod | 2 +- go.sum | 10 +-- internal/config/completions.go | 18 +--- internal/config/config.go | 8 +- internal/config/flags.go | 6 +- internal/config/load.go | 27 +++--- internal/config/log.go | 109 ++++++++++++----------- internal/config/log_test.go | 67 -------------- internal/config/logformat_enumer.go | 98 ++++++++++++++++++++ internal/visitor/find_args_completion.go | 41 ++++----- internal/visitor/template_comments.go | 36 ++++---- main.go | 3 + 13 files changed, 232 insertions(+), 207 deletions(-) delete mode 100644 internal/config/log_test.go create mode 100644 internal/config/logformat_enumer.go diff --git a/cmd/cmd.go b/cmd/cmd.go index 782bdee..48a226d 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -5,6 +5,7 @@ import ( "errors" "io" "io/fs" + "log/slog" "os" "path/filepath" "strings" @@ -15,7 +16,6 @@ import ( "github.com/clevyr/yampl/internal/visitor" "github.com/mattn/go-isatty" "github.com/muesli/termenv" - "github.com/rs/zerolog/log" "github.com/spf13/cobra" "gopkg.in/yaml.v3" ) @@ -38,7 +38,7 @@ func New(opts ...Option) *cobra.Command { conf := config.New() conf.RegisterFlags(cmd) conf.RegisterCompletions(cmd) - visitor.RegisterCompletion(cmd, conf) + visitor.RegisterCompletion(cmd) cmd.SetContext(config.WithContext(context.Background(), conf)) for _, opt := range opts { @@ -55,12 +55,8 @@ func validArgs(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCom var ErrStdinInplace = errors.New("-i or --inplace may not be used with stdin") func run(cmd *cobra.Command, args []string) error { - conf, ok := config.FromContext(cmd.Context()) - if !ok { - panic("config missing from command context") - } - - if err := conf.Load(cmd); err != nil { + conf, err := config.Load(cmd) + if err != nil { return err } @@ -173,7 +169,7 @@ func openAndTemplateFile(conf *config.Config, w io.Writer, dir, path string, wit } if err := os.Rename(temp.Name(), path); err != nil { - log.Trace().Msg("failed to rename file, attempting to copy contents") + slog.Debug("Failed to rename file. Attempting to copy contents.") in, err := os.Open(temp.Name()) if err != nil { diff --git a/go.mod b/go.mod index f2bb501..deaf216 100644 --- a/go.mod +++ b/go.mod @@ -6,9 +6,9 @@ require ( github.com/Masterminds/sprig/v3 v3.3.0 github.com/fatih/color v1.17.0 github.com/goccy/go-yaml v1.12.0 + github.com/lmittmann/tint v1.0.5 github.com/mattn/go-isatty v0.0.20 github.com/muesli/termenv v0.15.2 - github.com/rs/zerolog v1.33.0 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.9.0 diff --git a/go.sum b/go.sum index 233c3e7..8bd54d2 100644 --- a/go.sum +++ b/go.sum @@ -8,7 +8,6 @@ github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -19,7 +18,6 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/goccy/go-yaml v1.12.0 h1:/1WHjnMsI1dlIBQutrvSMGZRQufVO3asrHfTwfACoPM= github.com/goccy/go-yaml v1.12.0/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -32,12 +30,13 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lmittmann/tint v1.0.5 h1:NQclAutOfYsqs2F1Lenue6OoWCajs5wJcP3DfWVpePw= +github.com/lmittmann/tint v1.0.5/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 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/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= @@ -48,16 +47,12 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= -github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= @@ -74,7 +69,6 @@ golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= diff --git a/internal/config/completions.go b/internal/config/completions.go index cc81c6d..0051cfb 100644 --- a/internal/config/completions.go +++ b/internal/config/completions.go @@ -3,7 +3,6 @@ package config import ( "errors" - "github.com/rs/zerolog" "github.com/spf13/cobra" ) @@ -12,11 +11,6 @@ const ( Zsh = "zsh" Fish = "fish" Powershell = "powershell" - - Auto = "auto" - Color = "color" - Plain = "plain" - JSON = "json" ) func (c *Config) RegisterCompletions(cmd *cobra.Command) { @@ -31,20 +25,12 @@ func (c *Config) RegisterCompletions(cmd *cobra.Command) { cmd.RegisterFlagCompletionFunc(StripFlag, BoolCompletion), cmd.RegisterFlagCompletionFunc(LogLevelFlag, func(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) { - return []string{ - zerolog.TraceLevel.String(), - zerolog.DebugLevel.String(), - zerolog.InfoLevel.String(), - zerolog.WarnLevel.String(), - zerolog.ErrorLevel.String(), - zerolog.FatalLevel.String(), - zerolog.PanicLevel.String(), - }, cobra.ShellCompDirectiveNoFileComp + return LogLevelStrings(), cobra.ShellCompDirectiveNoFileComp }, ), cmd.RegisterFlagCompletionFunc(LogFormatFlag, func(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) { - return []string{Auto, Color, Plain, JSON}, cobra.ShellCompDirectiveNoFileComp + return LogFormatStrings(), cobra.ShellCompDirectiveNoFileComp }, ), cmd.RegisterFlagCompletionFunc(CompletionFlag, diff --git a/internal/config/config.go b/internal/config/config.go index 381b513..549750b 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -1,8 +1,10 @@ package config import ( + "log/slog" + "strings" + "github.com/clevyr/yampl/internal/config/flag" - "github.com/rs/zerolog" ) type Config struct { @@ -38,7 +40,7 @@ func New() *Config { IgnoreUnsetErrors: true, - LogLevel: zerolog.InfoLevel.String(), - LogFormat: Auto, + LogLevel: strings.ToLower(slog.LevelInfo.String()), + LogFormat: FormatAuto.String(), } } diff --git a/internal/config/flags.go b/internal/config/flags.go index cb27851..41614b1 100644 --- a/internal/config/flags.go +++ b/internal/config/flags.go @@ -3,8 +3,8 @@ package config import ( "bytes" "errors" + "log/slog" - "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) @@ -66,13 +66,13 @@ func (c *Config) RegisterFlags(cmd *cobra.Command) { panic(err) } - initLog(cmd) + c.InitLog(cmd.ErrOrStderr()) cmd.Flags().SetOutput(DeprecatedWriter{}) } type DeprecatedWriter struct{} func (d DeprecatedWriter) Write(b []byte) (int, error) { - log.Warn().Msg(string(bytes.TrimSpace(b))) + slog.Warn(string(bytes.TrimSpace(b))) return len(b), nil } diff --git a/internal/config/load.go b/internal/config/load.go index ecf2155..30cd9aa 100644 --- a/internal/config/load.go +++ b/internal/config/load.go @@ -12,7 +12,14 @@ import ( const EnvPrefix = "YAMPL_" -func (c *Config) Load(cmd *cobra.Command) error { +var ErrCmdMissingConfig = errors.New("config missing from command context") + +func Load(cmd *cobra.Command) (*Config, error) { + conf, ok := FromContext(cmd.Context()) + if !ok { + return nil, ErrCmdMissingConfig + } + IgnoredEnvs := []string{ CompletionFlag, } @@ -30,27 +37,27 @@ func (c *Config) Load(cmd *cobra.Command) error { } }) if len(errs) != 0 { - return errors.Join(errs...) + return nil, errors.Join(errs...) } - initLog(cmd) + conf.InitLog(cmd.ErrOrStderr()) - if !strings.HasPrefix(c.Prefix, "#") { - c.Prefix = "#" + c.Prefix + if !strings.HasPrefix(conf.Prefix, "#") { + conf.Prefix = "#" + conf.Prefix } - c.Vars.Fill(c.valuesStringToString.Value()) + conf.Vars.Fill(conf.valuesStringToString.Value()) if f := cmd.Flags().Lookup(FailFlag); f.Changed { val, err := cmd.Flags().GetBool(FailFlag) if err != nil { - return err + return nil, err } - c.IgnoreUnsetErrors = !val - c.IgnoreTemplateErrors = !val + conf.IgnoreUnsetErrors = !val + conf.IgnoreTemplateErrors = !val } - return nil + return conf, nil } func EnvName(name string) string { diff --git a/internal/config/log.go b/internal/config/log.go index ef57463..bb34bb2 100644 --- a/internal/config/log.go +++ b/internal/config/log.go @@ -1,72 +1,79 @@ package config import ( - "fmt" "io" + "log/slog" + "os" + "strings" + "time" - "github.com/clevyr/yampl/internal/colorize" - "github.com/fatih/color" - "github.com/rs/zerolog" - "github.com/rs/zerolog/log" - "github.com/spf13/cobra" + "github.com/lmittmann/tint" + "github.com/mattn/go-isatty" ) -func logLevel(level string) zerolog.Level { - parsedLevel, err := zerolog.ParseLevel(level) - if err != nil || parsedLevel == zerolog.NoLevel { - if level == "warning" { - parsedLevel = zerolog.WarnLevel - } else { - log.Warn().Str("value", level).Msg("invalid log level. defaulting to info.") - parsedLevel = zerolog.InfoLevel - } +//go:generate enumer -type LogFormat -trimprefix Format -transform lower -text + +type LogFormat uint8 + +const ( + FormatAuto LogFormat = iota + FormatColor + FormatPlain + FormatJSON +) + +func (c *Config) InitLog(w io.Writer) { + var level slog.Level + if err := level.UnmarshalText([]byte(c.LogLevel)); err != nil { + slog.Warn("Invalid log level. Defaulting to info.", "value", c.LogLevel) + level = slog.LevelInfo + c.LogLevel = strings.ToLower(level.String()) } - return parsedLevel + + var format LogFormat + if err := format.UnmarshalText([]byte(c.LogFormat)); err != nil { + slog.Warn("Invalid log format. Defaulting to auto.", "value", c.LogFormat) + format = FormatAuto + c.LogFormat = format.String() + } + + InitLog(w, level, format) } -func logFormat(out io.Writer, format string) io.Writer { +func InitLog(w io.Writer, level slog.Level, format LogFormat) { switch format { - case JSON: - return out + case FormatJSON: + slog.SetDefault(slog.New( + slog.NewJSONHandler(w, &slog.HandlerOptions{ + Level: level, + }), + )) default: - sprintf := fmt.Sprintf - var useColor bool + var color bool switch format { - case Auto: - if useColor = colorize.ShouldColor(out); !useColor { - break + case FormatAuto: + if f, ok := w.(*os.File); ok { + color = isatty.IsTerminal(f.Fd()) || isatty.IsCygwinTerminal(f.Fd()) } - fallthrough - case Color: - useColor = true - color.NoColor = false - sprintf = color.New(color.Bold).Sprintf - case Plain: - default: - log.Warn().Str("value", format).Msg("invalid log formatter. defaulting to auto.") - return logFormat(out, Auto) + case FormatColor: + color = true } - return zerolog.ConsoleWriter{ - Out: out, - NoColor: !useColor, - FormatMessage: func(i any) string { - return sprintf("%-45s", i) - }, - } + slog.SetDefault(slog.New( + tint.NewHandler(w, &tint.Options{ + Level: level, + TimeFormat: time.DateTime, + NoColor: !color, + }), + )) } } -func initLog(cmd *cobra.Command) { - level, err := cmd.Flags().GetString("log-level") - if err != nil { - panic(err) - } - zerolog.SetGlobalLevel(logLevel(level)) - - format, err := cmd.Flags().GetString("log-format") - if err != nil { - panic(err) +func LogLevelStrings() []string { + return []string{ + strings.ToLower(slog.LevelDebug.String()), + strings.ToLower(slog.LevelInfo.String()), + strings.ToLower(slog.LevelWarn.String()), + strings.ToLower(slog.LevelError.String()), } - log.Logger = log.Output(logFormat(cmd.ErrOrStderr(), format)) } diff --git a/internal/config/log_test.go b/internal/config/log_test.go deleted file mode 100644 index 98e5d94..0000000 --- a/internal/config/log_test.go +++ /dev/null @@ -1,67 +0,0 @@ -package config - -import ( - "io" - "os" - "testing" - - "github.com/rs/zerolog" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func Test_logFormat(t *testing.T) { - type args struct { - format string - } - tests := []struct { - name string - args args - want io.Writer - }{ - {"default", args{"auto"}, zerolog.ConsoleWriter{Out: os.Stderr, NoColor: true}}, - {"color", args{"color"}, zerolog.ConsoleWriter{Out: os.Stderr}}, - {"plain", args{"plain"}, zerolog.ConsoleWriter{Out: os.Stderr, NoColor: true}}, - {"json", args{"json"}, os.Stderr}, - {"unknown", args{""}, zerolog.ConsoleWriter{Out: os.Stderr, NoColor: true}}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := logFormat(os.Stderr, tt.args.format) - require.IsType(t, tt.want, got) - if want, ok := tt.want.(zerolog.ConsoleWriter); ok { - got := got.(zerolog.ConsoleWriter) - assert.NotNil(t, got.FormatMessage) - want.FormatMessage = got.FormatMessage - assert.Equal(t, want.Out, got.Out) - assert.Equal(t, want.NoColor, got.NoColor) - } - }) - } -} - -func Test_logLevel(t *testing.T) { - type args struct { - level string - } - tests := []struct { - name string - args args - want zerolog.Level - }{ - {"trace", args{"trace"}, zerolog.TraceLevel}, - {"debug", args{"debug"}, zerolog.DebugLevel}, - {"info", args{"info"}, zerolog.InfoLevel}, - {"warning", args{"warning"}, zerolog.WarnLevel}, - {"error", args{"error"}, zerolog.ErrorLevel}, - {"fatal", args{"fatal"}, zerolog.FatalLevel}, - {"panic", args{"panic"}, zerolog.PanicLevel}, - {"unknown", args{""}, zerolog.InfoLevel}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := logLevel(tt.args.level) - assert.Equal(t, tt.want, got) - }) - } -} diff --git a/internal/config/logformat_enumer.go b/internal/config/logformat_enumer.go new file mode 100644 index 0000000..bba2723 --- /dev/null +++ b/internal/config/logformat_enumer.go @@ -0,0 +1,98 @@ +// Code generated by "enumer -type LogFormat -trimprefix Format -transform lower -text"; DO NOT EDIT. + +package config + +import ( + "fmt" + "strings" +) + +const _LogFormatName = "autocolorplainjson" + +var _LogFormatIndex = [...]uint8{0, 4, 9, 14, 18} + +const _LogFormatLowerName = "autocolorplainjson" + +func (i LogFormat) String() string { + if i >= LogFormat(len(_LogFormatIndex)-1) { + return fmt.Sprintf("LogFormat(%d)", i) + } + return _LogFormatName[_LogFormatIndex[i]:_LogFormatIndex[i+1]] +} + +// An "invalid array index" compiler error signifies that the constant values have changed. +// Re-run the stringer command to generate them again. +func _LogFormatNoOp() { + var x [1]struct{} + _ = x[FormatAuto-(0)] + _ = x[FormatColor-(1)] + _ = x[FormatPlain-(2)] + _ = x[FormatJSON-(3)] +} + +var _LogFormatValues = []LogFormat{FormatAuto, FormatColor, FormatPlain, FormatJSON} + +var _LogFormatNameToValueMap = map[string]LogFormat{ + _LogFormatName[0:4]: FormatAuto, + _LogFormatLowerName[0:4]: FormatAuto, + _LogFormatName[4:9]: FormatColor, + _LogFormatLowerName[4:9]: FormatColor, + _LogFormatName[9:14]: FormatPlain, + _LogFormatLowerName[9:14]: FormatPlain, + _LogFormatName[14:18]: FormatJSON, + _LogFormatLowerName[14:18]: FormatJSON, +} + +var _LogFormatNames = []string{ + _LogFormatName[0:4], + _LogFormatName[4:9], + _LogFormatName[9:14], + _LogFormatName[14:18], +} + +// LogFormatString retrieves an enum value from the enum constants string name. +// Throws an error if the param is not part of the enum. +func LogFormatString(s string) (LogFormat, error) { + if val, ok := _LogFormatNameToValueMap[s]; ok { + return val, nil + } + + if val, ok := _LogFormatNameToValueMap[strings.ToLower(s)]; ok { + return val, nil + } + return 0, fmt.Errorf("%s does not belong to LogFormat values", s) +} + +// LogFormatValues returns all values of the enum +func LogFormatValues() []LogFormat { + return _LogFormatValues +} + +// LogFormatStrings returns a slice of all String values of the enum +func LogFormatStrings() []string { + strs := make([]string, len(_LogFormatNames)) + copy(strs, _LogFormatNames) + return strs +} + +// IsALogFormat returns "true" if the value is listed in the enum definition. "false" otherwise +func (i LogFormat) IsALogFormat() bool { + for _, v := range _LogFormatValues { + if i == v { + return true + } + } + return false +} + +// MarshalText implements the encoding.TextMarshaler interface for LogFormat +func (i LogFormat) MarshalText() ([]byte, error) { + return []byte(i.String()), nil +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface for LogFormat +func (i *LogFormat) UnmarshalText(text []byte) error { + var err error + *i, err = LogFormatString(string(text)) + return err +} diff --git a/internal/visitor/find_args_completion.go b/internal/visitor/find_args_completion.go index 820b71a..4b4bfdb 100644 --- a/internal/visitor/find_args_completion.go +++ b/internal/visitor/find_args_completion.go @@ -14,35 +14,36 @@ import ( "gopkg.in/yaml.v3" ) -func RegisterCompletion(cmd *cobra.Command, conf *config.Config) { - if err := cmd.RegisterFlagCompletionFunc(config.VarFlag, valueCompletion(conf)); err != nil { +func RegisterCompletion(cmd *cobra.Command) { + if err := cmd.RegisterFlagCompletionFunc(config.VarFlag, valueCompletion); err != nil { panic(err) } } -func valueCompletion(conf *config.Config) func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return func(cmd *cobra.Command, args []string, _ string) ([]string, cobra.ShellCompDirective) { - _ = conf.Load(cmd) - - if !strings.HasPrefix(conf.Prefix, "#") { - conf.Prefix = "#" + conf.Prefix - } +func valueCompletion(cmd *cobra.Command, args []string, _ string) ([]string, cobra.ShellCompDirective) { + conf, err := config.Load(cmd) + if err != nil { + return nil, cobra.ShellCompDirectiveError + } - v := NewFindArgs(conf) - for _, path := range args { - if err := filepath.WalkDir(path, func(path string, d fs.DirEntry, err error) error { - if err != nil || d.IsDir() || !util.IsYaml(path) { - return err - } + if !strings.HasPrefix(conf.Prefix, "#") { + conf.Prefix = "#" + conf.Prefix + } - return valueCompletionFile(path, v) - }); err != nil { - continue + v := NewFindArgs(conf) + for _, path := range args { + if err := filepath.WalkDir(path, func(path string, d fs.DirEntry, err error) error { + if err != nil || d.IsDir() || !util.IsYaml(path) { + return err } - } - return v.Values(), cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveNoFileComp + return valueCompletionFile(path, v) + }); err != nil { + continue + } } + + return v.Values(), cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveNoFileComp } func valueCompletionFile(path string, v *FindArgs) error { diff --git a/internal/visitor/template_comments.go b/internal/visitor/template_comments.go index 7ef09b4..9caf984 100644 --- a/internal/visitor/template_comments.go +++ b/internal/visitor/template_comments.go @@ -2,7 +2,9 @@ package visitor import ( "bytes" + "context" "fmt" + "log/slog" "maps" "regexp" "strings" @@ -12,29 +14,25 @@ import ( "github.com/clevyr/yampl/internal/comment" "github.com/clevyr/yampl/internal/config" yamplTemplate "github.com/clevyr/yampl/internal/template" - "github.com/rs/zerolog" - "github.com/rs/zerolog/log" "gopkg.in/yaml.v3" ) func NewTemplateComments(conf *config.Config, path string) TemplateComments { - var l zerolog.Logger - if path == "" { - l = log.Logger - } else { - l = log.With().Str("file", path).Logger() + logger := slog.Default() + if path != "" { + logger = logger.With("file", path) } return TemplateComments{ conf: conf, - log: l, + log: logger, path: path, } } type TemplateComments struct { conf *config.Config - log zerolog.Logger + log *slog.Logger path string } @@ -93,11 +91,11 @@ func (t TemplateComments) Run(n *yaml.Node) error { } func (t TemplateComments) Template(name string, n *yaml.Node, tmplSrc string, tmplTag comment.Tag) error { - log := t.log.With(). - Str("tmpl", tmplSrc). - Str("filePos", fmt.Sprintf("%d:%d", n.Line, n.Column)). - Str("from", n.Value). - Logger() + log := t.log.With( + "tmpl", tmplSrc, + "filePos", fmt.Sprintf("%d:%d", n.Line, n.Column), + "from", n.Value, + ) tmpl, err := template.New("`"+tmplSrc+"`"). Funcs(yamplTemplate.FuncMap( @@ -125,7 +123,7 @@ func (t TemplateComments) Template(name string, n *yaml.Node, tmplSrc string, tm str := buf.String() if str != n.Value { - log.Debug().Str("to", str).Msg("updating value") + log.Debug("Updating value", "to", str) n.Style = 0 switch tmplTag { @@ -160,18 +158,18 @@ func (t TemplateComments) checkDeprecated(tmplSrc string) { for _, match := range re.FindAllStringSubmatch(tmplSrc, -1) { key := match[1] if _, ok := t.conf.Vars[key[1:]]; !ok { - log.Warn().Msg(key + " is deprecated, use `current` instead") + slog.Warn(key + " is deprecated, use `current` instead") } } } } func (t TemplateComments) handleTemplateError(err error) error { - level := zerolog.WarnLevel + level := slog.LevelWarn switch { case err != nil && strings.Contains(err.Error(), "map has no entry for key"): if t.conf.IgnoreUnsetErrors { - level = zerolog.DebugLevel + level = slog.LevelDebug } else { return err } @@ -179,6 +177,6 @@ func (t TemplateComments) handleTemplateError(err error) error { default: return err } - t.log.WithLevel(level).Err(err).Msg("skipping value due to template error") + t.log.Log(context.Background(), level, "Skipping value due to template error", "error", err) return nil } diff --git a/main.go b/main.go index 5ccb4fa..0420f32 100644 --- a/main.go +++ b/main.go @@ -1,14 +1,17 @@ package main import ( + "log/slog" "os" "github.com/clevyr/yampl/cmd" + "github.com/clevyr/yampl/internal/config" ) var version = "beta" func main() { + config.InitLog(os.Stderr, slog.LevelInfo, config.FormatAuto) root := cmd.New(cmd.WithVersion(version)) if err := root.Execute(); err != nil { os.Exit(1)