Añadido el formateador de errores de texto textFormatter.

Añadidas funciones de cjson.write a btes.Buffer
master
DEV 2 years ago
parent 38177ccf76
commit f01cf4243d

@ -1,12 +1,13 @@
package main
import (
"bins/bfers"
"errs"
"errs/collr"
"errs/collr/fjson"
"errs/collr/ftext"
"errs/stack"
"fmt"
"time"
)
@ -49,6 +50,10 @@ func (c MiCustomErr) Code() string {
return "custom-code"
}
func (c MiCustomErr) Int () int {
return 33423
}
/*
func fm (b *bytes.Buffer, e error, l int) {
@ -65,12 +70,18 @@ func (c MiCustomErr) Unwrap () error {
}
func (c MiCustomErr) Collect (collector collr.Collector) {
collector.AddFieldInt("UnInt",c.Int())
collector.AddFieldFloat("UnFloat",34.33)
collector.AddFieldAny("UnoCualquiera",struct {
A string
B int
T time.Time
F float64
}{
A : "UUnA",
B : 3,
T : time.Now(),
F : 2.343,
})
}
@ -100,8 +111,8 @@ func printCollection (ec collr.ErrorCollection) {
func main() {
me := errs.WrapWithInfo(bfers.G.ErrTooLarge.WrapWithCause(MiCustomErr{}),
errs.ErrInfoWithInfo("Mi mensaje"))
me := errs.WrapWithCause(errs.WrapWithInfo(MiCustomErr{},
errs.ErrInfoWithInfo("Mi mensaje")),errs.ErrCode("UnERRORito"))
mu := errs.NewErrMulti(
@ -111,12 +122,17 @@ func main() {
)
//printCollection(*collr.NewErrorCollection(me).Collect(true,true,true))
jso := fjson.NewJSONFormatter()
f := ftext.DefaultFormatter()
j := fjson.DefaultFormatter()
fmt.Print(string(f.FormatError(errs.WrapWithTrace(mu,1))))
fmt.Print(string(jso.FormatError(errs.WrapWithTrace(mu,1))))
fmt.Print(string(j.FormatError(errs.WrapWithTrace(mu,1))))
}

@ -109,7 +109,7 @@ func genCharEscapes () []byte {
func Esc (code Code) string {
return code.String() }
return code.Begin() }
func EscEnd () string {
return g.endEscStr }

@ -182,11 +182,10 @@ func (c Code) escape () []byte {
func (c Code) stringValues() string {
return string(c.escape())
}
return string(c.escape()) }
func (c Code) String() string {
func (c Code) Begin() string {
if c == 0 {
return ""
}
@ -198,7 +197,8 @@ func (c Code) End () string {
if c == 0 {
return ""
}
return g.endEscStr }
return g.endEscStr
}
@ -242,7 +242,7 @@ func (c Code) Sprintln(format string, params ...any) string {
func (c Code) wrap(str ...any) string {
b := bytes.Buffer{}
b.WriteString(c.String())
b.WriteString(c.Begin())
for _,s := range str {
b.WriteString(fmt.Sprint(s))
}

@ -23,8 +23,6 @@
package bfers
import "errs"
const (
minBitSize = 6
@ -47,12 +45,12 @@ var (
ErrNegativeRead ErrBuffer
ErrUnreadInvalid ErrBuffer
}{
ErrOutOfRange: ErrBuffer{errs.ErrCode("out-of-range")},
ErrWriteCount: ErrBuffer{errs.ErrCode("write-count")},
ErrTooShort: ErrBuffer{errs.ErrCode("too-short")},
ErrTooLarge: ErrBuffer{errs.ErrCode("too-large")},
ErrNegativeRead: ErrBuffer{errs.ErrCode("negative-read")},
ErrUnreadInvalid: ErrBuffer{errs.ErrCode("unread-invalid")},
ErrOutOfRange: ErrBuffer{"out-of-range"},
ErrWriteCount: ErrBuffer{"write-count"},
ErrTooShort: ErrBuffer{"too-short"},
ErrTooLarge: ErrBuffer{"too-large"},
ErrNegativeRead: ErrBuffer{"negative-read"},
ErrUnreadInvalid: ErrBuffer{"unread-invalid"},
}
g = struct {

@ -23,12 +23,11 @@
package bfers
import (
"errs"
)
type (
ErrBuffer struct { errs.ErrCode }
ErrBuffer struct { string }
)
func (e ErrBuffer) Error() string {
return e.string
}

@ -25,6 +25,7 @@ package bfers
import (
"strconv"
"time"
"unicode/utf8"
)
@ -77,6 +78,12 @@ func (b *Buffer) WriteComplexStr(value complex128, formatter byte, precision int
b.data = append(b.data, strconv.FormatComplex(value, formatter, precision, 128)...)
}
func (b *Buffer) WriteDateStr (value time.Time, layout string) {
b.lastOp = opInvalid
if layout == "" {
layout = time.RFC822
}
b.data = append(value.AppendFormat(b.data,layout))
}

@ -171,12 +171,17 @@ func WriteFloat (b *bfers.Buffer, f float64, bits int, quoted bool) {
}
func WriteDate(b *bfers.Buffer, value time.Time, layout string) {
var t [64]byte
func WriteDate(b *bfers.Buffer, value time.Time, layout string, quote bool) {
if layout == "" {
layout = time.RFC3339
}
b.WOQ(true,'"',value.AppendFormat(t[:0],layout))
if quote {
b.WriteByte('"')
}
b.WriteDateStr(value,layout)
if quote {
b.WriteByte('"')
}
}

@ -25,7 +25,7 @@
package errs
import (
"errs/fmtr/ftext"
"errs/collr/ftext"
"errs/stack"
"fmt"
"reflect"
@ -46,7 +46,7 @@ const (
var (
G = struct {
Formatter ErrorFormatter
Formatter ErrorFormatter
ErrParam ErrCode
ErrParamNil ErrCode

@ -36,8 +36,9 @@ type (
ErrorCollection struct {
Err error
ErrStr string
Types []reflect.Type
Fields Fields
Types []reflect.Type
TypesStr []string
Fields Fields
Causes []ErrorCollection
Trace stack.Trace
@ -81,7 +82,9 @@ func (c *ErrorCollection) collect (addFields,addCauses,addTrace bool) *ErrorColl
c.ErrStr = c.Err.Error()
for ne != nil {
c.Types = append(c.Types,reflect.TypeOf(ne))
rt := reflect.TypeOf(ne)
c.Types = append(c.Types,rt)
c.TypesStr = append(c.TypesStr,rt.String())
// Unwrap Fields
if addFields {

@ -45,6 +45,9 @@ type (
)
func (f *Fields) Len() int {
return len(f.heads) }
func (f *Fields) AddFieldAny (name string, value any) {
f.addField(name, FieldKindAny).anys = append(f.anys,value) }

@ -136,12 +136,12 @@ func (b *jsonBuilder) write (coll *collr2.ErrorCollection, cont bool, level int)
} else {
b.writeOpen("types", indObj, '[', b.pretty)
for i, t := range coll.Types {
for i, t := range coll.TypesStr {
if b.pretty {
b.b.WriteString(ind2Obj)
}
b.b.WriteByte('"')
b.b.WriteString(t.String())
b.b.WriteString(t)
b.b.WriteByte('"')
if i < len(coll.Types)-1 {
b.b.WriteByte(',')
@ -328,7 +328,7 @@ func (b *jsonBuilder) writeFieldValue (fields collr2.Fields, field *collr2.Field
if d.IsZero() && b.f.IgnoreDefaults(){
return false
}
cjson.WriteDate(b.b,d,b.f.layout.TimeLayout)
cjson.WriteDate(b.b,d,b.f.layout.TimeLayout,true)
return true
case collr2.FieldKindDate:
@ -336,7 +336,7 @@ func (b *jsonBuilder) writeFieldValue (fields collr2.Fields, field *collr2.Field
if d.IsZero() && b.f.IgnoreDefaults(){
return false
}
cjson.WriteDate(b.b,d,b.f.layout.DateLayout)
cjson.WriteDate(b.b,d,b.f.layout.DateLayout,true)
return true
case collr2.FieldKindBool:

@ -24,42 +24,134 @@
package ftext
import (
"ansi"
"errs/stack"
"fmt"
"reflect"
"strings"
"sync"
"tbase/astrings"
)
func defaultFrameBuilder (builder *TextBuilder, frame stack.Frame, num int) {
/*
if strings.Index(frame.Package,"runtime") != -1 {
return
const(
)
var (
g = struct {
nullValue []byte
buildDefault sync.Once
formatter *TextFormatter
}{
nullValue: []byte{'n','u','l','l'},
}
)
func DefaultFormatter () *TextFormatter {
g.buildDefault.Do(func() {
g.formatter = NewTextFormatter(
WithNameTransformers(
astrings.TransformFnc(func (s string) string {
return astrings.ToKebab(s) }),
astrings.TransformFnc(func (s string) string {
return astrings.Pad(s,8,' ',true) }),
),
WithSectionsFormat(func(c *Sections) {
c.Main.Set(
func(b *TextBuilder) {
b.AddTextAnsi(ansi.Code(0).SetFgColor(ansi.ColorRed), "# ERROR ------------------------------------------------------\n\n")
},
func(b *TextBuilder) {
b.AddTextAnsi(ansi.Code(0).SetFgColor(ansi.ColorRed), "\n------------------------------------------------------ ERROR #\n")
})
c.Head.Set(func(b *TextBuilder){
if b.Level() == 0 {
b.SetAnsi(ansi.Code(0).SetFgColor(ansi.ColorHRed))
}
}, nil)
c.Fields.Set(func(b *TextBuilder){
if b.Level() == 0 {
b.SetAnsi(ansi.Code(0).SetFgColor(ansi.ColorGreen))
} else if b.level == 1 {
b.SetAnsi(ansi.Code(0).SetFgColor(ansi.ColorCyan))
} else if b.level == 2 {
b.SetAnsi(ansi.Code(0).SetFgColor(ansi.ColorBlue))
}
},nil)
c.Causes.Set(func(b *TextBuilder) {
b.SetAnsi(ansi.Code(0).SetFgColor(ansi.ColorCyan))
b.AddTextAnsi(ansi.Code(0), "\n# PREVIOUS CAUSES -------------------------------------------\n\n")
},nil)
c.Cause.Set(
func(b *TextBuilder) {
b.SetAnsi(ansi.Code(0).SetFgColor(ansi.ColorCyan))
lin := strings.Repeat("-",b.Level())
if b.Level() == 1 {
b.SetAnsi(ansi.Code(0).SetFgColor(ansi.ColorMagenta))
} else if b.level == 3 {
b.SetAnsi(ansi.Code(0).SetFgColor(ansi.ColorGreen))
}
b.AddTextAnsi(0, fmt.Sprintf("%sLevel %d ----------------------------------------------------\n",lin,b.Level()))
}, nil)
c.Trace.Set(func(b *TextBuilder) {
b.SetAnsi(ansi.Code(0).SetFgColor(ansi.ColorHYellow).SetBgColor(ansi.ColorBlack))
b.AddTextAnsi(b.ansiC.SetFgColor(ansi.ColorHBlue), "\n# STACK TRACE ------------------------------------------------\n\n")
},nil)
}))
})
return g.formatter
}
func defaultFrameBuilder (builder *TextBuilder, frame stack.Frame, num int) {
do := strings.Index(frame.Package,"runtime") == -1
var c1, c2, c3, c4 ansi.Code
if builder.Options().ShowAnsi(){
c1 = c1.SetFgColor(ansi.ColorBlue)//.SetBgColor(ansi.ColorHBlack)
c2 = c2.SetFgColor(ansi.ColorMagenta)
c3 = c3.SetFgColor(ansi.ColorWhite)
c4 = c3.SetFgColor(ansi.ColorHWhite)
c1 = c1.SetFgColor(ansi.ColorBlue)//.SetBgColor(ansi.ColorHBlack)
c2 = c2.SetFgColor(ansi.ColorMagenta)
c3 = c3.SetFgColor(ansi.ColorWhite)
c4 = c3.SetFgColor(ansi.ColorHWhite)
builder.AddTextAnsi(c4,fmt.Sprintf("%d %s.%s \n",num,frame.Package, frame.FuncName))
builder.AddTextAnsi(c2,fmt.Sprintf(" %.90s:%d\n", frame.File, frame.LineNumber))
if !do {
return
}
builder.AddText(c4.Sprintf(" %d %s.%s \n",num,frame.Package, frame.FuncName))
builder.AddText(c2.Sprintf(" %.90s:%d\n", frame.File, frame.LineNumber))
f, e := frame.SourceLine()
if e == nil {
builder.AddTextAnsi(fmt.Sprintf(" %s\n", f),c3)
builder.AddTextAnsi(c3,fmt.Sprintf(" %s\n", f))
} else {
builder.AddTextAnsi(fmt.Sprintf(" error %s\n", e.Error()),c3)
builder.AddTextAnsi(c3,fmt.Sprintf(" error %s\n", e.Error()))
}
*/
}
func defaultFallback (b *TextBuilder, err, cause error) {
/*
b.AddText(fmt.Sprintf("Formatter error: Cant format error type (%s)\nValue : %#v \nCause : %s\n",reflect.TypeOf(err).String(),err,cause.Error()))
*/
b.AddTextAnsi(ansi.Code(0).SetFgColor(ansi.ColorHRed),"- FORMAT ERROR -----------------------------------------------\n")
b.AddText(fmt.Sprintf("Cant format error type (%s)\n\n%#v \n\nCause : %s\n",reflect.TypeOf(err).String(),err,cause.Error()))
b.AddTextAnsi(ansi.Code(0).SetFgColor(ansi.ColorHRed),"----------------------------------------------- FORMAT ERROR -\n")
}

