diff --git a/native/color/mode.go b/native/color/mode.go index 6a1bdda..dd1315d 100644 --- a/native/color/mode.go +++ b/native/color/mode.go @@ -106,3 +106,19 @@ func (instance Modes) Strings() []string { func (instance Modes) String() string { return strings.Join(instance.Strings(), ",") } + +// ModeAware describes an object that is aware of a Mode and exports its current +// state. +type ModeAware interface { + // GetColorMode returns the current Mode. + GetColorMode() Mode +} + +// ModeMutableAware is similar to ModeAware but additionally is able to modify the +// Mode by calling SetColorMode(Mode). +type ModeMutableAware interface { + ModeAware + + // SetColorMode modifies the current Mode to the given one. + SetColorMode(Mode) +} diff --git a/native/facade/value/consumer.go b/native/facade/value/consumer.go index 0721873..29a1a88 100644 --- a/native/facade/value/consumer.go +++ b/native/facade/value/consumer.go @@ -24,7 +24,7 @@ type Consumer struct { Formatter Formatter } -// NewProvider create a new instance of Provider with the given target ProviderTarget instance. +// NewConsumer create a new instance of Provider with the given target ProviderTarget instance. func NewConsumer(target ConsumerTarget, customizer ...func(*Consumer)) Consumer { if c := target.GetConsumer(); c == nil { if d := consumer.Default; d != nil { diff --git a/native/facade/value/formatter.go b/native/facade/value/formatter.go index 85af2aa..d0c465e 100644 --- a/native/facade/value/formatter.go +++ b/native/facade/value/formatter.go @@ -2,6 +2,7 @@ package value import ( "fmt" + "github.com/echocat/slf4g/native/color" "github.com/echocat/slf4g/native/formatter" ) @@ -24,6 +25,12 @@ type Formatter struct { // Codec is used to transform provided plain data. If this is not defined // DefaultFormatterCodec is used. Codec FormatterCodec + + // ColorMode enables in cases where the Target is color.ModeMutableAware + // to modify the value of it. + // This will not always work. Not all targets supports it. In this case + // the value will be swallowed. + ColorMode *FormatterColorMode } // NewFormatter creates a new instance of Formatter with the given target. @@ -32,6 +39,12 @@ func NewFormatter(target FormatterTarget, customizer ...func(*Formatter)) Format Target: target, } + result.ColorMode = &FormatterColorMode{ + result.getColorMode, + result.setColorMode, + nil, + } + for _, c := range customizer { c(&result) } @@ -47,7 +60,8 @@ func (instance Formatter) Set(plain string) error { } instance.Target.SetFormatter(v) - return nil + + return instance.setColorMode(instance.ColorMode.get()) } // Get implements flag.Getter. @@ -64,6 +78,25 @@ func (instance Formatter) String() string { return string(b) } +func (instance Formatter) getColorMode() (color.Mode, bool) { + if t, ok := instance.Get().(color.ModeAware); ok { + return t.GetColorMode(), true + } + return 0, false +} + +func (instance Formatter) setColorMode(v color.Mode) error { + if t, ok := instance.Get().(color.ModeMutableAware); ok { + t.SetColorMode(v) + } + return nil +} + +// Type returns the type as a string. +func (instance Formatter) Type() string { + return "logFormatter" +} + // MarshalText implements encoding.TextMarshaler func (instance Formatter) MarshalText() (text []byte, err error) { if instance.Target == nil { diff --git a/native/facade/value/formatter_color_mode.go b/native/facade/value/formatter_color_mode.go new file mode 100644 index 0000000..215cee9 --- /dev/null +++ b/native/facade/value/formatter_color_mode.go @@ -0,0 +1,52 @@ +package value + +import ( + "github.com/echocat/slf4g/native/color" +) + +// FormatterColorMode enables the access the color.Mode of a FormatterTarget. +type FormatterColorMode struct { + provider func() (color.Mode, bool) + sink func(color.Mode) error + value *color.Mode +} + +// Set implements flag.Value. +func (instance *FormatterColorMode) Set(plain string) error { + var buf color.Mode + if err := buf.Set(plain); err != nil { + return err + } + + if err := instance.sink(buf); err != nil { + return err + } + + instance.value = &buf + return nil +} + +func (instance FormatterColorMode) get() color.Mode { + if v, ok := instance.provider(); ok { + return v + } + if v := instance.value; v != nil { + return *v + } + return color.ModeAuto +} + +// Get implements flag.Getter. +func (instance FormatterColorMode) Get() interface{} { + return instance.get() +} + +// String implements flag.Value. +func (instance FormatterColorMode) String() string { + return instance.get().String() +} + +// Type returns the type as a string. +func (instance FormatterColorMode) Type() string { + return "logColorMode" +} diff --git a/native/facade/value/level.go b/native/facade/value/level.go index 996030a..83cffcd 100644 --- a/native/facade/value/level.go +++ b/native/facade/value/level.go @@ -26,7 +26,7 @@ type Level struct { // Names is used to transform provided plain data. If this is not defined // the Target is assumed as nlevel.NamesAware or if this even does not work // nlevel.DefaultNames is used. - Names nlevel.Names + Names level.Names } // NewLevel creates a new instance of Level with the given target. @@ -72,6 +72,11 @@ func (instance Level) String() string { return string(b) } +// Type returns the type as a string. +func (instance Level) Type() string { + return "logLevel" +} + // MarshalText implements encoding.TextMarshaler func (instance Level) MarshalText() (text []byte, err error) { if instance.Target == nil { diff --git a/native/facade/value/level_test.go b/native/facade/value/level_test.go index 9e32a45..b503247 100644 --- a/native/facade/value/level_test.go +++ b/native/facade/value/level_test.go @@ -157,12 +157,12 @@ func (instance *mockLevelTarget) SetLevel(v level.Level) { instance.level = v } -func (instance *mockLevelTarget) GetLevelNames() nlevel.Names { +func (instance *mockLevelTarget) GetLevelNames() level.Names { return mockLevelNames } type failingLevelNames struct { - nlevel.Names + level.Names } func (instance failingLevelNames) ToName(level.Level) (string, error) { diff --git a/native/facade/value/provider_example_test.go b/native/facade/value/provider_example_test.go index 5f8f882..5bca151 100644 --- a/native/facade/value/provider_example_test.go +++ b/native/facade/value/provider_example_test.go @@ -11,6 +11,7 @@ func ExampleNewProvider() { pv := value.NewProvider(native.DefaultProvider) flag.Var(pv.Consumer.Formatter, "log.format", "Configures the log format.") + flag.Var(pv.Consumer.Formatter.ColorMode, "log.color", "Configures the log color mode.") flag.Var(pv.Level, "log.level", "Configures the log level.") flag.Parse() diff --git a/native/formatter/level.go b/native/formatter/level.go index 37fa135..004b053 100644 --- a/native/formatter/level.go +++ b/native/formatter/level.go @@ -20,7 +20,7 @@ type Level interface { // NewNamesBasedLevel creates a new instance of Level which uses given nlevel.Names to // resolve the name of a given log.Level and format it with it. -func NewNamesBasedLevel(names nlevel.Names) Level { +func NewNamesBasedLevel(names level.Names) Level { return LevelFunc(func(in level.Level, using log.Provider) (interface{}, error) { result, err := names.ToName(in) return result, err diff --git a/native/formatter/template.go b/native/formatter/template.go index afb9bdf..be5dd31 100644 --- a/native/formatter/template.go +++ b/native/formatter/template.go @@ -158,7 +158,7 @@ func (instance TemplateRenderingContext) Hints() hints.Hints { // LevelNames is a convenience method to easy return the current nlevel.Names // of the corresponding log.Provider. -func (instance TemplateRenderingContext) LevelNames() nlevel.Names { +func (instance TemplateRenderingContext) LevelNames() level.Names { if v, ok := instance.Provider.(level.NamesAware); ok { if names := v.GetLevelNames(); names != nil { return names diff --git a/native/formatter/text.go b/native/formatter/text.go index b5f1c6c..725ebdd 100644 --- a/native/formatter/text.go +++ b/native/formatter/text.go @@ -282,6 +282,14 @@ func (instance *Text) colorizeChecked(l level.Level, message *string, h hints.Hi } } +func (instance *Text) GetColorMode() color.Mode { + return instance.ColorMode +} + +func (instance *Text) SetColorMode(v color.Mode) { + instance.ColorMode = v +} + func (instance *Text) wrapHints(h hints.Hints) hints.Hints { return textHintsCombined{h, instance.textAsHints} } @@ -305,7 +313,7 @@ func (instance *Text) formatLevelChecked(l level.Level, using log.Provider, to * } } -func (instance *Text) getLevelNames(using log.Provider) nlevel.Names { +func (instance *Text) getLevelNames(using log.Provider) level.Names { if v, ok := using.(level.NamesAware); ok { return v.GetLevelNames() } diff --git a/native/formatter/utils_test.go b/native/formatter/utils_test.go index 9fdb145..93a7371 100644 --- a/native/formatter/utils_test.go +++ b/native/formatter/utils_test.go @@ -45,9 +45,9 @@ func mustParseTime(in string) time.Time { type mockProviderWithLevelNames struct { *recording.Provider - Names nlevel.Names + Names level.Names } -func (instance mockProviderWithLevelNames) GetLevelNames() nlevel.Names { +func (instance mockProviderWithLevelNames) GetLevelNames() level.Names { return instance.Names } diff --git a/native/internal/demo_flags/main.go b/native/internal/demo_flags/main.go index 5d30336..f11d50f 100644 --- a/native/internal/demo_flags/main.go +++ b/native/internal/demo_flags/main.go @@ -13,6 +13,7 @@ import ( func main() { pv := value.NewProvider(native.DefaultProvider) flag.Var(pv.Consumer.Formatter, "log.format", "configures the log format.") + flag.Var(pv.Consumer.Formatter.ColorMode, "log.color", "configures the log color mode.") flag.Var(pv.Level, "log.level", "configures the log level.") flag.Parse() diff --git a/native/level/named.go b/native/level/named.go index 99d08d3..5ab9a63 100644 --- a/native/level/named.go +++ b/native/level/named.go @@ -8,14 +8,14 @@ import ( "github.com/echocat/slf4g/level" ) -// AsNamed wraps the given level.Level into Named to it in a human readable +// AsNamed wraps the given level.Level into Named to it in a human-readable // format and provides the possibility to marshal and get used with // flag (or compatible) packages. -func AsNamed(in *level.Level, names Names) Named { +func AsNamed(in *level.Level, names level.Names) Named { return &namedImpl{in, names} } -// Named represents a level.Level in a human readable format and provides the +// Named represents a level.Level in a human-readable format and provides the // possibility to marshal and get used with flag (or compatible) packages. type Named interface { Unwrap() *level.Level @@ -27,7 +27,7 @@ type Named interface { type namedImpl struct { level *level.Level - names Names + names level.Names } func (instance *namedImpl) Get() interface{} { @@ -55,7 +55,7 @@ func (instance *namedImpl) UnmarshalText(text []byte) error { return nil } -func (instance *namedImpl) getNames() Names { +func (instance *namedImpl) getNames() level.Names { if v := instance.names; v != nil { return v } diff --git a/native/level/names.go b/native/level/names.go index b11ebc2..6b644d2 100644 --- a/native/level/names.go +++ b/native/level/names.go @@ -60,29 +60,3 @@ func (instance *defaultNames) ToLevel(name string) (level.Level, error) { } } } - -// ErrIllegalLevel represents that an illegal level.Level value/name was -// provided. -// -// Deprecated: use level.ErrIllegalLevel instead. -var ErrIllegalLevel = level.ErrIllegalLevel - -// Names is used to make readable names out of level.Level or the other way -// around. -// -// Deprecated: use level.Names instead. -type Names level.Names - -// NamesAware represents an object that is aware of Names. -// -// Deprecated: use level.NamesAware instead. -type NamesAware level.NamesAware - -// NewNamesFacade creates a facade of Names using the given provider. -// -// Deprecated: use level.NewNamesFacade instead. -func NewNamesFacade(provider func() Names) Names { - return level.NewNamesFacade(func() level.Names { - return provider() - }) -} diff --git a/native/provider.go b/native/provider.go index acf376c..36a0ccd 100644 --- a/native/provider.go +++ b/native/provider.go @@ -33,10 +33,10 @@ type Provider struct { // not set it will be log.Info by default. Level level.Level - // LevelNames is used to format the levels as human readable + // LevelNames is used to format the levels as human-readable // representations. If this is not set it will be level.DefaultNames by // default. - LevelNames nlevel.Names + LevelNames level.Names // LevelProvider is used to determine the log.Levels support by this // Provider and all of its managed loggers. If this is not set it will be @@ -120,7 +120,7 @@ func (instance *Provider) GetFieldKeysSpec() fields.KeysSpec { // GetLevelNames returns an instance of level.Names that support by formatting // level.Level managed by this Provider. -func (instance *Provider) GetLevelNames() nlevel.Names { +func (instance *Provider) GetLevelNames() level.Names { if v := instance.LevelNames; v != nil { return v }