diff --git a/formatter/formatter.go b/formatter/formatter.go index 73ae476..db27913 100644 --- a/formatter/formatter.go +++ b/formatter/formatter.go @@ -24,8 +24,24 @@ type Formatter struct { DoFmt } -// Decamel is preimplemented and default formatter to produce human -// readable error strings from function names. +// DecamelAndRmTryPrefix is pre-implemented formatter to produce human readable +// error strings from function names. It's similar to [Decamel] but also removes +// try-prefixes from function names: +// +// func TryCopyFile(..) -> "copy file: file not exists" +// ^-------^ -> generated from 'func TryCopyFile' +// +// It's convenient helper for those who wants to write compact functions by +// following convention to always add 'Try' prefix to those functions that can +// throw errors thru panics. Fox example, if you're using helpers like +// [github.com/lainio/err2/assert.That] and [github.com/lainio/err2/try.To] but +// you don't want to handle errors in your current function, it's still good +// practice to use convention to mark that function to throw errors. However, we +// suggest that you don't do that in your packages public API functions. +var DecamelAndRmTryPrefix = &Formatter{DoFmt: str.DecamelRmTryPrefix} + +// Decamel is pre-implemented and default formatter to produce human readable +// error strings from function names. // // func CopyFile(..) -> "copy file: file not exists" // ^-------^ -> generated from 'func CopyFile' diff --git a/internal/str/str.go b/internal/str/str.go index c9d9d13..5259c81 100644 --- a/internal/str/str.go +++ b/internal/str/str.go @@ -25,6 +25,10 @@ func DecamelRegexp(str string) string { return str } +func DecamelRmTryPrefix(s string) string { + return strings.ReplaceAll(Decamel(s), "try ", "") +} + // Decamel return the given string as space delimeted. It's optimized to split // and decamel function names returned from Go call stacks. For more information // see its test cases. diff --git a/internal/str/str_test.go b/internal/str/str_test.go index 9bf8160..56da177 100644 --- a/internal/str/str_test.go +++ b/internal/str/str_test.go @@ -23,6 +23,12 @@ func BenchmarkDecamel(b *testing.B) { } } +func BenchmarkDecamelRmTryPrefix(b *testing.B) { + for n := 0; n < b.N; n++ { + _ = str.DecamelRmTryPrefix(camelStr) + } +} + func TestCamel(t *testing.T) { t.Parallel() type args struct { @@ -104,3 +110,79 @@ func TestDecamel(t *testing.T) { }) } } + +func TestDecamelRmTryPrefix(t *testing.T) { + t.Parallel() + type args struct { + s string + } + tests := []struct { + name string + args args + want string + }{ + {"simple", args{"CamelString"}, "camel string"}, + {"simple try", args{"TryCamelString"}, "camel string"}, + {"underscore", args{"CamelString_error"}, "camel string error"}, + {"underscore and try", args{"TryCamelString_error"}, "camel string error"}, + { + "our contant", + args{camelStr}, + "benchmark recursion with old error if check and defer", + }, + {"number", args{"CamelString2Testing"}, "camel string2 testing"}, + {"acronym", args{"ARMCamelString"}, "armcamel string"}, + {"acronym and try at END so it left", args{"ARMCamelStringTry"}, "armcamel string try"}, + {"acronym and try", args{"TryARMCamelString"}, "armcamel string"}, + {"acronym at end", args{"archIsARM"}, "arch is arm"}, + { + "simple method", + args{"(*DIDAgent).AssertWallet"}, + "didagent assert wallet", + }, + { + "package name and simple method", + args{"ssi.(*DIDAgent).CreateWallet"}, + "ssi: didagent create wallet", + }, + { + "package name and simple method and Function start try", + args{"ssi.(*DIDAgent).TryCreateWallet"}, + "ssi: didagent create wallet", + }, + { + "simple method and anonym", + args{"(*DIDAgent).AssertWallet.Func1"}, + "didagent assert wallet: func1", + }, + { + "complex method and anonym", + args{"(**DIDAgent).AssertWallet.Func1"}, + "didagent assert wallet: func1", + }, + { + "complex method and anonym AND try", + args{"(**DIDAgent).TryAssertWallet.Func1"}, + "didagent assert wallet: func1", + }, + { + "unnatural method and anonym", + args{"(**DIDAgent)...AssertWallet...Func1"}, + "didagent assert wallet: func1", + }, + { + "unnatural method and anonym AND try", + args{"(**DIDAgent)...TryAssertWallet...TryFunc1"}, + "didagent assert wallet: func1", + }, + {"from spf13 cobra", args{"bot.glob..func5"}, "bot: glob: func5"}, + } + for _, ttv := range tests { + tt := ttv + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + got := str.DecamelRmTryPrefix(tt.args.s) + require.Equal(t, got, tt.want) + }) + } +} diff --git a/samples/main-play.go b/samples/main-play.go index f06dc81..79a8e21 100644 --- a/samples/main-play.go +++ b/samples/main-play.go @@ -190,8 +190,8 @@ func doMain() (err error) { } } else { // 2nd argument is empty to assert - //TryCopyFile("main.go", "") - try.To(CopyFile("main.go", "")) + TryCopyFile("main.go", "") + //try.To(CopyFile("main.go", "")) } fmt.Println("=== you cannot see this ===") diff --git a/samples/main.go b/samples/main.go index 0ff4380..db79f4b 100644 --- a/samples/main.go +++ b/samples/main.go @@ -7,6 +7,7 @@ import ( "github.com/lainio/err2" "github.com/lainio/err2/assert" + "github.com/lainio/err2/formatter" ) var ( @@ -24,6 +25,10 @@ func init() { // highlight that this is before flag.Parse to allow it to work properly. err2.SetLogTracer(os.Stderr) // for import err2.SetLogTracer(nil) + + // select which one you want to play with + err2.SetFormatter(formatter.DecamelAndRmTryPrefix) + // err2.SetFormatter(formatter.Decamel) } func main() {