@ -26,17 +26,15 @@ package ftext
const (
AddWrapped Option = 1 << iota
AddType
AddCode
AddTypes Option = 1 << iota
AddFields
AddCause
AddCauses
AddTrace
ShowAnsi
UseIndent
NotShowEmpty
IgnoreEmpty
optionsDefault = AddWrapped | AddCode | AddType | ShowAnsi | UseIndent | AddFields | AddCause | AddTrace | NotShowEmpty
optionsDefault = AddTypes | ShowAnsi | UseIndent | AddFields | AddCauses | AddTrace | IgnoreEmpty
)
@ -52,29 +50,25 @@ func (o Option) SetDefaults () Option {
return optionsDefault
}
func (o Option) AddWrapped() bool {
return o&AddWrapped !=0 }
func (o Option) AddType() bool {
return o&AddType !=0 }
func (o Option) AddTypes() bool {
return o&AddTypes !=0 }
func (o Option) AddCode() bool {
return o&AddCode != 0 }
func (o Option) ShowAnsi () bool {
return o&ShowAnsi !=0 }
func (o Option) UseIndent() bool {
return o&UseIndent !=0 }
func (o Option) AddFields() bool {
return o&AddFields !=0 }
func (o Option) AddCause() bool {
return o&AddCause !=0 }
func (o Option) AddCauses() bool {
return o&AddCauses !=0 }
func (o Option) AddTrace() bool {
return o&AddTrace !=0 }
func (o Option) NotShowEmpty() bool {
return o&NotShowEmpty !=0 }
func (o Option) IgnoreEmpty() bool {
return o&IgnoreEmpty !=0 }
func (o Option) ShowAnsi () bool {
return o&ShowAnsi !=0 }
func (o Option) UseIndent() bool {
return o&UseIndent !=0 }

