From 188dc681921d19183ddfdd772ec47cf37eb7e488 Mon Sep 17 00:00:00 2001 From: DEV Date: Sat, 6 Apr 2024 15:56:32 +0200 Subject: [PATCH] incluidas las librerias de transformacion de strings --- app/main.go | 27 +++++-- core/ansi/active.go | 66 +++++++++++++++-- core/ansi/code.go | 21 +++--- core/ansi/code_color.go | 55 ++++++++++++++ core/ansi/non_escape_reader.go | 99 +++++++++++++++++++++++++ core/ansi/non_escape_writer.go | 44 +---------- core/bins/chars/active.go | 2 +- core/bins/chars/ascii_char_atts.go | 22 +++--- core/bins/chars/{char_att.go => att.go} | 6 +- core/bins/chars/char_atts.go | 22 +++--- 10 files changed, 270 insertions(+), 94 deletions(-) create mode 100644 core/ansi/code_color.go create mode 100644 core/ansi/non_escape_reader.go rename core/bins/chars/{char_att.go => att.go} (92%) diff --git a/app/main.go b/app/main.go index 18ccae2..4d38758 100644 --- a/app/main.go +++ b/app/main.go @@ -4,7 +4,6 @@ import ( "ansi" "errs/stack" "fmt" - "os" ) @@ -16,6 +15,21 @@ func printTrace (s stack.Trace) { } +func GenerateBinaryString() string { + binaryString := "" + for c := 0; c < 255; c++ { + if ('a' <= byte(c) && byte(c) <= 'z') || ('A' <= byte(c) && byte(c) <= 'Z') || byte(c) == '@' { + binaryString += "1" + } else { + binaryString += "0" + } + } + return binaryString +} + + + + type ( MiCustomErr struct { @@ -45,15 +59,18 @@ func (c MiCustomErr) Unwrap () error { func main() { - c := ansi.ColorRed.SetBgColor(ansi.ColorHWhite).SetBlink(true) + result := GenerateBinaryString() + fmt.Println(result) + + c := ansi.ColorRed.SetBgColor(ansi.ColorHWhite).SetBlink(true).SetBold(true) fmt.Printf("Attributes %s\n",c.Atts()) s := fmt.Sprintf("%sColor Red y White \n",c.Escape()) - w := ansi.NewNonEscapeWriter(os.Stdout) + sf := ansi.FilterEscapes([]byte(s)) - os.Stdout.WriteString(s) + fmt.Printf("Filtrados %s\n",sf) + fmt.Printf("No filtrados %s\n",s) - w.Write([]byte(s)) } diff --git a/core/ansi/active.go b/core/ansi/active.go index f999a92..5617322 100644 --- a/core/ansi/active.go +++ b/core/ansi/active.go @@ -23,22 +23,27 @@ package ansi - +import ( + "bytes" +) var ( - G = struct { - beginEscape []byte - endEscape []byte - clearEscape []byte + g = struct { + beginEscIni []byte + beginEscEnd []byte + endEsc []byte + charsEscs []byte + endEscStr string ics []colorInfo itx []textInfo }{ - beginEscape : []byte("\x1b["), - endEscape : []byte{'m'}, - clearEscape : []byte("\x1b[0m"), + beginEscIni : []byte("\x1b["), + beginEscEnd : []byte{'m'}, + endEsc : []byte("\x1b[0m"), + endEscStr : "\x1b[0m", ics : []colorInfo{ {[]byte("none") ,[]byte{},[]byte{}}, @@ -69,8 +74,53 @@ var ( {[]byte("underline-off"), []byte{'2','4'}}, {[]byte("blink-off"), []byte{'2','5'}}, }, + + charsEscs: genCharEscapes(), } ) +func genCharEscapes () []byte { + r := make([]byte,255) + for i:=int('a'); i<=int('c'); i++ { + r[i]=1 + } + for i:=int('A'); i<=int('Z'); i++ { + r[i]=1 + } + r[int('@')]=1 + return r +} + + +func BeginEscape (code Code) string { + return code.Escape() } + +func EndEscape () string { + return g.endEscStr } + + +func FilterEscapes (data []byte) []byte { + var buf bytes.Buffer + + for i := 0; i < len(data); { + if data[i] != 0x1b { + buf.WriteByte(data[i]) + i++ + continue + } + // Si encuentra una secuencia de escape, salta hasta encontrar un carácter alfabético. + next := i + 1 + for next < len(data) && g.charsEscs[data[next]] == 0 { + next++ + } + i = next + } + + return buf.Bytes() +} + + + + diff --git a/core/ansi/code.go b/core/ansi/code.go index 2c003e2..c887a6e 100644 --- a/core/ansi/code.go +++ b/core/ansi/code.go @@ -81,7 +81,7 @@ func (c Code) Atts () string { dc := TextBoldOn for i:=0; i<6; i++ { if m & dc != 0 { - r = append(r,string(G.itx[i].name)) + r = append(r,string(g.itx[i].name)) } dc <<= 1 } @@ -109,7 +109,7 @@ func (c Code) SetFgColor(color Code) Code { return (c & fgMask) | color& bgMask } func (c Code) FgColorName () string { - return string(G.ics[(c & clMask) & bgMask].name) } + return string(g.ics[(c & clMask) & bgMask].name) } func (c Code) BgColor() Code { @@ -119,13 +119,10 @@ func (c Code) SetBgColor(color Code) Code { return (c & bgMask) | (color<< bgShift) & fgMask } func (c Code) BgColorName () string { - return string(G.ics[((c & clMask) & fgMask) >> bgShift].name) } + return string(g.ics[((c & clMask) & fgMask) >> bgShift].name) } -func (c Code) Colors () (Code,Code) { - return (c & clMask) & bgMask, ((c & clMask) & fgMask) >> bgShift } - func (c Code) SetColors(fg, bg Code) Code { return c.SetFgColor(fg).SetBgColor(bg) } @@ -186,7 +183,7 @@ func (c Code) scapeText () []byte { if r != nil { r = append(r,';') } - r = append(r,G.itx[i].esc...) + r = append(r, g.itx[i].esc...) } dc <<= 1 } @@ -203,13 +200,13 @@ func (c Code) scapeColor () []byte { f := m & bgMask b := (m & fgMask) >> bgShift if f != 0 { - r = append(r,G.ics[f].fgEsc...) + r = append(r, g.ics[f].fgEsc...) } if b != 0 { if f > 0 { r=append(r,';') } - r = append(r,G.ics[b].bgEsc...) + r = append(r, g.ics[b].bgEsc...) } return r } @@ -233,8 +230,8 @@ func (c Code) escape () []byte { func (c Code) Escape() string { if c == 0 { - return string(G.clearEscape) + return "" } r := c.escape() - return string(append(G.beginEscape, append(r, G.endEscape...)...)) -} \ No newline at end of file + return string(append(g.beginEscIni, append(r, g.beginEscEnd...)...)) +} diff --git a/core/ansi/code_color.go b/core/ansi/code_color.go new file mode 100644 index 0000000..57088f9 --- /dev/null +++ b/core/ansi/code_color.go @@ -0,0 +1,55 @@ +// ------------------------------------------------------------------------ +// Project active2 +// Active Thing (activething.com) git.activething.com/go +// +// File name code_color.go +// Created by DEV +// Modified 06/04/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 ansi + + +const ( + + ColorNone AnsiColor = iota + ColorBlack + ColorRed + ColorGreen + ColorYellow + ColorBlue + ColorMagenta + ColorCyan + ColorWhite + ColorHBlack + ColorHRed + ColorHGreen + ColorHYellow + ColorHBlue + ColorHMagenta + ColorHCyan + ColorHWhite + ColorDefault +) + +type ( + + AnsiColor uint8 + +) + + diff --git a/core/ansi/non_escape_reader.go b/core/ansi/non_escape_reader.go new file mode 100644 index 0000000..388ccc9 --- /dev/null +++ b/core/ansi/non_escape_reader.go @@ -0,0 +1,99 @@ +// ------------------------------------------------------------------------ +// Project active2 +// Active Thing (activething.com) git.activething.com/go +// +// File name non_escape_reader.go +// Created by DEV +// Modified 06/04/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 ansi + +import ( + "bufio" + "io" +) + +type ( + + NonEscapeReader struct { + pos int + unescaped []byte + reader io.Reader + } +) + +func NewNonEscapeReader (reader io.Reader) *NonEscapeReader { + r := bufio.NewReader(reader) + return &NonEscapeReader{ + reader : r, + unescaped : make([]byte,0,r.Size()), + } +} + +/* +func (r *NonEscapeReader) Read (p []byte) (n int, e error) { + n := 0 + for { + // Read a byte from the underlying reader + b, err := f.Reader.ReadByte() + if err == io.EOF { + break + } + if err != nil { + return n, err + } + + // If not an escape character, write it to the output buffer + if !escapeMap[b] { + p[n] = b + n++ + continue + } + + // If escape character, skip the next byte + next, err := SkipEscape(f.Reader, escapeMap) + if err != nil { + return n, err + } + + // Update reader position to reflect skipped bytes + f.pos += next - f.pos + } + + return n, nil + +} + + +func skipEscape(r *bufio.Reader, escapeMap [255]byte) (int, error) { + for { + b, err := r.ReadByte() + if err == io.EOF { + return 0, errors.New("Incomplete escape sequence") + } + if err != nil { + return 0, err + } + + if !escapeMap[b] { + return r.Pos(), nil + } + } +} + + */ \ No newline at end of file diff --git a/core/ansi/non_escape_writer.go b/core/ansi/non_escape_writer.go index c9d7703..2771123 100644 --- a/core/ansi/non_escape_writer.go +++ b/core/ansi/non_escape_writer.go @@ -24,7 +24,6 @@ package ansi import ( - "bytes" "io" ) @@ -43,46 +42,5 @@ func NewNonEscapeWriter(w io.Writer) *NonEscapeWriter { func (w *NonEscapeWriter) Write (data []byte) (c int, e error) { - var buf bytes.Buffer - er := bytes.NewReader(data) - - for { - c, err := er.ReadByte() - if err == io.EOF { - break - } - if err != nil { - return 0, err - } - - if c != 0x1b { - buf.WriteByte(c) - continue - } - - // Si encuentra una secuencia de escape, salta hasta encontrar un carácter alfabético. - for { - c, err := er.ReadByte() - if err == io.EOF { - break - } - if err != nil { - return 0, err - } - - // Si encuentra un carácter alfabético, sale del bucle. - if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' { - break - } - } - } - - // Escribe el contenido sin secuencias de escape en el escritor de salida. - n, err := w.writer.Write(buf.Bytes()) - if err != nil { - return n, err - } - - return len(data), nil -} + return w.writer.Write(FilterEscapes(data)) } diff --git a/core/bins/chars/active.go b/core/bins/chars/active.go index 5f9357e..8ec7895 100644 --- a/core/bins/chars/active.go +++ b/core/bins/chars/active.go @@ -30,7 +30,7 @@ package chars const ( - CharAttNone CharAtt = 0 + CharAttNone Att = 0 maxTableSize = 1<<8 - 1 diff --git a/core/bins/chars/ascii_char_atts.go b/core/bins/chars/ascii_char_atts.go index 8eefa14..038655d 100644 --- a/core/bins/chars/ascii_char_atts.go +++ b/core/bins/chars/ascii_char_atts.go @@ -28,7 +28,7 @@ package chars const ( - ASCIIAttControl CharAtt = 1 << iota + ASCIIAttControl Att = 1 << iota ASCIIAttPrintable ASCIIAttAlpha @@ -90,7 +90,7 @@ func (t ASCIIAtts) SimpleLetterEqualFold(source, target []byte) bool { return false } for i, b := range source { - if IsAlphaUpper(CharAtt(b)) != IsAlphaUpper(CharAtt(target[i])) { + if IsAlphaUpper(Att(b)) != IsAlphaUpper(Att(target[i])) { return false } } @@ -288,39 +288,39 @@ func (t ASCIIAtts) GetHex2DigitToByte(cha, chb byte) (byte, bool) { -func IsControl(a CharAtt) bool { +func IsControl(a Att) bool { return a%ASCIIAttControl != 0 } -func IsPrintable(a CharAtt) bool { +func IsPrintable(a Att) bool { return a%ASCIIAttPrintable != 0 } -func IsAlpha(a CharAtt) bool { +func IsAlpha(a Att) bool { return a%ASCIIAttAlpha != 0 } -func IsAlphaLower(a CharAtt) bool { +func IsAlphaLower(a Att) bool { return a%ASCIIAttAlphaLower != 0 } -func IsAlphaUpper(a CharAtt) bool { +func IsAlphaUpper(a Att) bool { return a%ASCIIAttAlphaUpper != 0 } -func IsDigit(a CharAtt) bool { +func IsDigit(a Att) bool { return a%ASCIIAttDigit != 0 } -func IsHex(a CharAtt) bool { +func IsHex(a Att) bool { return a%ASCIIAttHex != 0 } -func IsAlphaNum(a CharAtt) bool { +func IsAlphaNum(a Att) bool { return a&(ASCIIAttAlpha|ASCIIAttDigit) != 0 } -func IsHexDigit(a CharAtt) bool { +func IsHexDigit(a Att) bool { return a%ASCIIAttDigitHex != 0 } diff --git a/core/bins/chars/char_att.go b/core/bins/chars/att.go similarity index 92% rename from core/bins/chars/char_att.go rename to core/bins/chars/att.go index c4edf88..361a8ce 100644 --- a/core/bins/chars/char_att.go +++ b/core/bins/chars/att.go @@ -29,15 +29,15 @@ package chars -type CharAtt uint8 +type Att uint8 -func (a CharAtt) Is(att CharAtt) bool { +func (a Att) Is(att Att) bool { return a&att == att } -func (a CharAtt) Has(att CharAtt) bool { +func (a Att) Has(att Att) bool { return a&att != 0 } /* diff --git a/core/bins/chars/char_atts.go b/core/bins/chars/char_atts.go index 5ba488c..5362cbd 100644 --- a/core/bins/chars/char_atts.go +++ b/core/bins/chars/char_atts.go @@ -27,11 +27,11 @@ package chars -type CharAtts [maxTableSize]CharAtt +type CharAtts [maxTableSize]Att -func (t *CharAtts) SetRange(att CharAtt, begin, end int) { +func (t *CharAtts) SetRange(att Att, begin, end int) { if end >= maxTableSize { end = maxTableSize - 1 } @@ -41,7 +41,7 @@ func (t *CharAtts) SetRange(att CharAtt, begin, end int) { } -func (t *CharAtts) AddRange(att CharAtt, begin, end int) { +func (t *CharAtts) AddRange(att Att, begin, end int) { if end >= maxTableSize { end = maxTableSize - 1 } @@ -51,7 +51,7 @@ func (t *CharAtts) AddRange(att CharAtt, begin, end int) { } -func (t *CharAtts) DelRange(att CharAtt, begin, end int) { +func (t *CharAtts) DelRange(att Att, begin, end int) { if end >= maxTableSize { end = maxTableSize - 1 } @@ -61,28 +61,28 @@ func (t *CharAtts) DelRange(att CharAtt, begin, end int) { } -func (t *CharAtts) SetSlice(list []byte, att CharAtt, opr int) { +func (t *CharAtts) SetSlice(list []byte, att Att, opr int) { for _, bt := range list { t[bt] = att } } -func (t *CharAtts) AddSlice(list []byte, att CharAtt) { +func (t *CharAtts) AddSlice(list []byte, att Att) { for _, bt := range list { t[bt] |= att } } -func (t *CharAtts) DelSlice(list []byte, att CharAtt, opr int) { +func (t *CharAtts) DelSlice(list []byte, att Att, opr int) { for _, bt := range list { t[bt] &^= att } } -func (t CharAtts) Has(source []byte, att CharAtt) bool { +func (t CharAtts) Has(source []byte, att Att) bool { for _, ch := range source { if t[ch]&att == att { return true @@ -92,7 +92,7 @@ func (t CharAtts) Has(source []byte, att CharAtt) bool { } -func (t CharAtts) HasAny(source []byte, att CharAtt) bool { +func (t CharAtts) HasAny(source []byte, att Att) bool { for _, ch := range source { if t[ch]&att != 0 { return true @@ -102,7 +102,7 @@ func (t CharAtts) HasAny(source []byte, att CharAtt) bool { } -func (t CharAtts) IsOf(source []byte, att CharAtt) bool { +func (t CharAtts) IsOf(source []byte, att Att) bool { if len(source) == 0 { return false } @@ -115,7 +115,7 @@ func (t CharAtts) IsOf(source []byte, att CharAtt) bool { } -func (t CharAtts) IsOfAny(source []byte, att CharAtt) bool { +func (t CharAtts) IsOfAny(source []byte, att Att) bool { if len(source) == 0 { return false }