parent
16088c88b5
commit
d96d15cb9b
@ -0,0 +1,88 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project active2
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name camel.go
|
||||
// Created by DEV
|
||||
// Modified 31/03/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
// https://github.com/iancoleman/strcase/blob/v0.3.0/camel.go
|
||||
|
||||
package astrings
|
||||
|
||||
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Converts a string to CamelCase
|
||||
func toCamelInitCase(s string, initCase bool) string {
|
||||
s = strings.TrimSpace(s)
|
||||
if s == "" {
|
||||
return s
|
||||
}
|
||||
a, hasAcronym := G.uppercaseAcronym.Load(s)
|
||||
if hasAcronym {
|
||||
s = a.(string)
|
||||
}
|
||||
|
||||
n := strings.Builder{}
|
||||
n.Grow(len(s))
|
||||
capNext := initCase
|
||||
prevIsCap := false
|
||||
for i, v := range []byte(s) {
|
||||
vIsCap := v >= 'A' && v <= 'Z'
|
||||
vIsLow := v >= 'a' && v <= 'z'
|
||||
if capNext {
|
||||
if vIsLow {
|
||||
v += 'A'
|
||||
v -= 'a'
|
||||
}
|
||||
} else if i == 0 {
|
||||
if vIsCap {
|
||||
v += 'a'
|
||||
v -= 'A'
|
||||
}
|
||||
} else if prevIsCap && vIsCap && !hasAcronym {
|
||||
v += 'a'
|
||||
v -= 'A'
|
||||
}
|
||||
prevIsCap = vIsCap
|
||||
|
||||
if vIsCap || vIsLow {
|
||||
n.WriteByte(v)
|
||||
capNext = false
|
||||
} else if vIsNum := v >= '0' && v <= '9'; vIsNum {
|
||||
n.WriteByte(v)
|
||||
capNext = true
|
||||
} else {
|
||||
capNext = v == '_' || v == ' ' || v == '-' || v == '.'
|
||||
}
|
||||
}
|
||||
return n.String()
|
||||
}
|
||||
|
||||
// ToCamel converts a string to CamelCase
|
||||
func ToCamel(s string) string {
|
||||
return toCamelInitCase(s, true)
|
||||
}
|
||||
|
||||
// ToLowerCamel converts a string to lowerCamelCase
|
||||
func ToLowerCamel(s string) string {
|
||||
return toCamelInitCase(s, false)
|
||||
}
|
||||
@ -0,0 +1,117 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project active2
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name snake.go
|
||||
// Created by DEV
|
||||
// Modified 31/03/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
// https://github.com/iancoleman/strcase/blob/v0.3.0/snake.go
|
||||
|
||||
package astrings
|
||||
|
||||
import "strings"
|
||||
|
||||
|
||||
|
||||
// ToSnake converts a string to snake_case
|
||||
func ToSnake(s string) string {
|
||||
return ToDelimited(s, '_')
|
||||
}
|
||||
|
||||
|
||||
func ToSnakeWithIgnore(s string, ignore string) string {
|
||||
return ToScreamingDelimited(s, '_', ignore, false)
|
||||
}
|
||||
|
||||
// ToScreamingSnake converts a string to SCREAMING_SNAKE_CASE
|
||||
func ToScreamingSnake(s string) string {
|
||||
return ToScreamingDelimited(s, '_', "", true)
|
||||
}
|
||||
|
||||
// ToKebab converts a string to kebab-case
|
||||
func ToKebab(s string) string {
|
||||
return ToDelimited(s, '-')
|
||||
}
|
||||
|
||||
// ToScreamingKebab converts a string to SCREAMING-KEBAB-CASE
|
||||
func ToScreamingKebab(s string) string {
|
||||
return ToScreamingDelimited(s, '-', "", true)
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ToDelimited converts a string to delimited.snake.case
|
||||
// (in this case `delimiter = '.'`)
|
||||
func ToDelimited(s string, delimiter uint8) string {
|
||||
return ToScreamingDelimited(s, delimiter, "", false)
|
||||
}
|
||||
|
||||
// ToScreamingDelimited converts a string to SCREAMING.DELIMITED.SNAKE.CASE
|
||||
// (in this case `delimiter = '.'; screaming = true`)
|
||||
// or delimited.snake.case
|
||||
// (in this case `delimiter = '.'; screaming = false`)
|
||||
func ToScreamingDelimited(s string, delimiter uint8, ignore string, screaming bool) string {
|
||||
s = strings.TrimSpace(s)
|
||||
n := strings.Builder{}
|
||||
n.Grow(len(s) + 2) // nominal 2 bytes of extra space for inserted delimiters
|
||||
for i, v := range []byte(s) {
|
||||
vIsCap := v >= 'A' && v <= 'Z'
|
||||
vIsLow := v >= 'a' && v <= 'z'
|
||||
if vIsLow && screaming {
|
||||
v += 'A'
|
||||
v -= 'a'
|
||||
} else if vIsCap && !screaming {
|
||||
v += 'a'
|
||||
v -= 'A'
|
||||
}
|
||||
|
||||
// treat acronyms as words, eg for JSONData -> JSON is a whole word
|
||||
if i+1 < len(s) {
|
||||
next := s[i+1]
|
||||
vIsNum := v >= '0' && v <= '9'
|
||||
nextIsCap := next >= 'A' && next <= 'Z'
|
||||
nextIsLow := next >= 'a' && next <= 'z'
|
||||
nextIsNum := next >= '0' && next <= '9'
|
||||
// add underscore if next letter case type is changed
|
||||
if (vIsCap && (nextIsLow || nextIsNum)) || (vIsLow && (nextIsCap || nextIsNum)) || (vIsNum && (nextIsCap || nextIsLow)) {
|
||||
prevIgnore := ignore != "" && i > 0 && strings.ContainsAny(string(s[i-1]), ignore)
|
||||
if !prevIgnore {
|
||||
if vIsCap && nextIsLow {
|
||||
if prevIsCap := i > 0 && s[i-1] >= 'A' && s[i-1] <= 'Z'; prevIsCap {
|
||||
n.WriteByte(delimiter)
|
||||
}
|
||||
}
|
||||
n.WriteByte(v)
|
||||
if vIsLow || vIsNum || nextIsNum {
|
||||
n.WriteByte(delimiter)
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (v == ' ' || v == '_' || v == '-' || v == '.') && !strings.ContainsAny(string(v), ignore) {
|
||||
// replace space/underscore/hyphen/dot with delimiter
|
||||
n.WriteByte(delimiter)
|
||||
} else {
|
||||
n.WriteByte(v)
|
||||
}
|
||||
}
|
||||
|
||||
return n.String()
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
module atypes
|
||||
|
||||
go 1.22
|
||||
@ -1,87 +0,0 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project active2
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name err_ops.go
|
||||
// Created by DEV
|
||||
// Modified 24/03/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
package errs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
|
||||
|
||||
func applyErrOptions(Err *ErrInfo, options ...ErrInfoFnc) *ErrInfo {
|
||||
for _,o := range options {
|
||||
o(Err)
|
||||
}
|
||||
return Err
|
||||
}
|
||||
|
||||
|
||||
|
||||
func ErrInfoWithCause (cause error) ErrInfoFnc {
|
||||
return func(e *ErrInfo) {
|
||||
if cause == nil {
|
||||
return
|
||||
}
|
||||
e.error = *NewErrCause(e.error,cause)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
func ErrInfoWithMessage(message string, params ...any) ErrInfoFnc {
|
||||
if len(params) > 0 {
|
||||
message = fmt.Sprintf(message,params ...)
|
||||
}
|
||||
return func(e *ErrInfo) {
|
||||
e.message = message
|
||||
}
|
||||
}
|
||||
|
||||
func ErrInfoWithInfo (info string, params ...any) ErrInfoFnc {
|
||||
if len(params) > 0 {
|
||||
info = fmt.Sprintf(info,params ...)
|
||||
}
|
||||
return func(e *ErrInfo) {
|
||||
e.info = info
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
func ErrInfoWithStackTrace (offset int) ErrInfoFnc {
|
||||
return func (e *ErrInfo) {
|
||||
e.error = *NewErrTrace(e.error,offset) }
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
func ErrInfoWithMeta (name string, value string) ErrInfoFnc {
|
||||
return func (e *ErrInfo) {
|
||||
if e.metas == nil {
|
||||
e.metas=map[string]string{name:value}
|
||||
return
|
||||
}
|
||||
e.metas[name]=value
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,165 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project active2
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name format_text.go
|
||||
// Created by DEV
|
||||
// Modified 30/03/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
package errs
|
||||
|
||||
import (
|
||||
"atypes/astrings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
FormatShowWrapped uint8 = 1 << iota
|
||||
FormatShowType
|
||||
FormatShowColors
|
||||
FormatShowIndent
|
||||
FormatShowDetails
|
||||
FormatShowCause
|
||||
FormatShowTrace
|
||||
FormatShowFieldEmpty
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
type (
|
||||
|
||||
FmtText struct {
|
||||
Show uint8
|
||||
|
||||
Indent string
|
||||
FieldSep string
|
||||
|
||||
FixFieldLen int
|
||||
MaxStringLen int
|
||||
|
||||
TimeLayout string
|
||||
DateLayout string
|
||||
IntLayout string
|
||||
FloatLayout string
|
||||
|
||||
Color FmtTextColor
|
||||
CodeColor FmtTextColor
|
||||
FieldNameColor FmtTextColor
|
||||
FieldValueColor FmtTextColor
|
||||
|
||||
StringTransformers astrings.Transformers
|
||||
ValueTransformers astrings.Transformers
|
||||
NameTransformers astrings.Transformers
|
||||
}
|
||||
|
||||
FmtTextFnc func (fm *FmtText)
|
||||
)
|
||||
|
||||
|
||||
|
||||
func NewFmtText(options ...FmtTextFnc) *FmtText {
|
||||
f := &FmtText{
|
||||
Indent : " ",
|
||||
FieldSep : " : ",
|
||||
|
||||
TimeLayout : time.RFC822Z,
|
||||
DateLayout : time.RFC822Z,
|
||||
IntLayout : "%d",
|
||||
FloatLayout: "%-10s: %.2f",
|
||||
|
||||
}
|
||||
for _,o := range options {
|
||||
o(f)
|
||||
}
|
||||
if f.FixFieldLen > 0 {
|
||||
f.NameTransformers = append(f.NameTransformers,func(s string)string {
|
||||
return astrings.Pad(s,f.FixFieldLen,' ',true)
|
||||
})
|
||||
}
|
||||
|
||||
return f
|
||||
|
||||
}
|
||||
|
||||
|
||||
func (f *FmtText) Format (err error) []byte {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
st := newFmtTextState(f)
|
||||
defer st.Reset()
|
||||
|
||||
st.format(err)
|
||||
if st.error != nil {
|
||||
e := st.error
|
||||
//st.Reset()
|
||||
st.format(e)
|
||||
}
|
||||
|
||||
return st.Bytes()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func (f *FmtText) ShowWrapped () bool {
|
||||
return f.Show&FormatShowWrapped !=0 }
|
||||
|
||||
func (f *FmtText) ShowType () bool {
|
||||
return f.Show&FormatShowType !=0 }
|
||||
|
||||
func (f *FmtText) ShowColors () bool {
|
||||
return f.Show&FormatShowColors !=0 }
|
||||
|
||||
func (f *FmtText) ShowIndent () bool {
|
||||
return f.Show&FormatShowIndent !=0 }
|
||||
|
||||
func (f *FmtText) ShowDetails() bool {
|
||||
return f.Show&FormatShowDetails !=0 }
|
||||
|
||||
func (f *FmtText) ShowCause () bool {
|
||||
return f.Show&FormatShowCause !=0 }
|
||||
|
||||
func (f *FmtText) ShowTrace () bool {
|
||||
return f.Show&FormatShowTrace !=0 }
|
||||
|
||||
func (f *FmtText) ShowFieldEmpty () bool {
|
||||
return f.Show&FormatShowFieldEmpty !=0 }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func FmtTextWithNameLenTransformer(len int) FmtTextFnc {
|
||||
return func(f *FmtText) {
|
||||
f.NameTransformers = append(f.NameTransformers,func(s string)string {
|
||||
return astrings.Pad(s,len,' ',true)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func FmtTextWithNameTransformer (transformer ...astrings.Transform) FmtTextFnc {
|
||||
return func(f *FmtText) {
|
||||
f.NameTransformers = append(f.NameTransformers,transformer...)
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,204 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project active2
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name format_text_builder.go
|
||||
// Created by DEV
|
||||
// Modified 30/03/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
package errs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
fmtTextState struct {
|
||||
f *FmtText
|
||||
buffer bytes.Buffer
|
||||
level int
|
||||
error error
|
||||
}
|
||||
|
||||
)
|
||||
|
||||
func newFmtTextState(f *FmtText) *fmtTextState {
|
||||
return &fmtTextState{ f : f } }
|
||||
|
||||
|
||||
|
||||
func (s *fmtTextState) Reset () {
|
||||
s.buffer.Reset()
|
||||
s.level = 0
|
||||
s.error = nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (s *fmtTextState) Level () int {
|
||||
return s.level }
|
||||
|
||||
func (s *fmtTextState) Error () error {
|
||||
return s.error }
|
||||
|
||||
|
||||
func (s *fmtTextState) Bytes () []byte {
|
||||
return s.buffer.Bytes() }
|
||||
|
||||
|
||||
|
||||
func (s *fmtTextState) AddError (err error) {
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (s *fmtTextState) AddCause (err error) {
|
||||
if err == nil || !s.f.ShowCause() {
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (s *fmtTextState) AddTrace (trace StackTrace) {
|
||||
if trace == nil || !s.f.ShowTrace() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (s *fmtTextState) AddWrapped(err error) {
|
||||
if err == nil || !s.f.ShowWrapped() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func (s *fmtTextState) AddCode (code string) {
|
||||
s.writeField("error", s.f.ValueTransformers.Apply(code)) }
|
||||
|
||||
func (s *fmtTextState) AddType (ter string ) {
|
||||
s.writeField("error-type",ter) }
|
||||
|
||||
|
||||
|
||||
|
||||
func (s *fmtTextState) AddString (str string) {
|
||||
s.writeString(s.f.StringTransformers.Apply(str))
|
||||
}
|
||||
|
||||
func (s *fmtTextState) AddStrings(str []string) {
|
||||
for _,st := range str {
|
||||
s.writeString(s.f.StringTransformers.Apply(st))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func (s *fmtTextState) AddFieldString (name string, value string ) {
|
||||
value = s.f.ValueTransformers.Apply(value)
|
||||
if len(value) == 0 && !s.f.ShowFieldEmpty() {
|
||||
return
|
||||
}
|
||||
s.writeField(name,value) }
|
||||
|
||||
func (s *fmtTextState) AddFieldInt (name string, value int ) {
|
||||
s.writeField(name,fmt.Sprintf(s.f.IntLayout,value)) }
|
||||
|
||||
func (s *fmtTextState) AddFieldFloat (name string, value float64 ) {
|
||||
s.writeField(name,fmt.Sprintf(s.f.FloatLayout,value)) }
|
||||
|
||||
func (s *fmtTextState) AddFieldTime (name string, value time.Time) {
|
||||
s.writeField(name,value.Format(s.f.TimeLayout)) }
|
||||
|
||||
func (s *fmtTextState) AddFieldDate (name string, value time.Time) {
|
||||
s.writeField(name,value.Format(s.f.DateLayout)) }
|
||||
|
||||
|
||||
func (s *fmtTextState) writeField (name string, value string) {
|
||||
name = s.f.NameTransformers.Apply (name)
|
||||
if !s.f.ShowColors() {
|
||||
s.writeString(name)
|
||||
s.writeString(s.f.FieldSep)
|
||||
s.writeString(value)
|
||||
s.buffer.WriteString("\n")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func (s *fmtTextState) writeString(str string) {
|
||||
s.buffer.WriteString(str)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
func (s *fmtTextState) format (er error) {
|
||||
dn := false
|
||||
defer func(d *bool, s *fmtTextState){
|
||||
if !(*d) {
|
||||
if s.error == nil {
|
||||
s.error = NewErrCause(G.ErrFormat,NewErrPanic(recover()))
|
||||
} else {
|
||||
s.error = NewErrCause(G.ErrFormat,s.error)
|
||||
}
|
||||
} else if s.level != 0 {
|
||||
s.error = G.ErrFormatLevel
|
||||
}
|
||||
if s.error != nil {
|
||||
panic(s.error)
|
||||
}
|
||||
}(&dn, s)
|
||||
|
||||
if fm,is := er.(Formattable); is {
|
||||
fm.BuildFormat(s)
|
||||
} else {
|
||||
s.build(er)
|
||||
}
|
||||
dn=true
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
func (s *fmtTextState) build (er error) {
|
||||
rt := reflect.TypeOf(er)
|
||||
if rt.Kind() == reflect.Pointer {
|
||||
er = reflect.ValueOf(er).Elem().Interface().(error)
|
||||
if er == nil {
|
||||
return
|
||||
}
|
||||
rt = rt.Elem()
|
||||
}
|
||||
|
||||
s.AddCode(er.Error())
|
||||
s.AddType(rt.String())
|
||||
|
||||
Extract(s,er)
|
||||
|
||||
s.AddWrapped(Unwrap(er))
|
||||
s.AddCause (UnwrapCause(er))
|
||||
s.AddTrace (UnwrapTrace(er))
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,103 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project active2
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name field_extractor.go
|
||||
// Created by DEV
|
||||
// Modified 31/03/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
package errs
|
||||
|
||||
import "time"
|
||||
|
||||
type (
|
||||
|
||||
|
||||
FormatExtractor interface {
|
||||
Extract (builder FormatBuilder, err error) bool
|
||||
}
|
||||
|
||||
FormatExtractorFnc func (builder FormatBuilder, err error) bool
|
||||
|
||||
|
||||
FormatExtractors []FormatExtractor
|
||||
|
||||
)
|
||||
|
||||
func (f FormatExtractorFnc) Extract (builder FormatBuilder, err error) bool {
|
||||
return f(builder,err) }
|
||||
|
||||
|
||||
|
||||
func (l FormatExtractors) Extract (builder FormatBuilder, err error) bool {
|
||||
if err == nil || len(l) == 0 {
|
||||
return true
|
||||
}
|
||||
for _,f := range l {
|
||||
if f != nil {
|
||||
if !f.Extract(builder,err) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
func (l FormatExtractors) Append (exf ...FormatExtractor) FormatExtractors {
|
||||
return append(l,exf...) }
|
||||
|
||||
|
||||
|
||||
|
||||
func DefaultsExtractors () FormatExtractors {
|
||||
|
||||
return []FormatExtractor{
|
||||
FormatExtractorFnc(func (b FormatBuilder, e error) bool {
|
||||
if ms,is := e.(interface { Code() string }); is {
|
||||
b.AddFieldString("code",ms.Code())
|
||||
}
|
||||
return true
|
||||
}),
|
||||
|
||||
FormatExtractorFnc(func (b FormatBuilder, e error) bool {
|
||||
if ms,is := e.(interface { Message() string }); is {
|
||||
b.AddFieldString("message",ms.Message())
|
||||
}
|
||||
return true
|
||||
}),
|
||||
FormatExtractorFnc(func (b FormatBuilder, e error) bool {
|
||||
if in,is := e.(interface { Info () string }); is {
|
||||
b.AddFieldString("info",in.Info())
|
||||
}
|
||||
return true
|
||||
}),
|
||||
FormatExtractorFnc(func (b FormatBuilder, e error) bool {
|
||||
if tm,is := e.(interface { Time() time.Time }); is {
|
||||
b.AddFieldTime("time",tm.Time())
|
||||
}
|
||||
return true
|
||||
}),
|
||||
FormatExtractorFnc(func (b FormatBuilder, e error) bool {
|
||||
if tm,is := e.(interface { Date() time.Time }); is {
|
||||
b.AddFieldDate("date",tm.Date())
|
||||
}
|
||||
return true
|
||||
}),
|
||||
}
|
||||
}
|
||||
@ -1,83 +0,0 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project active2
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name error_formattable_options.go
|
||||
// Created by DEV
|
||||
// Modified 30/03/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
package errs
|
||||
|
||||
import (
|
||||
"time"
|
||||
"typex"
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
FormatOps struct {
|
||||
FormatShow
|
||||
|
||||
Indent string
|
||||
FieldSep string
|
||||
|
||||
TimeLayout string
|
||||
IntLayout string
|
||||
FloatLayout string
|
||||
|
||||
Color FormatColor
|
||||
CodeColor FormatColor
|
||||
FieldNameColor FormatColor
|
||||
FieldValueColor FormatColor
|
||||
|
||||
StringAdapters typex.StringAdapters
|
||||
ValueAdapters typex.StringAdapters
|
||||
NameAdapters typex.StringAdapters
|
||||
}
|
||||
|
||||
FormatOpsFnc func (ops any)
|
||||
)
|
||||
|
||||
|
||||
func NewFormatOps (options ...FormatOpsFnc) *FormatOps {
|
||||
os := &FormatOps {
|
||||
Indent : " ",
|
||||
FieldSep : " : ",
|
||||
|
||||
TimeLayout : time.RFC822Z,
|
||||
IntLayout : "%d",
|
||||
FloatLayout: "%-10s: %.2f",
|
||||
}
|
||||
for _,o := range options {
|
||||
o(os)
|
||||
}
|
||||
return os
|
||||
}
|
||||
|
||||
|
||||
func (o *FormatOps) Clone (options ...FormatOpsFnc) *FormatOps {
|
||||
if len(options) == 0 {
|
||||
return o
|
||||
}
|
||||
no := *o
|
||||
for _,op := range options {
|
||||
op(&no)
|
||||
}
|
||||
return &no
|
||||
}
|
||||
|
||||
@ -1,71 +0,0 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project active2
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name format_use_ops.go
|
||||
// Created by DEV
|
||||
// Modified 30/03/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
package errs
|
||||
|
||||
|
||||
|
||||
const (
|
||||
|
||||
FormatShowWrapped FormatShow = 1 << iota
|
||||
FormatShowType
|
||||
FormatShowColors
|
||||
FormatShowIndent
|
||||
FormatShowDetails
|
||||
FormatShowCause
|
||||
FormatShowTrace
|
||||
FormatShowFieldEmpty
|
||||
)
|
||||
|
||||
|
||||
|
||||
type (
|
||||
|
||||
FormatShow uint8
|
||||
|
||||
)
|
||||
|
||||
func (u FormatShow) ShowWrapped () bool {
|
||||
return u&FormatShowWrapped !=0 }
|
||||
|
||||
func (u FormatShow) ShowType () bool {
|
||||
return u&FormatShowType !=0 }
|
||||
|
||||
func (u FormatShow) ShowColors () bool {
|
||||
return u&FormatShowColors !=0 }
|
||||
|
||||
func (u FormatShow) ShowIndent () bool {
|
||||
return u&FormatShowIndent !=0 }
|
||||
|
||||
func (u FormatShow) ShowDetails() bool {
|
||||
return u&FormatShowDetails !=0 }
|
||||
|
||||
func (u FormatShow) ShowCause () bool {
|
||||
return u&FormatShowCause !=0 }
|
||||
|
||||
func (u FormatShow) ShowTrace () bool {
|
||||
return u&FormatShowTrace !=0 }
|
||||
|
||||
func (u FormatShow) ShowFieldEmpty () bool {
|
||||
return u&FormatShowFieldEmpty !=0 }
|
||||
|
||||
@ -1,84 +0,0 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project active2
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name format_text_ops.go
|
||||
// Created by DEV
|
||||
// Modified 30/03/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
package errs
|
||||
|
||||
import (
|
||||
"time"
|
||||
"typex"
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
FormatTextOps struct {
|
||||
FormatShow
|
||||
|
||||
Indent string
|
||||
FieldSep string
|
||||
|
||||
TimeLayout string
|
||||
IntLayout string
|
||||
FloatLayout string
|
||||
|
||||
Color FormatColor
|
||||
CodeColor FormatColor
|
||||
FieldNameColor FormatColor
|
||||
FieldValueColor FormatColor
|
||||
|
||||
StringAdapters typex.StringAdapters
|
||||
ValueAdapters typex.StringAdapters
|
||||
NameAdapters typex.StringAdapters
|
||||
}
|
||||
|
||||
FormatTextOpsFnc func (ops *FormatTextOps)
|
||||
)
|
||||
|
||||
|
||||
func NewFormatTextOps (options ...FormatTextOpsFnc) *FormatTextOps {
|
||||
os := &FormatTextOps {
|
||||
Indent : " ",
|
||||
FieldSep : " : ",
|
||||
|
||||
TimeLayout : time.RFC822Z,
|
||||
IntLayout : "%d",
|
||||
FloatLayout: "%-10s: %.2f",
|
||||
}
|
||||
for _,o := range options {
|
||||
o(os)
|
||||
}
|
||||
return os
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
func (o *FormatTextOps) Clone (options ...FormatTextOpsFnc) *FormatTextOps {
|
||||
if len(options) == 0 {
|
||||
return o
|
||||
}
|
||||
no := *o
|
||||
for _,op := range options {
|
||||
op(&no)
|
||||
}
|
||||
return &no
|
||||
}
|
||||
@ -1,219 +0,0 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// Project active2
|
||||
// Active Thing (activething.com) git.activething.com/go
|
||||
//
|
||||
// File name format_text_builder.go
|
||||
// Created by DEV
|
||||
// Modified 30/03/2024
|
||||
//
|
||||
// Copyright 2024 activething.com
|
||||
// ------------------------------------------------------------------------
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
package errs
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
type (
|
||||
|
||||
formatTextState struct {
|
||||
options FormatTextOps
|
||||
buffer bytes.Buffer
|
||||
level int
|
||||
error error
|
||||
}
|
||||
|
||||
)
|
||||
|
||||
func newFormatTextState (options *FormatTextOps) *formatTextState {
|
||||
st := &formatTextState{
|
||||
options : *options,
|
||||
}
|
||||
return st
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func (f *formatTextState) Options() FormatOps {
|
||||
return f.options.FormatOps }
|
||||
|
||||
func (f *formatTextState) Reset () {
|
||||
f.buffer.Reset()
|
||||
f.level = 0
|
||||
f.error = nil
|
||||
}
|
||||
|
||||
|
||||
|
||||
func (f *formatTextState) Level () int {
|
||||
return f.level }
|
||||
|
||||
func (f *formatTextState) Error () error {
|
||||
return f.error }
|
||||
|
||||
|
||||
func (f *formatTextState) Bytes () []byte {
|
||||
return f.buffer.Bytes() }
|
||||
|
||||
|
||||
|
||||
func (f *formatTextState) AddError (err error, options ...FormatOpsFnc) {
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (f *formatTextState) AddCause (err error, options ...FormatOpsFnc) {
|
||||
if err == nil || !f.options.ShowCause() {
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (f *formatTextState) AddTrace (trace StackTrace, options ...FormatOpsFnc) {
|
||||
if trace == nil || !f.options.ShowTrace() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (f *formatTextState) AddWrapped(err error, options ...FormatOpsFnc) {
|
||||
if err == nil || !f.options.ShowWrapped() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func (f *formatTextState) AddCode (code string, options ...FormatOpsFnc) {
|
||||
f.writeField("error",f.options.ValueAdapters.Apply(code),options...) }
|
||||
|
||||
func (f *formatTextState) AddType (ter string , options ...FormatOpsFnc) {
|
||||
f.writeField("error-type",ter, options ...) }
|
||||
|
||||
|
||||
|
||||
|
||||
func (f *formatTextState) AddString (str string, options ...FormatOpsFnc) {
|
||||
f.writeString(f.options.StringAdapters.Apply(str),options...)
|
||||
}
|
||||
|
||||
func (f *formatTextState) AddStrings(str []string, options ...FormatOpsFnc) {
|
||||
for _,s := range str {
|
||||
f.writeString(f.options.StringAdapters.Apply(s))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func (f *formatTextState) AddFieldString (name string, value string , options ...FormatOpsFnc) {
|
||||
value = f.options.ValueAdapters.Apply(value)
|
||||
if len(value) == 0 && !f.options.ShowFieldEmpty() {
|
||||
return
|
||||
}
|
||||
f.writeField(name,value) }
|
||||
|
||||
func (f *formatTextState) AddFieldInt (name string, value int , options ...FormatOpsFnc) {
|
||||
f.writeField(name,fmt.Sprintf(f.options.IntLayout,value),options...) }
|
||||
|
||||
func (f *formatTextState) AddFieldFloat (name string, value float64 , options ...FormatOpsFnc) {
|
||||
f.writeField(name,fmt.Sprintf(f.options.FloatLayout,value),options ...) }
|
||||
|
||||
func (f *formatTextState) AddFieldTime (name string, value time.Time, options ...FormatOpsFnc) {
|
||||
f.writeField(name,value.Format(f.options.TimeLayout),options ...) }
|
||||
|
||||
|
||||
|
||||
func (f *formatTextState) writeField (name string, value string, options ...FormatOpsFnc) {
|
||||
name = f.options.NameAdapters.Apply (name)
|
||||
if !f.options.ShowColors() {
|
||||
f.writeString(name)
|
||||
f.writeString(f.options.FieldSep)
|
||||
f.writeString(value)
|
||||
f.buffer.WriteString("\n")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func (f *formatTextState) writeString(str string, options ...FormatOpsFnc) {
|
||||
f.buffer.WriteString(str)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
func (f *formatTextState) format (er error) {
|
||||
dn := false
|
||||
defer func(d *bool, s *formatTextState){
|
||||
if !(*d) {
|
||||
if s.error == nil {
|
||||
s.error = NewErrCause(G.ErrFormat,NewErrPanic(recover()))
|
||||
} else {
|
||||
s.error = NewErrCause(G.ErrFormat,s.error)
|
||||
}
|
||||
} else if s.level != 0 {
|
||||
s.error = G.ErrFormatLevel
|
||||
}
|
||||
}(&dn,f)
|
||||
|
||||
if fm,is := er.(Formattable); is {
|
||||
fm.BuildFormat(f)
|
||||
} else {
|
||||
f.build(er)
|
||||
}
|
||||
dn=true
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
func (f *formatTextState) build (er error) {
|
||||
rt := reflect.TypeOf(er)
|
||||
if rt.Kind() == reflect.Pointer {
|
||||
er = reflect.ValueOf(er).Elem().Interface().(error)
|
||||
if er == nil {
|
||||
return
|
||||
}
|
||||
rt = rt.Elem()
|
||||
}
|
||||
|
||||
f.AddCode(er.Error())
|
||||
f.AddType(rt.String())
|
||||
|
||||
if ms,is := er.(interface { Message() string }); is {
|
||||
f.AddFieldString("message",ms.Message())
|
||||
}
|
||||
if in,is := er.(interface { Info () string }); is {
|
||||
f.AddFieldString("info",in.Info())
|
||||
}
|
||||
if tm,is := er.(interface { Time() time.Time }); is {
|
||||
f.AddFieldTime("time",tm.Time())
|
||||
}
|
||||
|
||||
|
||||
f.AddWrapped(Unwrap(er))
|
||||
f.AddCause(UnwrapCause(er))
|
||||
f.AddTrace(UnwrapTrace(er))
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
module typex
|
||||
|
||||
go 1.22
|
||||
Loading…
Reference in new issue