@ -23,12 +23,9 @@
package ftext
import "ansi"
type (
section struct {
ansiC ansi.Code
beginFn func(textBuilder *TextBuilder)
endFn func(textBuilder *TextBuilder)
}
@ -37,20 +34,17 @@ type (
)
func (s *section) Set(ansiC ansi.Code, beginFn, endFn TextBuilderFnc) {
s.ansiC = ansiC
func (s *section) Set(beginFn, endFn TextBuilderFnc) {
s.beginFn,s.endFn = beginFn,endFn }
func (s *section) begin(txtBuilder *TextBuilder) {
txtBuilder.setAnsi(s.ansiC)
if s.beginFn != nil {
s.beginFn(txtBuilder)
}
}
func (s *section) end(txtBuilder *TextBuilder) {
txtBuilder.setAnsi(s.ansiC)
if s.endFn != nil {
s.endFn(txtBuilder)
}

@ -25,15 +25,22 @@ package ftext
import (
"ansi"
"bytes"
"bins/bfers"
"errs/collr"
"fmt"
"strings"
)
type (
TextBuilder struct {
f *TextFormatter
b bytes.Buffer
b *bfers.Buffer
useAux bool
auxB *bfers.Buffer
level int
ansiC ansi.Code
invalid error
}
@ -42,33 +49,238 @@ type (
TextBuilderFnc func (b *TextBuilder)
)
func newTextBuilder(formatter *TextFormatter) *TextBuilder {
return &TextBuilder{
f : formatter,
ansiC: formatter.layout.AnsiC}}
b := &TextBuilder {
f : formatter,
b : bfers.NewBuffer(),
useAux: len(formatter.valueTrans) > 0,
ansiC : formatter.layout.AnsiC,
}
if b.useAux {
b.auxB = bfers.NewBuffer()
} else {
b.auxB = b.b
}
return b
}
func (b *TextBuilder) Level () int {
return b.level }
func (b *TextBuilder) AddText (text string) {
b.b.WriteString(text) }
func (s *TextBuilder) format (err error) {}
func (b *TextBuilder) AddTextAnsi (ansiC ansi.Code, text string) {
if b.f.ShowAnsi() {
if ansiC == 0 {
ansiC = b.ansiC
}
b.b.WriteString(ansiC.Begin())
defer b.b.WriteString(ansiC.End())
}
b.b.WriteString(text)
}
func (b *TextBuilder) SetAnsi(ansiC ansi.Code) {
if ansiC != 0 {
b.ansiC = ansiC
} else {
b.ansiC = b.f.layout.AnsiC
}
}
func (b *TextBuilder) format (err error) {
c := collr.NewErrorCollection(err)
if c.Collect(b.f.AddFields(), b.f.AddCauses(), b.f.AddTrace()); c.Invalid != nil {
//b.writeFormatError(cl.Invalid)
return
}
b.write(c,false, 0)
}
func (b *TextBuilder) write (c *collr.ErrorCollection, cont bool, level int) {
if b.invalid != nil {
return
}
ind := strings.Repeat(b.f.layout.Indent,level)
//ind2:= ind +b.f.layout.Indent
func (s *TextBuilder) setAnsi(ansiC ansi.Code) {
if ansiC != 0 {
s.ansiC = ansiC
} else {
s.ansiC = s.f.layout.AnsiC
d := false
f := b.f
b.level = level
if level == 0 {
b.f.sections.Main.begin(b)
}
defer func(bl *TextBuilder, dn *bool,er error){
if !(*dn) {
if rc := recover(); rc != nil {
if er,is := rc.(error); is {
bl.invalid = er
} else {
bl.invalid = fmt.Errorf("%#v",rc)
}
bl.f.onFormatError(bl,er,bl.invalid)
}
}
}(b,&d, c.Err)
f.sections.Head.begin(b)
b.writeFieldNameValue(collr.FieldNameError, c.ErrStr, ind)
if f.AddTypes() {
b.writeFieldNameValue(collr.FieldNameType,strings.Join(c.TypesStr,","), ind)
}
f.sections.Head.end(b)
if f.AddFields() && c.Fields.Len() > 0 {
f.sections.Fields.begin(b)
heads := c.Fields.GetHeads()
for _,fl := range heads {
b.writeField(c.Fields,fl,ind)
}
f.sections.Fields.end(b)
}
if len(c.Causes) > 0 {
if level == 0 {
f.sections.Causes.begin(b)
} else {
panic("Error ocurrido")
}
b.level++
for _,cs := range c.Causes {
f.sections.Cause.begin(b)
b.write(&cs,false,level+1)
f.sections.Cause.end(b)
}
if level == 0 {
f.sections.Causes.end(b)
}
}
if c.Trace != nil {
f.sections.Trace.begin(b)
for nu,fm := range c.Trace.Frames() {
b.f.frameBuilder(b,fm,nu)
}
f.sections.Trace.end(b)
}
if level == 0 {
b.f.sections.Main.end(b)
}
d = true
}
func (s *TextBuilder) reset () {
s.b.Reset()
s.f = nil
s.invalid = nil
}
func (b *TextBuilder) reset () {
b.b.Reset()
if b.useAux {
b.auxB.Reset()
b.useAux = false
}
b.f = nil
b.level = 0
b.invalid = nil
}
func (b *TextBuilder) writeFieldBegin (name, indent string) {
if b.ansiC != 0 {
b.b.WriteString(b.ansiC.Begin())
}
b.b.WriteString(indent)
b.b.WriteString(b.f.nameTrans.Transform(name))
b.b.WriteString(b.f.layout.FieldSep)
}
func (b *TextBuilder) writeFieldEnd () {
b.b.WriteByte('\n')
if b.ansiC != 0 {
b.b.WriteString(b.ansiC.End())
}
}
func (b *TextBuilder) writeFieldNameValue(name string, value string, indent string) {
p:= b.b.Len()
b.writeFieldBegin(name,indent)
if b.f.IgnoreEmpty() && len(value) == 0 {
b.b.Truncate(p)
return
}
b.b.WriteString(b.f.valueTrans.Transform(value))
b.writeFieldEnd()
}
func (b *TextBuilder) writeField (fields collr.Fields, field *collr.FieldHead, indent string) {
p := b.b.Len()
b.writeFieldBegin(field.Name,indent)
if !b.writeFieldValue(fields,field) {
b.b.Truncate(p)
return
}
b.writeFieldEnd()
}
func (b *TextBuilder) writeFieldValue (fields collr.Fields, field *collr.FieldHead) bool {
switch field.Kind {
case collr.FieldKindFloat:
b.auxB.WriteFloatStr(fields.GetFieldValueFloat(field),'f',-1)
case collr.FieldKindInt:
b.auxB.WriteIntStr(int64(fields.GetFieldValueInt(field)),10)
case collr.FieldKindString:
s := fields.GetFieldValueString(field)
if b.f.IgnoreEmpty() && len(s) == 0 {
return false
}
b.auxB.WriteString(fields.GetFieldValueString(field))
case collr.FieldKindTime:
b.auxB.WriteDateStr(fields.GetFieldValueDate(field), b.f.layout.TimeLayout)
case collr.FieldKindDate:
b.auxB.WriteDateStr(fields.GetFieldValueDate(field), b.f.layout.DateLayout)
case collr.FieldKindBool:
b.auxB.WriteBoolStr(fields.GetFieldValueBool(field))
default:
a := fields.GetFieldValueAny(field)
if a == nil {
if b.f.IgnoreEmpty() {
return false
}
b.auxB.WOQ(false,'"',g.nullValue)
} else {
s := fmt.Sprintf("%#v",a)
if b.f.IgnoreEmpty() && len(s) == 0 {
return false
}
b.auxB.WriteString(s)
}
}
if b.useAux {
b.b.WriteString(b.f.valueTrans.Transform(string(b.auxB.Bytes())))
b.auxB.Reset()
}
return true
}

@ -82,6 +82,9 @@ func (f *TextFormatter) FormatError (err error) []byte {
func WithErrorFallbacks (format, cause, trace ErrorFallbackFnc) TextFormatterFnc {
return func(f *TextFormatter) {
if format == nil {

@ -82,7 +82,7 @@ func (s *TextBuilder) AddTextAnsi (text string, ansiC ansi.Code) {
if ansiC == 0 {
ansiC = s.ansiC
}
s.b.WriteString(ansiC.String())
s.b.WriteString(ansiC.Begin())
defer s.b.WriteString(ansiC.End())
}
@ -391,7 +391,7 @@ func (s *TextBuilder) writeField (name string, value string, head bool) {
v := s.f.valueTrans.Transform(value)
if s.ansiC != 0 {
s.b.WriteString(s.ansiC.String())
s.b.WriteString(s.ansiC.Begin())
}
s.b.WriteString(s.indent)
s.b.WriteString(n)
@ -400,7 +400,7 @@ func (s *TextBuilder) writeField (name string, value string, head bool) {
s.b.WriteByte('\n')
if s.ansiC != 0 {
s.b.WriteString(s.ansiC.String())
s.b.WriteString(s.ansiC.Begin())
}
}

@ -551,7 +551,7 @@ func packDate(state *pkrs.State, value time.Time, flags pkrs.Flags) {
if state.Error != nil {
panic(pkrs.G.ErrInvalidState.WrapWithCause(state.Error))
}
cjson.WriteDate(state.Buffer,value,flags.DateFormat())
cjson.WriteDate(state.Buffer,value,flags.DateFormat(),true)
//state.WOQ(true,'"',value.AppendFormat(state.Temp[:0],flags.DateFormat()))
}

Loading…
Cancel
Save

Powered by TurnKey Linux.