fin de ANSI3 como mejor opcion de implementacion de los escapes de estilo ANSI

master
dev 1 year ago
parent e7a4c9e898
commit aef026a192

@ -51,64 +51,13 @@ package main
import (
"base/ansi"
"base/ansi2"
"fmt"
)
func ansiStylesMain() {
fmt.Println(ansi.Red.Apply("1 Este es un mensaje en rojo"))
fmt.Println(ansi.Green.Apply("2 Este es un mensaje en verde"))
fmt.Println(ansi.Bold.Apply("3 Texto en negrita"))
fmt.Println(ansi.Underline.Apply("4 Texto subrayado"))
fmt.Println(ansi.ErrorStyle.Apply("5 Error importante"))
fmt.Println(ansi.WarningStyle.Apply("6 Advertencia"))
fmt.Println(ansi.InfoStyle.Apply("7 Información"))
fmt.Println(ansi.SuccessStyle.Apply("8 Operación exitosa"))
fmt.Println(ansi2.BasicRed.Apply("1 Este es un mensaje en rojo"))
fmt.Println(ansi2.BasicGreen.Apply("2 Este es un mensaje en verde"))
fmt.Println(ansi2.BasicBold.Apply("3 Texto en negrita"))
fmt.Println(ansi2.BasicUnderline.Apply("4 Texto subrayado"))
fmt.Println(ansi2.BasicErrorStyle.Apply("5 Error importante"))
fmt.Println(ansi2.BasicWarningStyle.Apply("6 Advertencia"))
fmt.Println(ansi2.BasicInfoStyle.Apply("7 Información"))
fmt.Println(ansi2.BasicSuccessStyle.Apply("8 Operación exitosa"))
fmt.Printf("Diferencias\n%#v\n%#v\n",ansi.Red.Apply("A"),ansi2.BasicRed.Apply("A"))
// Ejemplo combinado manual
//style := ansi.MakeStyle(ansi.ColorMagenta, ansi.ColorNone, ansi.TextStyleBold|ansi.TextStyleUnderline)
//fmt.Println(style.Apply("Magenta, negrita y subrayado"))
/*
ansi.ShowAllAnsiCombinations("Todas las combinaciones de ANSI Color & Styles")
*/
s := ansi2.MakeRGBStyle(
ansi2.MakeRGBColor(255, 105, 180), // Color de primer plano (magenta vibrante)
ansi2.MakeRGBColor(0, 50, 100), // Color de fondo (azul oscuro)
ansi.StyleBold|ansi.StyleItalic, // Atributos de texto
).Apply("RGB ---- Magenta, negrita y subrayado en RGB")
fmt.Printf("%#v\n", s)
fmt.Println(s)
i := ansi2.MakeIndexStyle(208,237,ansi2.TextStyleBold|ansi2.TextStyleUnderline)
fmt.Printf("Resultado{%#v\n}",i.Apply("A"))
fmt.Println(i.Apply("INDEX --- Un tono naranja (índice 208) sobre un fondo gris oscuro (índice 237) con estilos negrita y subrayado"))
fmt.Println(i.DelTextStyle(ansi2.TextStyleUnderline).Apply("INDEX --- Un tono naranja (índice 208) sobre un fondo gris oscuro (índice 237) con estilos negrita y subrayado"))
fmt.Println(i.AddTextStyle(ansi2.TextStyleUnderline).Apply("INDEX --- Un tono naranja (índice 208) sobre un fondo gris oscuro (índice 237) con estilos negrita y subrayado"))
}
func ansiStylesMain() {
s4 := ansi.NewBasicStyleBuilder(ansi.BColorRed,0, ansi.TextStyleItalic|ansi.TextStyleBold).Build()
s4.Apply("A")
fmt.Printf("Esto es %s\n",s4.Apply("TXTXTXTXTXT"))
}

@ -2,9 +2,9 @@
Proyecto WIAWAIW
—————————————————————————————————————————————————————————————————————————————
Fichero a.go
Package ansi
Package ansi3
Autor Juan V. Navarro juanvnl@activething.com
Creado 15/08/2025
Creado 17/08/2025
—————————————————————————————————————————————————————————————————————————————
LICENSES AND TERMS OF USE
@ -50,204 +50,99 @@
package ansi
const (
foregroundMask = 0x001F
backgroundMask = 0x03E0
textStyleMask = 0xFC00
backgroundShift = 5
textStyleShift = 10
StyleNone = 0
)
// Color index constants (5 bits each = 0-31)
const (
ColorNone = iota
ColorBlack
ColorRed
ColorGreen
ColorYellow
ColorBlue
ColorMagenta
ColorCyan
ColorWhite
ColorBrightBlack
ColorBrightRed
ColorBrightGreen
ColorBrightYellow
ColorBrightBlue
ColorBrightMagenta
ColorBrightCyan
ColorGray
ColorDarkRed
ColorDarkGreen
ColorDarkYellow
ColorDarkBlue
ColorDarkMagenta
ColorDarkCyan
ColorLightGray
// 24-31 reserved for more colors
maxColor = 31
)
// Style bit constants (6 bits = 64 combinations max)
const (
StyleBold = 1 << 0 // bit 0
StyleDim = 1 << 1 // bit 1
StyleItalic = 1 << 2 // bit 2
StyleUnderline = 1 << 3 // bit 3
StyleBlink = 1 << 4 // bit 4
StyleReverse = 1 << 5 // bit 5
maxBitsStyleText = 6
maxStyleText = (1 << maxBitsStyleText)-1
// Bits 6-7 available for more styles if needed
)
const (
//
styleStringBegin = "ansi_style("
styleStringEnd = ")"
styleStringSep = ';'
styleStringTxSep = '|'
styleStringFg = "fg:"
styleStringBg = "bg:"
styleStringTx = ""
styleStringNone = styleStringBegin + "" + styleStringEnd
//
ansiCodeBegin = "\033[" // "\x1b["
ansiCodeEnd = "\033[0m" // "\x1b[0m"
ansiCodeEndStyle = byte('m')
ansiCodeSep = byte(';')
)
defaultAnsiBufferSize = 64
var (
)
// Foreground color lookup table (32 entries for 5-bit support)
foregroundStyles = [32]styleInfo{
{"", "none"}, // ColorNone
{"30", "black"}, // ColorBlack
{"31", "red"}, // ColorRed
{"32", "green"}, // ColorGreen
{"33", "yellow"}, // ColorYellow
{"34", "blue"}, // ColorBlue
{"35", "magenta"}, // ColorMagenta
{"36", "cyan"}, // ColorCyan
{"37", "white"}, // ColorWhite
{"90", "bright-black"}, // ColorBrightBlack
{"91", "bright-red"}, // ColorBrightRed
{"92", "bright-green"}, // ColorBrightGreen
{"93", "bright-yellow"}, // ColorBrightYellow
{"94", "bright-blue"}, // ColorBrightBlue
{"95", "bright-magenta"}, // ColorBrightMagenta
{"96", "bright-cyan"}, // ColorBrightCyan
// Extended colors (16-31)
{"37", "gray"}, // ColorGray
{"2;31", "dark-red"}, // ColorDarkRed (dim red)
{"2;32", "dark-green"}, // ColorDarkGreen (dim green)
{"2;33", "dark-yellow"}, // ColorDarkYellow (dim yellow)
{"2;34", "dark-blue"}, // ColorDarkBlue (dim blue)
{"2;35", "dark-magenta"}, // ColorDarkMagenta (dim magenta)
{"2;36", "dark-cyan"}, // ColorDarkCyan (dim cyan)
{"97", "light-gray"}, // ColorLightGray
// Reserved slots 24-31 for future expansion
{"", "reserved24"},
{"", "reserved25"},
{"", "reserved26"},
{"", "reserved27"},
{"", "reserved28"},
{"", "reserved29"},
{"", "reserved30"},
{"", "reserved31"},
}
// backgroundColors color lookup table (32 entries for 5-bit support)
backgroundStyles = [32]styleInfo{
{"", "none"}, // ColorNone
{"40", "black"}, // ColorBlack
{"41", "red"}, // ColorRed
{"42", "green"}, // ColorGreen
{"43", "yellow"}, // ColorYellow
{"44", "blue"}, // ColorBlue
{"45", "magenta"}, // ColorMagenta
{"46", "cyan"}, // ColorCyan
{"47", "white"}, // ColorWhite
{"100", "bright-black"}, // ColorBrightBlack
{"101", "bright-red"}, // ColorBrightRed
{"102", "bright-green"}, // ColorBrightGreen
{"103", "bright-yellow"}, // ColorBrightYellow
{"104", "bright-blue"}, // ColorBrightBlue
{"105", "bright-magenta"}, // ColorBrightMagenta
{"106", "bright-cyan"}, // ColorBrightCyan
// Extended colors (16-31)
{"47", "gray"}, // ColorGray
{"2;41", "dark-red"}, // ColorDarkRed (dim red bg)
{"2;42", "dark-green"}, // ColorDarkGreen (dim green bg)
{"2;43", "dark-yellow"}, // ColorDarkYellow (dim yellow bg)
{"2;44", "dark-blue"}, // ColorDarkBlue (dim blue bg)
{"2;45", "dark-magenta"}, // ColorDarkMagenta (dim magenta bg)
{"2;46", "dark-cyan"}, // ColorDarkCyan (dim cyan bg)
{"107", "light-gray"}, // ColorLightGray
// Reserved slots 24-31 for future expansion
{"", "reserved24"},
{"", "reserved25"},
{"", "reserved26"},
{"", "reserved27"},
{"", "reserved28"},
{"", "reserved29"},
{"", "reserved30"},
{"", "reserved31"},
}
var (
// Individual text style lookup table (6 styles for 6-bit support)
textStyles = [maxBitsStyleText]styleInfo{
{"1", "bold"}, // StyleBold (bit 0)
{"2", "dim"}, // StyleDim (bit 1)
{"3", "italic"}, // StyleItalic (bit 2)
{"4", "underline"}, // StyleUnderline (bit 3)
{"5", "blink"}, // StyleBlink (bit 4)
{"7", "reverse"}, // StyleReverse (bit 5)
basicColorCodes = [lastBColor]basicColorInfo{
{ fg:[]byte("" ) , bg:[]byte("" ), nm: []byte("none") },
{ fg:[]byte("30"), bg: []byte("40" ), nm: []byte("black") },
{ fg:[]byte("31"), bg: []byte("41" ), nm: []byte("red") },
{ fg:[]byte("32"), bg: []byte("42" ), nm: []byte("green") },
{ fg:[]byte("33"), bg: []byte("43" ), nm: []byte("yellow") },
{ fg:[]byte("34"), bg: []byte("44" ), nm: []byte("blue") },
{ fg:[]byte("35"), bg: []byte("45" ), nm: []byte("magenta") },
{ fg:[]byte("36"), bg: []byte("46" ), nm: []byte("cyan") },
{ fg:[]byte("37"), bg: []byte("47" ), nm: []byte("white") },
{ fg:[]byte("90"), bg: []byte("100"), nm: []byte("bright-black") },
{ fg:[]byte("91"), bg: []byte("101"), nm: []byte("bright-red") },
{ fg:[]byte("92"), bg: []byte("102"), nm: []byte("bright-green") },
{ fg:[]byte("93"), bg: []byte("103"), nm: []byte("bright-yellow") },
{ fg:[]byte("94"), bg: []byte("104"), nm: []byte("bright-blue") },
{ fg:[]byte("95"), bg: []byte("105"), nm: []byte("bright-magenta") },
{ fg:[]byte("96"), bg: []byte("106"), nm: []byte("bright-cyan") },
{ fg:[]byte("97"), bg: []byte("107"), nm: []byte("bright-white") }}
textStylesInfos = [maxBitsTextStyle+1]textStyleInfo{
{ []byte(""), []byte("") }, // TextStyleBold (bit 0)
{ []byte("1"), []byte("bold") }, // TextStyleBold (bit 0)
{ []byte("2"), []byte("dim") }, // TextStyleDim (bit 1)
{ []byte("3"), []byte("italic") }, // TextStyleItalic (bit 2)
{ []byte("4"), []byte("underline") }, // TextStyleUnderline (bit 3)
{ []byte("5"), []byte("blink") }, // TextStyleBlink (bit 4)
{ []byte("7"), []byte("reverse") }, // TextStyleReverse (bit 5)
}
// Estilso ANSI básicos predefinidos
BasicStyles = struct {
Red,
Green,
Yellow,
Blue,
Magenta,
Cyan,
White,
Bold,
Dim,
Italic,
Underline,
Blink,
Reverse,
Error,
Warning,
Info,
Success ANSIStyle
}{
Red : NewBasicStyleBuilder(BColorRed , BColorNone, TextStyleNone).Build(),
Green : NewBasicStyleBuilder(BColorGreen , BColorNone, TextStyleNone).Build(),
Yellow : NewBasicStyleBuilder(BColorYellow , BColorNone, TextStyleNone).Build(),
Blue : NewBasicStyleBuilder(BColorBlue , BColorNone, TextStyleNone).Build(),
Magenta : NewBasicStyleBuilder(BColorMagenta, BColorNone, TextStyleNone).Build(),
Cyan : NewBasicStyleBuilder(BColorCyan , BColorNone, TextStyleNone).Build(),
White : NewBasicStyleBuilder(BColorWhite , BColorNone, TextStyleNone).Build(),
// Pure styles
Bold : NewBasicStyleBuilder(BColorNone , BColorNone, TextStyleBold).Build(),
Dim : NewBasicStyleBuilder(BColorNone , BColorNone, TextStyleDim).Build(),
Italic : NewBasicStyleBuilder(BColorNone , BColorNone, TextStyleItalic).Build(),
Underline : NewBasicStyleBuilder(BColorNone , BColorNone, TextStyleUnderline).Build(),
Blink : NewBasicStyleBuilder(BColorNone , BColorNone, TextStyleBlink).Build(),
Reverse : NewBasicStyleBuilder(BColorNone , BColorNone, TextStyleReverse).Build(),
// Common combinations
Error : NewBasicStyleBuilder(BColorRed , BColorNone, TextStyleBold).Build(),
Warning : NewBasicStyleBuilder(BColorYellow , BColorNone, TextStyleBold).Build(),
Info : NewBasicStyleBuilder(BColorBlue , BColorNone, TextStyleNone).Build(),
Success : NewBasicStyleBuilder(BColorGreen , BColorNone, TextStyleBold).Build(),
}
// Predefined common styles using MakeStyle
// Basic colors
Red = MakeStyle(ColorRed, ColorNone, StyleNone)
Green = MakeStyle(ColorGreen, ColorNone, StyleNone)
Yellow = MakeStyle(ColorYellow, ColorNone, StyleNone)
Blue = MakeStyle(ColorBlue, ColorNone, StyleNone)
Magenta = MakeStyle(ColorMagenta, ColorNone, StyleNone)
Cyan = MakeStyle(ColorCyan, ColorNone, StyleNone)
White = MakeStyle(ColorWhite, ColorNone, StyleNone)
// Pure styles
Bold = MakeStyle(ColorNone, ColorNone, StyleBold)
Dim = MakeStyle(ColorNone, ColorNone, StyleDim)
Italic = MakeStyle(ColorNone, ColorNone, StyleItalic)
Underline = MakeStyle(ColorNone, ColorNone, StyleUnderline)
Blink = MakeStyle(ColorNone, ColorNone, StyleBlink)
Reverse = MakeStyle(ColorNone, ColorNone, StyleReverse)
// Common combinations
ErrorStyle = MakeStyle(ColorRed, ColorNone, StyleBold)
WarningStyle = MakeStyle(ColorYellow, ColorNone, StyleBold)
InfoStyle = MakeStyle(ColorBlue, ColorNone, StyleNone)
SuccessStyle = MakeStyle(ColorGreen, ColorNone, StyleBold)
)

@ -2,9 +2,9 @@
Proyecto WIAWAIW
—————————————————————————————————————————————————————————————————————————————
Fichero ansi_style.go
Package ansi2
Package ansi3
Autor Juan V. Navarro juanvnl@activething.com
Creado 16/08/2025
Creado 17/08/2025
—————————————————————————————————————————————————————————————————————————————
LICENSES AND TERMS OF USE
@ -47,16 +47,19 @@
Copyright (c) 2025 Active Thing
————————————————————————————————————————————————————————————————————————————— */
package ansi2
package ansi
type (
Style string
ANSIStyle string
)
func (s Style) Apply (text string) string {
func (s ANSIStyle) Apply (text string) string {
if s == "" {
return text
}
@ -70,3 +73,16 @@ func (s Style) Apply (text string) string {
}
func (s ANSIStyle) Begin () string {
if len(s) == 0 {
return ""
}
return string(s)
}
func (s ANSIStyle) End() string {
if len(s) == 0 {
return ""
}
return ansiCodeEnd
}

@ -2,9 +2,9 @@
Proyecto WIAWAIW
—————————————————————————————————————————————————————————————————————————————
Fichero basic_color.go
Package ansi2
Package ansi3
Autor Juan V. Navarro juanvnl@activething.com
Creado 16/08/2025
Creado 17/08/2025
—————————————————————————————————————————————————————————————————————————————
LICENSES AND TERMS OF USE
@ -47,33 +47,35 @@
Copyright (c) 2025 Active Thing
————————————————————————————————————————————————————————————————————————————— */
package ansi2
package ansi
const (
// 8 colores básicos
ColorNone BasicColor = iota
ColorBlack
ColorRed
ColorGreen
ColorYellow
ColorBlue
ColorMagenta
ColorCyan
ColorWhite
BColorNone BasicColor = iota
BColorBlack
BColorRed
BColorGreen
BColorYellow
BColorBlue
BColorMagenta
BColorCyan
BColorWhite
// 8 colores brillantes
ColorBrightBlack // También conocido como Gray
ColorBrightRed
ColorBrightGreen
ColorBrightYellow
ColorBrightBlue
ColorBrightMagenta
ColorBrightCyan
ColorBrightWhite
maxBasicColor
BColorBrightBlack // También conocido como Gray
BColorBrightRed
BColorBrightGreen
BColorBrightYellow
BColorBrightBlue
BColorBrightMagenta
BColorBrightCyan
BColorBrightWhite
lastBColor
maxBColor = lastBColor -1
)
@ -83,14 +85,9 @@ type (
)
func (c BasicColor) IsValid() bool { return c > 0 && c < lastBColor }
func (c BasicColor) foregroundAnsiCode () string {
return basicColorCodes[c].fg
}
func (c BasicColor) backgroundAnsiCode () string {
return basicColorCodes[c].bg
}
func (c BasicColor) sanitize() BasicColor {
if c < lastBColor { return 0 }
return c
}

@ -1,10 +1,10 @@
/* ——————————————————————————————————————————————————————————————————————————
Proyecto WIAWAIW
—————————————————————————————————————————————————————————————————————————————
Fichero rgb_color.go
Package ansi2
Fichero basic_color_info.go
Package ansi3
Autor Juan V. Navarro juanvnl@activething.com
Creado 16/08/2025
Creado 17/08/2025
—————————————————————————————————————————————————————————————————————————————
LICENSES AND TERMS OF USE
@ -47,16 +47,16 @@
Copyright (c) 2025 Active Thing
————————————————————————————————————————————————————————————————————————————— */
package ansi2
package ansi
type (
RGBColor struct {
R,G,B uint8
basicColorInfo struct {
fg,bg,nm []byte
}
)
func MakeRGBColor(r, g, b uint8) RGBColor { return RGBColor{r, g, b} }

@ -0,0 +1,122 @@
/* ——————————————————————————————————————————————————————————————————————————
Proyecto WIAWAIW
—————————————————————————————————————————————————————————————————————————————
Fichero basic_style_builder.go
Package ansi3
Autor Juan V. Navarro juanvnl@activething.com
Creado 17/08/2025
—————————————————————————————————————————————————————————————————————————————
LICENSES AND TERMS OF USE
-------------------------
This software is licensed under the Elastic License v2.0 (the "License").
For full terms and additional information regarding permitted and prohibited
uses, please visit:
https://activething.com/wiawiaw/licenses
You may use, copy, modify, and redistribute this software internally within
your organization for any purpose, including research, development, and
testing, subject to the terms of this License.
You may NOT, however, use, provide, distribute, or make this software
available to any third party as part of a hosted service, SaaS offering, or
commercial product without first obtaining a commercial license from
Active Thing.
You may combine this software with other code, provided that such
combination does not circumvent the restrictions of this License.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. In no event shall
the authors or copyright holders be liable for any claim, damages, or other
liability arising from the use of this software.
—————————————————————————————————————————————————————————————————————————————
Web : activething.com | wiawiaw.com
git : g.activething.com | github.com/activething
Correo : dev@activething.com
—————————————————————————————————————————————————————————————————————————————
No deseo caminar sobre el agua", dijo Siddhartha.
Que los antiguos chamanes se contenten con tales habilidades.
—— Hermann Hesse, Siddhartha
—————————————————————————————————————————————————————————————————————————————
Copyright (c) 2025 Active Thing
————————————————————————————————————————————————————————————————————————————— */
package ansi
type (
BasicStyleBuilder struct {
fgColor BasicColor
bgColor BasicColor
txStyle TextStyle
}
)
func NewBasicStyleBuilder(fgcolor, bgcolor BasicColor, txStyle TextStyle) *BasicStyleBuilder {
s := &BasicStyleBuilder{
fgColor : fgcolor.sanitize(),
bgColor : bgcolor.sanitize(),
txStyle : txStyle.sanitize(),
}
return s
}
func (s *BasicStyleBuilder) FgColor () BasicColor { return s.fgColor }
func (s *BasicStyleBuilder) BgColor () BasicColor { return s.bgColor }
func (s *BasicStyleBuilder) TxStyle () TextStyle { return s.txStyle }
func (s *BasicStyleBuilder) SetFgColor (color BasicColor) *BasicStyleBuilder {
s.fgColor = color.sanitize()
return s
}
func (s *BasicStyleBuilder) SetBgColor (color BasicColor) *BasicStyleBuilder {
s.bgColor = color.sanitize()
return s
}
func (s *BasicStyleBuilder) SetTextStyle (txtStyle TextStyle) *BasicStyleBuilder {
s.txStyle = txtStyle.sanitize()
return s
}
func (s *BasicStyleBuilder) Build () ANSIStyle {
bf := make([]byte, 0,defaultAnsiBufferSize)
bf = append(bf,ansiCodeBegin...)
hc := false
if s.fgColor != 0 {
bf = append(bf,basicColorCodes[s.fgColor].fg...)
hc = true
}
if s.bgColor != 0 {
if hc {
bf = append(bf,ansiCodeSep)
} else {
hc = true
}
bf = append(bf,basicColorCodes[s.bgColor].bg...)
}
if s.txStyle != 0 {
bf = s.txStyle.appendStyles(bf, hc)
}
return ANSIStyle(bf)
}

@ -1,10 +1,10 @@
/* ——————————————————————————————————————————————————————————————————————————
Proyecto WIAWAIW
—————————————————————————————————————————————————————————————————————————————
Fichero text_style_info.go
Package ansi
Fichero index_color.go
Package ansi3
Autor Juan V. Navarro juanvnl@activething.com
Creado 15/08/2025
Creado 17/08/2025
—————————————————————————————————————————————————————————————————————————————
LICENSES AND TERMS OF USE
@ -51,11 +51,22 @@ package ansi
// styleInfo contains information about each style/color
type styleInfo struct {
code string // ANSI escape sequence
name string // human readable name
}
const (
IColorNone IndexColor = -1
maxIColor IndexColor = 255
)
func (s styleInfo) Has () bool { return s.code != "" }
type IndexColor int16
func (c IndexColor) IsValid() bool { return c >= 0 && c < maxIColor }
func (c IndexColor) sanitize() IndexColor {
if c < 0 || c > maxIColor {
return IColorNone
}
return c
}

@ -1,10 +1,10 @@
/* ——————————————————————————————————————————————————————————————————————————
Proyecto WIAWAIW
—————————————————————————————————————————————————————————————————————————————
Fichero a.go
Package ansi2
Fichero index_style_builder.go
Package ansi3
Autor Juan V. Navarro juanvnl@activething.com
Creado 16/08/2025
Creado 17/08/2025
—————————————————————————————————————————————————————————————————————————————
LICENSES AND TERMS OF USE
@ -47,55 +47,82 @@
Copyright (c) 2025 Active Thing
————————————————————————————————————————————————————————————————————————————— */
package ansi2
package ansi
import "strconv"
const (
//
ansiCodeBegin = "\033[" // "\x1b["
ansiCodeEnd = "\033[0m" // "\x1b[0m"
ansiCodeEndStyle = byte('m')
ansiCodeSep = byte(';')
indexAnsiForeg = "38;5;"
indexAnsiBackg = "48;5;"
)
type (
IndexStyleBuilder struct {
fgColor IndexColor
bgColor IndexColor
txStyle TextStyle
}
defaultAnsiBufferSize = 64
)
func NewIndexStyleBuilder(fgcolor, bgcolor IndexColor, txtStyle TextStyle) *IndexStyleBuilder {
return &IndexStyleBuilder{
fgColor: fgcolor.sanitize(),
bgColor: bgcolor.sanitize(),
txStyle: txtStyle.sanitize(),
}
}
func (s *IndexStyleBuilder) SetFgColor (color IndexColor) *IndexStyleBuilder {
s.fgColor = color.sanitize()
return s
}
var (
func (s *IndexStyleBuilder) SetBgColor (color IndexColor) *IndexStyleBuilder {
s.bgColor = color.sanitize()
return s
}
textStylesInfos = makeTextStylesInfo()
basicColorCodes = makeBasicColorsInfo()
func (s *IndexStyleBuilder) SetTextStyle (txtStyle TextStyle) *IndexStyleBuilder {
s.txStyle = txtStyle.sanitize()
return s
}
func (s *IndexStyleBuilder) FgColor () IndexColor { return s.fgColor }
// Basic colors
BasicRed = MakeBasicStyle(ColorRed , ColorNone, TextStyleNone)
BasicGreen = MakeBasicStyle(ColorGreen , ColorNone, TextStyleNone)
BasicYellow = MakeBasicStyle(ColorYellow , ColorNone, TextStyleNone)
BasicBlue = MakeBasicStyle(ColorBlue , ColorNone, TextStyleNone)
BasicMagenta = MakeBasicStyle(ColorMagenta , ColorNone, TextStyleNone)
BasicCyan = MakeBasicStyle(ColorCyan , ColorNone, TextStyleNone)
BasicWhite = MakeBasicStyle(ColorWhite , ColorNone, TextStyleNone)
func (s *IndexStyleBuilder) BgColor () IndexColor { return s.bgColor }
// Pure styles
BasicBold = MakeBasicStyle(ColorNone, ColorNone, TextStyleBold)
BasicDim = MakeBasicStyle(ColorNone, ColorNone, TextStyleDim)
BasicItalic = MakeBasicStyle(ColorNone, ColorNone, TextStyleItalic)
BasicUnderline = MakeBasicStyle(ColorNone, ColorNone, TextStyleUnderline)
BasicBlink = MakeBasicStyle(ColorNone, ColorNone, TextStyleBlink)
BasicReverse = MakeBasicStyle(ColorNone, ColorNone, TextStyleReverse)
func (s *IndexStyleBuilder) TxStyle () TextStyle { return s.txStyle }
// Common combinations
BasicErrorStyle = MakeBasicStyle(ColorRed , ColorNone, TextStyleBold)
BasicWarningStyle = MakeBasicStyle(ColorYellow , ColorNone, TextStyleBold)
BasicInfoStyle = MakeBasicStyle(ColorBlue , ColorNone, TextStyleNone)
BasicSuccessStyle = MakeBasicStyle(ColorGreen , ColorNone, TextStyleBold)
)
func (s *IndexStyleBuilder) Build () ANSIStyle {
bf := make([]byte, 0,defaultAnsiBufferSize)
bf = append(bf,ansiCodeBegin...)
hc := false
if s.fgColor != IColorNone {
bf = append(bf,indexAnsiForeg...)
bf = strconv.AppendInt(bf, int64(s.fgColor), 10)
hc = true
}
if s.bgColor != IColorNone {
if hc {
bf = append(bf,ansiCodeSep)
} else {
hc = true
}
bf = append(bf,indexAnsiBackg...)
bf = strconv.AppendInt(bf, int64(s.bgColor), 10)
}
if s.txStyle != 0 {
bf = s.txStyle.appendStyles(bf, hc)
}
return ANSIStyle(bf)
}

@ -1,10 +1,10 @@
/* ——————————————————————————————————————————————————————————————————————————
Proyecto WIAWAIW
—————————————————————————————————————————————————————————————————————————————
Fichero color_type.go
Package ansi2
Autor Juan V. Navarro juanvnl@activething.com
Creado 15/08/2025
Fichero rgb_color.go
Package ansi3
Autor Juan V. Navarro juanvnl@activething.com
Creado 17/08/2025
—————————————————————————————————————————————————————————————————————————————
LICENSES AND TERMS OF USE
@ -38,26 +38,32 @@
Web : activething.com | wiawiaw.com
git : g.activething.com | github.com/activething
Correo : dev@activething.com
—————————————————————————————————————————————————————————————————————————————
No deseo caminar sobre el agua", dijo Siddhartha.
Que los antiguos chamanes se contenten con tales habilidades.
—— Hermann Hesse, Siddhartha
—————————————————————————————————————————————————————————————————————————————
Copyright (c) 2025 Active Thing
Copyright (c) 2025 Active Thing
————————————————————————————————————————————————————————————————————————————— */
package ansi2
package ansi
const (
ANSIColorNone ANSIColorType = iota
ANSIColor4Bit
ANSIColor8Bit
ANSIColor24Bit
)
type (
ANSIColorType uint8
RGBColor struct {
R,G,B uint8
}
)
func MakeRGBColor(r, g, b uint8) RGBColor { return RGBColor{r, g, b} }
func (c RGBColor) Has() bool { return c.R|c.G|c.B != 0 }

@ -1,10 +1,10 @@
/* ——————————————————————————————————————————————————————————————————————————
Proyecto WIAWAIW
—————————————————————————————————————————————————————————————————————————————
Fichero t_ansi_styles_check.go
Package ansi
Fichero rgb_style_builder.go
Package ansi3
Autor Juan V. Navarro juanvnl@activething.com
Creado 15/08/2025
Creado 17/08/2025
—————————————————————————————————————————————————————————————————————————————
LICENSES AND TERMS OF USE
@ -50,56 +50,94 @@
package ansi
import (
"fmt"
"strings"
"strconv"
)
// ShowAllAnsiCombinations muestra en consola todas las combinaciones posibles de
// foreground, background y estilos de texto usando un texto de ejemplo.
func ShowAllAnsiCombinations(text string) {
// Encabezado
fmt.Println("Todas las combinaciones posibles de estilos ANSI:")
fmt.Println(strings.Repeat("-", 50))
// Iterar sobre todos los colores de foreground
for fgIndex, fgInfo := range foregroundStyles {
if len(fgInfo.code) != 0 {
continue // Saltar colores reservados/no definidos
}
const(
rgbAnsiForeg = "38;2;"
rgbAnsiBackg = "48;2;"
)
const(
defaultRGBBufferSize = 16
)
type (
RGBStyleBuilder struct {
fgColor RGBColor
bgColor RGBColor
txStyle TextStyle
}
)
func NewRGBStyleBuilder(fgcolor, bgcolor RGBColor, txtStyle TextStyle) *RGBStyleBuilder {
return &RGBStyleBuilder{
fgColor: fgcolor,
bgColor: bgcolor,
txStyle: txtStyle.sanitize(),
}
}
func (s *RGBStyleBuilder) SetFgColor (color RGBColor) *RGBStyleBuilder {
s.fgColor = color
return s
}
// Iterar sobre todos los colores de background
for bgIndex, bgInfo := range backgroundStyles {
if len(bgInfo.code) != 0 {
continue // Saltar colores reservados/no definidos
}
// Iterar sobre todas las combinaciones de estilos de texto
// Usamos un bucle hasta 2^maxBitsStyleText para probar todas las combinaciones
for styleBits := uint8(0); styleBits <= maxStyleText; styleBits++ {
// Validar que el estilo sea válido (no mayor a maxStyleText)
if styleBits > maxStyleText {
continue
}
// Crear el estilo combinado
style := MakeStyle(uint8(fgIndex), uint8(bgIndex), styleBits)
// Obtener los nombres de los estilos de texto activos
var styleNames []string
for i, ts := range textStyles {
if styleBits&(1<<i) != 0 {
styleNames = append(styleNames, ts.name)
}
}
if len(styleNames) == 0 {
styleNames = append(styleNames, "none")
}
// Mostrar la combinación
fmt.Printf("%-84s | %s\n",style.String(),style.Apply(text))
}
func (s *RGBStyleBuilder) SetBgColor (color RGBColor) *RGBStyleBuilder {
s.bgColor = color
return s
}
func (s *RGBStyleBuilder) SetTextStyle (txtStyle TextStyle) *RGBStyleBuilder {
s.txStyle = txtStyle.sanitize()
return s
}
func (s *RGBStyleBuilder) FgColor () RGBColor { return s.fgColor }
func (s *RGBStyleBuilder) BgColor () RGBColor { return s.bgColor }
func (s *RGBStyleBuilder) TxStyle () TextStyle{ return s.txStyle }
func (s *RGBStyleBuilder) Build () ANSIStyle {
bf := make([]byte, 0,defaultAnsiBufferSize)
bf = append(bf,ansiCodeBegin...)
hc := false
if s.fgColor.Has() {
bf = append(bf,rgbAnsiForeg...)
bf = strconv.AppendUint(bf,uint64(s.fgColor.R), 10); bf = append(bf,ansiCodeSep)
bf = strconv.AppendUint(bf,uint64(s.fgColor.G), 10); bf = append(bf,ansiCodeSep)
bf = strconv.AppendUint(bf,uint64(s.fgColor.B), 10)
hc = true
}
if s.bgColor.Has() {
if hc {
bf = append(bf,ansiCodeSep)
} else {
hc = true
}
bf = append(bf,rgbAnsiBackg...)
bf = strconv.AppendUint(bf,uint64(s.bgColor.R), 10); bf = append(bf,ansiCodeSep)
bf = strconv.AppendUint(bf,uint64(s.bgColor.G), 10); bf = append(bf,ansiCodeSep)
bf = strconv.AppendUint(bf,uint64(s.bgColor.B), 10)
}
fmt.Println(strings.Repeat("-", 50))
}
if s.txStyle != 0 {
bf = s.txStyle.appendStyles(bf, hc)
}
return ANSIStyle(bf)
}

@ -1,247 +0,0 @@
/* ——————————————————————————————————————————————————————————————————————————
Proyecto WIAWAIW
—————————————————————————————————————————————————————————————————————————————
Fichero style.go
Package ansi
Autor Juan V. Navarro juanvnl@activething.com
Creado 15/08/2025
—————————————————————————————————————————————————————————————————————————————
LICENSES AND TERMS OF USE
-------------------------
This software is licensed under the Elastic License v2.0 (the "License").
For full terms and additional information regarding permitted and prohibited
uses, please visit:
https://activething.com/wiawiaw/licenses
You may use, copy, modify, and redistribute this software internally within
your organization for any purpose, including research, development, and
testing, subject to the terms of this License.
You may NOT, however, use, provide, distribute, or make this software
available to any third party as part of a hosted service, SaaS offering, or
commercial product without first obtaining a commercial license from
Active Thing.
You may combine this software with other code, provided that such
combination does not circumvent the restrictions of this License.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. In no event shall
the authors or copyright holders be liable for any claim, damages, or other
liability arising from the use of this software.
—————————————————————————————————————————————————————————————————————————————
Web : activething.com | wiawiaw.com
git : g.activething.com | github.com/activething
Correo : dev@activething.com
—————————————————————————————————————————————————————————————————————————————
No deseo caminar sobre el agua", dijo Siddhartha.
Que los antiguos chamanes se contenten con tales habilidades.
—— Hermann Hesse, Siddhartha
—————————————————————————————————————————————————————————————————————————————
Copyright (c) 2025 Active Thing
————————————————————————————————————————————————————————————————————————————— */
package ansi
import (
"strings"
)
type (
// Style represents ANSI formatting as a 16-bit value:
// Bits 0-4: Foreground color (32 colors max)
// Bits 5-9: Background color (32 colors max)
// Bits 10-15: Text styles (6 bits = 64 style combinations max)
Style uint16
)
// MakeStyle constructs an Style from foreground, background, and style components
// All parameters are validated to prevent overflows
func MakeStyle(foreground, background, styles uint8) Style {
// Validate foreground (must fit in 5 bits: 0-31)
if foreground > maxColor {
foreground = ColorNone
}
// Validate background (must fit in 5 bits: 0-31)
if background > maxColor {
background = ColorNone
}
// Validate styles (must fit in 6 bits: 0-63)
if styles > maxStyleText {
styles = StyleNone
}
// Pack into 16-bit value:
// - Foreground: bits 0-4
// - backgroundColors: bits 5-9 (shift by 5)
// - Styles: bits 10-15 (shift by 10)
return Style(foreground) | Style(background)<<5 | Style(styles)<<10
}
// Foreground extracts the foreground color
func (as Style) Foreground() uint8 { return uint8(as & foregroundMask) }
// Background extracts the background color index
func (as Style) Background() uint8 { return uint8((as & backgroundMask) >> backgroundShift) }
// TextStyle extracts the raw style flags
func (as Style) TextStyle () uint8 { return uint8((as & textStyleMask) >> textStyleShift) }
// TextStyleList extracts the active individual styles as a slice
func (as Style) TextStyleList() []Style {
var styles []Style
styleBits := uint8((as & textStyleMask) >> textStyleShift)
for i := uint8(0); i < maxBitsStyleText; i++ {
bitValue := uint8(1 << i)
if styleBits&bitValue != 0 {
styles = append(styles, Style(bitValue)<<textStyleShift)
}
}
return styles
}
// HasForeground checks if a foreground color is set
func (as Style) HasForeground() bool { return as.Foreground() != ColorNone }
// HasBackground checks if a background color is set
func (as Style) HasBackground() bool { return as.Background() != ColorNone }
// HasTextStyle checks if a specific style flag is set
func (as Style) HasTextStyle (style uint8) bool { return as.TextStyle()&style != 0 }
func (as Style) Apply(text string) string {
if as == 0 {
return text
}
// Buffer en stack: 256 bytes es más que suficiente para cualquier estilo y texto corto.
buf := make([]byte,0,256)
buf = append(buf,ansiCodeBegin...)
hasCode := false
if fg := as.Foreground(); fg != ColorNone {
if info := foregroundStyles[fg]; info.Has() {
buf = append(buf,info.code...)
hasCode = true
}
}
if bg := as.Background(); bg != ColorNone {
if info := backgroundStyles[bg]; info.Has() {
if hasCode {
buf = append(buf,ansiCodeSep)
}
buf = append(buf,info.code...)
hasCode = true
}
}
// Styles
styleBits := as.TextStyle()
for i, info := range textStyles {
if styleBits&(1<<i) != 0 {
if hasCode {
buf = append(buf,ansiCodeSep)
}
buf = append(buf,info.code...)
hasCode = true
}
}
if !hasCode {
return text
}
buf = append(buf,ansiCodeEndStyle)
buf = append(buf, []byte(text)...)
buf = append(buf, ansiCodeEnd...)
// Convertimos a string sin asignación extra
return string(buf)
}
// String returns a human-readable representation using lookup tables
func (as Style) String() string {
if as == 0 {
return styleStringNone
}
var b strings.Builder
first := true
// estimacion maxima
b.Grow(72)
b.WriteString(styleStringBegin)
// Foreground color
if fg := as.Foreground(); fg != ColorNone {
b.WriteString(styleStringFg)
b.WriteString(foregroundStyles[fg].name)
first = false
}
// backgroundColors color
if bg := as.Background(); bg != ColorNone {
if !first {
b.WriteByte(styleStringSep)
}
b.WriteString(styleStringBg)
b.WriteString(backgroundStyles[bg].name)
first = false
}
// Styles
styleBits := as.TextStyle()
f := true
for i, info := range textStyles {
if styleBits&(1<<i) != 0 {
if !first && f {
b.WriteByte(styleStringSep)
}
if !f {
b.WriteByte(styleStringTxSep)
}
b.WriteString(info.name)
f = false
}
}
b.WriteString(styleStringEnd)
return b.String()
}
// ForegroundName returns the styleInfo for the foreground color
func (as Style) ForegroundName() string { return foregroundStyles[as.Foreground()].name }
// BackgroundName returns the styleInfo for the background color
func (as Style) BackgroundName() string { return backgroundStyles[as.Background()].name }
// TextStylesName returns a slice of styleInfo for all active styles
func (as Style) TextStylesName() []string {
var infos []string
styleBits := as.TextStyle()
for i, info := range textStyles {
if styleBits&(1<<i) != 0 {
infos = append(infos, info.name)
}
}
return infos
}

@ -1,8 +1,8 @@
/* ——————————————————————————————————————————————————————————————————————————
Proyecto WIAWAIW
—————————————————————————————————————————————————————————————————————————————
Fichero text_style.go
Package ansi2
Fichero style_builder.go
Package ansi3
Autor Juan V. Navarro juanvnl@activething.com
Creado 17/08/2025
—————————————————————————————————————————————————————————————————————————————
@ -47,61 +47,73 @@
Copyright (c) 2025 Active Thing
————————————————————————————————————————————————————————————————————————————— */
package ansi2
package ansi
const (
maxBitsTextStyle = 6
maxTextStyle = (1 << maxBitsTextStyle)-1
ansiTsMask = 0x3F
TextStyleNone = uint8(0)
TextStyleBold = uint8(1 << 0) // bit 0
TextStyleDim = uint8(1 << 1) // bit 1
TextStyleItalic = uint8(1 << 2) // bit 2
TextStyleUnderline = uint8(1 << 3) // bit 3
TextStyleBlink = uint8(1 << 4) // bit 4
TextStyleReverse = uint8(1 << 5) // bit 5
type (
styleBuilder struct {
fgColor []byte
bgColor []byte
tStyle []byte
}
)
func validateTextStyle(style uint8) uint8 {
return style & ansiTsMask // Asegurar que solo usamos los 6 bits válidos
}
func (s *styleBuilder) FGColorCode () string { return string(s.fgColor) }
func makeTextStylesInfo () [maxBitsTextStyle]textStyleInfo {
return [maxBitsTextStyle]textStyleInfo{
{"1", "bold"}, // TextStyleBold (bit 0)
{"2", "dim"}, // TextStyleDim (bit 1)
{"3", "italic"}, // TextStyleItalic (bit 2)
{"4", "underline"}, // TextStyleUnderline (bit 3)
{"5", "blink"}, // TextStyleBlink (bit 4)
{"7", "reverse"}, // TextStyleReverse (bit 5)
}
}
func (s *styleBuilder) BGColorCode () string { return string(s.bgColor) }
func (s *styleBuilder) TextStyle () string { return string(s.tStyle ) }
func appendStyleText (buf []byte, hasCode bool, styleText uint8) ([]byte,bool) {
// saneamos
//styleText&= ansiTsMask
if styleText == 0 {
return buf,hasCode
}
func (s *styleBuilder) SetTextStyle (txtStyle TextStyle) {
s.tStyle = s.tStyle[0:]
if txtStyle &= textStyleMask; txtStyle == 0 {
return
}
hasCode := false
for i,info := range textStylesInfos {
if styleText&(1<<i) != 0 {
if txtStyle&(1<<i) != 0 {
if hasCode {
buf = append(buf,ansiCodeSep)
s.tStyle = append(s.tStyle, ansiCodeSep)
}
buf = append(buf,info.cd...)
s.tStyle = append(s.tStyle, info.cd...)
hasCode = true
}
}
}
func (s *styleBuilder) Build() ANSIStyle {
lp := len(s.fgColor)+len(s.bgColor)+len(s.tStyle)
if lp == 0 {
return ""
}
hs := false
bf := make([]byte,0,defaultAnsiBufferSize)
bf = append(bf,ansiCodeBegin...)
if len(s.fgColor) > 0 {
bf = append(bf, s.fgColor...)
hs = true
}
if len(s.bgColor) > 0 {
if hs {
bf = append(bf, ansiCodeSep)
} else {
hs = true
}
bf = append(bf, s.bgColor...)
}
if len(s.tStyle) > 0 {
if hs {
bf = append(bf, ansiCodeSep)
}
bf = append(bf, s.tStyle...)
}
return ANSIStyle(append(bf,ansiCodeEndStyle))
}
return buf,true
}

@ -1,116 +0,0 @@
/* ——————————————————————————————————————————————————————————————————————————
Proyecto WIAWAIW
—————————————————————————————————————————————————————————————————————————————
Fichero t_ansi_styles_test.go
Package ansi
Autor Juan V. Navarro juanvnl@activething.com
Creado 15/08/2025
—————————————————————————————————————————————————————————————————————————————
LICENSES AND TERMS OF USE
-------------------------
This software is licensed under the Elastic License v2.0 (the "License").
For full terms and additional information regarding permitted and prohibited
uses, please visit:
https://activething.com/wiawiaw/licenses
You may use, copy, modify, and redistribute this software internally within
your organization for any purpose, including research, development, and
testing, subject to the terms of this License.
You may NOT, however, use, provide, distribute, or make this software
available to any third party as part of a hosted service, SaaS offering, or
commercial product without first obtaining a commercial license from
Active Thing.
You may combine this software with other code, provided that such
combination does not circumvent the restrictions of this License.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. In no event shall
the authors or copyright holders be liable for any claim, damages, or other
liability arising from the use of this software.
—————————————————————————————————————————————————————————————————————————————
Web : activething.com | wiawiaw.com
git : g.activething.com | github.com/activething
Correo : dev@activething.com
—————————————————————————————————————————————————————————————————————————————
No deseo caminar sobre el agua", dijo Siddhartha.
Que los antiguos chamanes se contenten con tales habilidades.
—— Hermann Hesse, Siddhartha
—————————————————————————————————————————————————————————————————————————————
Copyright (c) 2025 Active Thing
————————————————————————————————————————————————————————————————————————————— */
package ansi
import (
"strings"
"testing"
)
func TestMakeStyleAndAccessors(t *testing.T) {
s := MakeStyle(ColorRed, ColorBlue, StyleBold|StyleUnderline)
if s.Foreground() != ColorRed {
t.Errorf("Foreground() = %d, want %d", s.Foreground(), ColorRed)
}
if s.Background() != ColorBlue {
t.Errorf("backgroundColors() = %d, want %d", s.Background(), ColorBlue)
}
if s.TextStyle() != (StyleBold|StyleUnderline) {
t.Errorf("TextStyle() = %d, want %d", s.TextStyle(), StyleBold|StyleUnderline)
}
}
func TestApply(t *testing.T) {
s := MakeStyle(ColorRed, ColorNone, StyleBold)
result := s.Apply("test")
expectedPrefix := "\033[31;1m"
expectedSuffix := "\033[0m"
if !strings.HasPrefix(result, expectedPrefix) {
t.Errorf("Apply() prefix = %q, want %q", result, expectedPrefix)
}
if !strings.HasSuffix(result, expectedSuffix) {
t.Errorf("Apply() suffix = %q, want %q", result, expectedSuffix)
}
}
func TestNames(t *testing.T) {
s := MakeStyle(ColorRed, ColorBlue, StyleBold|StyleUnderline)
if got := s.ForegroundName(); got != "red" {
t.Errorf("ForegroundName() = %q, want %q", got, "red")
}
if got := s.BackgroundName(); got != "blue" {
t.Errorf("BackgroundName() = %q, want %q", got, "blue")
}
names := s.TextStylesName()
if len(names) != 2 || names[0] != "bold" || names[1] != "underline" {
t.Errorf("TextStylesName() = %v, want [bold underline]", names)
}
}
func TestOutOfRangeValues(t *testing.T) {
s := MakeStyle(255, 255, 255)
if s.Foreground() != ColorNone {
t.Errorf("Expected ColorNone for out-of-range foreground")
}
if s.Background() != ColorNone {
t.Errorf("Expected ColorNone for out-of-range background")
}
if s.TextStyle() != StyleNone {
t.Errorf("Expected StyleNone for out-of-range styles")
}
}
func TestNoStyle(t *testing.T) {
s := Style(0)
text := "plain"
if got := s.Apply(text); got != text {
t.Errorf("Apply() with no style = %q, want %q", got, text)
}
}

@ -1,166 +0,0 @@
/* ——————————————————————————————————————————————————————————————————————————
Proyecto WIAWAIW
—————————————————————————————————————————————————————————————————————————————
Fichero t_bench_test.go
Package ansi
Autor Juan V. Navarro juanvnl@activething.com
Creado 15/08/2025
—————————————————————————————————————————————————————————————————————————————
LICENSES AND TERMS OF USE
-------------------------
This software is licensed under the Elastic License v2.0 (the "License").
For full terms and additional information regarding permitted and prohibited
uses, please visit:
https://activething.com/wiawiaw/licenses
You may use, copy, modify, and redistribute this software internally within
your organization for any purpose, including research, development, and
testing, subject to the terms of this License.
You may NOT, however, use, provide, distribute, or make this software
available to any third party as part of a hosted service, SaaS offering, or
commercial product without first obtaining a commercial license from
Active Thing.
You may combine this software with other code, provided that such
combination does not circumvent the restrictions of this License.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. In no event shall
the authors or copyright holders be liable for any claim, damages, or other
liability arising from the use of this software.
—————————————————————————————————————————————————————————————————————————————
Web : activething.com | wiawiaw.com
git : g.activething.com | github.com/activething
Correo : dev@activething.com
—————————————————————————————————————————————————————————————————————————————
No deseo caminar sobre el agua", dijo Siddhartha.
Que los antiguos chamanes se contenten con tales habilidades.
—— Hermann Hesse, Siddhartha
—————————————————————————————————————————————————————————————————————————————
Copyright (c) 2025 Active Thing
————————————————————————————————————————————————————————————————————————————— */
package ansi
import (
"base/ansi2"
"testing"
fatih "github.com/fatih/color"
mgutz "github.com/mgutz/ansi"
)
func BenchmarkOurLibrary(b *testing.B) {
style := MakeStyle(ColorRed,ColorRed,StyleBold)
text := "Mensaje de error"
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = style.Apply(text)
}
}
func BenchmarkOurLibraryBasicANSI2(b *testing.B) {
style := ansi2.MakeBasicStyle(ansi2.ColorRed,ansi2.ColorBlue,StyleBold)
text := "Mensaje de error"
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = style.Apply(text)
}
}
func BenchmarkOurLibraryBasicANSI2_Cache(b *testing.B) {
style := ansi2.MakeBasicStyle(ansi2.ColorRed,ansi2.ColorBlue,StyleBold).StyleCode()
text := "Mensaje de error"
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = style.Apply(text)
}
}
func BenchmarkOurLibraryRGB(b *testing.B) {
style := ansi2.MakeRGBStyle(
ansi2.MakeRGBColor(255, 105, 180), // Color de primer plano (magenta vibrante)
ansi2.MakeRGBColor(0, 50, 100),
StyleBold)
text := "Mensaje de error"
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = style.Apply(text)
}
}
func BenchmarkOurLibraryRGBANSIStyle (b *testing.B) {
style := ansi2.MakeRGBStyle(
ansi2.MakeRGBColor(255, 105, 180), // Color de primer plano (magenta vibrante)
ansi2.MakeRGBColor(0, 50, 100),
StyleBold).ToANSIStyle()
text := "Mensaje de error"
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = style.Apply(text)
}
}
/*
func BenchmarkOurLibrary2(b *testing.B) {
style := ErrorStyle
text := "Mensaje de error"
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = style.Apply2(text)
}
}
func BenchmarkOurLibrary3(b *testing.B) {
style := ErrorStyle
text := "Mensaje de error"
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = style.Apply3(text)
}
}
*/
func BenchmarkFatihColor(b *testing.B) {
c := fatih.New(fatih.FgRed, fatih.BgRed, fatih.Bold)
text := "Mensaje de error"
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = c.Sprint(text)
}
}
func BenchmarkMgutzAnsi(b *testing.B) {
code := mgutz.ColorFunc("red+red+b")
text := "Mensaje de error"
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = code(text)
}
}
func BenchmarkMgutzAnsiTrueColor(b *testing.B) {
// True Color RGB: foreground RGB(255,0,0) + background RGB(0,100,200) + bold
code := mgutz.ColorFunc("255:0:0+0:100:200+b")
text := "Mensaje de error en True Color"
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = code(text)
}
}

@ -0,0 +1,120 @@
/* ——————————————————————————————————————————————————————————————————————————
Proyecto WIAWAIW
—————————————————————————————————————————————————————————————————————————————
Fichero text_style.go
Package ansi3
Autor Juan V. Navarro juanvnl@activething.com
Creado 17/08/2025
—————————————————————————————————————————————————————————————————————————————
LICENSES AND TERMS OF USE
-------------------------
This software is licensed under the Elastic License v2.0 (the "License").
For full terms and additional information regarding permitted and prohibited
uses, please visit:
https://activething.com/wiawiaw/licenses
You may use, copy, modify, and redistribute this software internally within
your organization for any purpose, including research, development, and
testing, subject to the terms of this License.
You may NOT, however, use, provide, distribute, or make this software
available to any third party as part of a hosted service, SaaS offering, or
commercial product without first obtaining a commercial license from
Active Thing.
You may combine this software with other code, provided that such
combination does not circumvent the restrictions of this License.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. In no event shall
the authors or copyright holders be liable for any claim, damages, or other
liability arising from the use of this software.
—————————————————————————————————————————————————————————————————————————————
Web : activething.com | wiawiaw.com
git : g.activething.com | github.com/activething
Correo : dev@activething.com
—————————————————————————————————————————————————————————————————————————————
No deseo caminar sobre el agua", dijo Siddhartha.
Que los antiguos chamanes se contenten con tales habilidades.
—— Hermann Hesse, Siddhartha
—————————————————————————————————————————————————————————————————————————————
Copyright (c) 2025 Active Thing
————————————————————————————————————————————————————————————————————————————— */
package ansi
const (
maxBitsTextStyle = 6
textStyleMask = (1 << maxBitsTextStyle)-1
)
const (
TextStyleNone TextStyle = 0
TextStyleBold TextStyle = 1 << iota
TextStyleDim
TextStyleItalic
TextStyleUnderline
TextStyleBlink
TextStyleReverse
)
type (
TextStyle uint8
)
func (s TextStyle) HasBold () bool { return s&TextStyleBold != 0 }
func (s TextStyle) HasItalic() bool { return s&TextStyleItalic != 0 }
func (s TextStyle) HasUnderline() bool { return s&TextStyleUnderline != 0 }
func (s TextStyle) HasBlink() bool { return s&TextStyleBlink != 0 }
func (s TextStyle) HasReverse() bool { return s&TextStyleReverse != 0 }
func (s TextStyle) HasDim () bool { return s&TextStyleDim != 0 }
func (s TextStyle) sanitize() TextStyle { return TextStyle(s & textStyleMask) }
func (s TextStyle) appendStyles (buf []byte, hc bool) []byte {
for i,info := range textStylesInfos {
if s&(1<<i) != 0 {
if hc {
buf = append(buf, ansiCodeSep)
} else {
hc = true
}
buf = append(buf, info.cd...)
}
}
return buf
}

@ -2,7 +2,7 @@
Proyecto WIAWAIW
—————————————————————————————————————————————————————————————————————————————
Fichero text_style_info.go
Package ansi2
Package ansi
Autor Juan V. Navarro juanvnl@activething.com
Creado 16/08/2025
—————————————————————————————————————————————————————————————————————————————
@ -47,10 +47,13 @@
Copyright (c) 2025 Active Thing
————————————————————————————————————————————————————————————————————————————— */
package ansi2
package ansi
type textStyleInfo struct {
cd string // ANSI escape sequence
nm string // human-readable name
cd,
nm []byte
}

@ -1,79 +0,0 @@
/* ——————————————————————————————————————————————————————————————————————————
Proyecto WIAWAIW
—————————————————————————————————————————————————————————————————————————————
Fichero basic_color_info.go
Package ansi2
Autor Juan V. Navarro juanvnl@activething.com
Creado 16/08/2025
—————————————————————————————————————————————————————————————————————————————
LICENSES AND TERMS OF USE
-------------------------
This software is licensed under the Elastic License v2.0 (the "License").
For full terms and additional information regarding permitted and prohibited
uses, please visit:
https://activething.com/wiawiaw/licenses
You may use, copy, modify, and redistribute this software internally within
your organization for any purpose, including research, development, and
testing, subject to the terms of this License.
You may NOT, however, use, provide, distribute, or make this software
available to any third party as part of a hosted service, SaaS offering, or
commercial product without first obtaining a commercial license from
Active Thing.
You may combine this software with other code, provided that such
combination does not circumvent the restrictions of this License.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. In no event shall
the authors or copyright holders be liable for any claim, damages, or other
liability arising from the use of this software.
—————————————————————————————————————————————————————————————————————————————
Web : activething.com | wiawiaw.com
git : g.activething.com | github.com/activething
Correo : dev@activething.com
—————————————————————————————————————————————————————————————————————————————
No deseo caminar sobre el agua", dijo Siddhartha.
Que los antiguos chamanes se contenten con tales habilidades.
—— Hermann Hesse, Siddhartha
—————————————————————————————————————————————————————————————————————————————
Copyright (c) 2025 Active Thing
————————————————————————————————————————————————————————————————————————————— */
package ansi2
type (
basicColorInfo struct {
fg,bg,nm string
}
)
func makeBasicColorsInfo() [maxBasicColor]basicColorInfo {
return [maxBasicColor]basicColorInfo{
{ fg:"" , bg: "" , nm: "None" },
{ fg:"30", bg: "40" , nm: "Black" },
{ fg:"31", bg: "41" , nm: "Red" },
{ fg:"32", bg: "42" , nm: "Green" },
{ fg:"33", bg: "43" , nm: "Yellow" },
{ fg:"34", bg: "44" , nm: "Blue" },
{ fg:"35", bg: "45" , nm: "Magenta" },
{ fg:"36", bg: "46" , nm: "Cyan" },
{ fg:"37", bg: "47" , nm: "White" },
{ fg:"90", bg: "100", nm: "Bright-Black" },
{ fg:"91", bg: "101", nm: "Bright-Red" },
{ fg:"92", bg: "102", nm: "Bright-Green" },
{ fg:"93", bg: "103", nm: "Bright-Yellow" },
{ fg:"94", bg: "104", nm: "Bright-Blue" },
{ fg:"95", bg: "105", nm: "Bright-Magenta" },
{ fg:"96", bg: "106", nm: "Bright-Cyan" },
{ fg:"97", bg: "107", nm: "Bright-White" }}
}

@ -1,186 +0,0 @@
/* ——————————————————————————————————————————————————————————————————————————
Proyecto WIAWAIW
—————————————————————————————————————————————————————————————————————————————
Fichero basic_style.go
Package ansi2
Autor Juan V. Navarro juanvnl@activething.com
Creado 16/08/2025
—————————————————————————————————————————————————————————————————————————————
LICENSES AND TERMS OF USE
-------------------------
This software is licensed under the Elastic License v2.0 (the "License").
For full terms and additional information regarding permitted and prohibited
uses, please visit:
https://activething.com/wiawiaw/licenses
You may use, copy, modify, and redistribute this software internally within
your organization for any purpose, including research, development, and
testing, subject to the terms of this License.
You may NOT, however, use, provide, distribute, or make this software
available to any third party as part of a hosted service, SaaS offering, or
commercial product without first obtaining a commercial license from
Active Thing.
You may combine this software with other code, provided that such
combination does not circumvent the restrictions of this License.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. In no event shall
the authors or copyright holders be liable for any claim, damages, or other
liability arising from the use of this software.
—————————————————————————————————————————————————————————————————————————————
Web : activething.com | wiawiaw.com
git : g.activething.com | github.com/activething
Correo : dev@activething.com
—————————————————————————————————————————————————————————————————————————————
No deseo caminar sobre el agua", dijo Siddhartha.
Que los antiguos chamanes se contenten con tales habilidades.
—— Hermann Hesse, Siddhartha
—————————————————————————————————————————————————————————————————————————————
Copyright (c) 2025 Active Thing
————————————————————————————————————————————————————————————————————————————— */
package ansi2
const (
basicFgOffset = 0
basicBgOffset = 5
basicTsOffset = 10
basicFgMask BasicStyle = 0x001F
basicBgMask BasicStyle = 0x03E0
basicTsMask BasicStyle = ansiTsMask << (basicTsOffset)
)
type (
// BasicStyle represents ANSI formatting as a 16-bit value:
// Bits 0-4: Foreground color (5 bits = 32 values, usando 0-16)
// Bits 5-9: Background color (5 bits = 32 values, usando 0-16)
// Bits 10-15: Text styles
BasicStyle uint16
)
func MakeBasicStyle(foreground, background BasicColor, styles uint8) BasicStyle {
return BasicStyle(0).
SetForeground(foreground).
SetBackground(background).
SetTextStyle(styles)
}
func (_ BasicStyle) ColorType () ANSIColorType { return ANSIColor4Bit }
func (s BasicStyle) HasForeground() bool { return s&basicFgMask != 0 }
// Foreground extracts the foreground color
func (s BasicStyle) Foreground() BasicColor { return BasicColor(s & basicFgMask) }
// SetForeground sets the foreground color
func (s BasicStyle) SetForeground(color BasicColor) BasicStyle {
// Clear existing foreground and set new with sanitized input
return (s &^ basicFgMask) | (BasicStyle(color) & basicFgMask)
}
func (s BasicStyle) HasBackground() bool { return s&basicBgMask != 0 }
// Background extracts the background color index
func (s BasicStyle) Background() BasicColor {
return BasicColor((s & basicBgMask) >> basicBgOffset) }
func (s BasicStyle) SetBackground(color BasicColor) BasicStyle {
return s &^ basicBgMask | (BasicStyle(color) << basicBgOffset) }
// HasTextStyle checks if any text style is set
func (s BasicStyle) HasTextStyle() bool { return s&basicTsMask != 0 }
// TextStyle extracts the text style bitmask
func (s BasicStyle) TextStyle() uint8 { return uint8((s & basicTsMask) >> basicTsOffset) }
// SetTextStyle replaces the current text style
func (s BasicStyle) SetTextStyle(textStyle uint8) BasicStyle {
return (s &^ basicTsMask) | (BasicStyle(textStyle & ansiTsMask) << basicTsOffset) }
// AddTextStyle adds text style flags (OR operation)
func (s BasicStyle) AddTextStyle(textStyle uint8) BasicStyle {
return s | (BasicStyle(textStyle & ansiTsMask) << basicTsOffset) }
// DelTextStyle removes text style flags (AND NOT operation)
func (s BasicStyle) DelTextStyle(textStyle uint8) BasicStyle {
return s &^ (BasicStyle(textStyle & ansiTsMask) << basicTsOffset) }
func (s BasicStyle) Apply(text string) string {
if s == 0 || len(text) == 0 {
return text
}
buf := make([]byte,0,64)
buf = s.toCodes(buf)
buf = append(buf, []byte(text)...)
buf = append(buf, ansiCodeEnd...)
return string(buf)
}
func (s BasicStyle) ANSICode() Style {
if s == 0 {
return ""
}
buf := make([]byte,0,64)
return Style(append(buf,s.toCodes(buf)...))
}
func (s BasicStyle) toCodes(buf []byte) []byte {
buf = append(buf, []byte(ansiCodeBegin)...)
hasCode := false
// Añadir color de primer plano
if s.HasForeground() {
buf = append(buf, s.Foreground().foregroundAnsiCode()...)
hasCode = true
}
// Añadir color de fondo
if s.HasBackground() {
if hasCode {
buf = append(buf,ansiCodeSep)
}
buf = append(buf, s.Background().backgroundAnsiCode()...)
hasCode = true
}
if s.HasTextStyle() {
buf,hasCode = appendStyleText(buf,hasCode,s.TextStyle())
}
if !hasCode {
return buf
}
return append(buf, ansiCodeEndStyle)
}

@ -1,188 +0,0 @@
/* ——————————————————————————————————————————————————————————————————————————
Proyecto WIAWAIW
—————————————————————————————————————————————————————————————————————————————
Fichero index_style.go
Package ansi2
Autor Juan V. Navarro juanvnl@activething.com
Creado 16/08/2025
—————————————————————————————————————————————————————————————————————————————
LICENSES AND TERMS OF USE
-------------------------
This software is licensed under the Elastic License v2.0 (the "License").
For full terms and additional information regarding permitted and prohibited
uses, please visit:
https://activething.com/wiawiaw/licenses
You may use, copy, modify, and redistribute this software internally within
your organization for any purpose, including research, development, and
testing, subject to the terms of this License.
You may NOT, however, use, provide, distribute, or make this software
available to any third party as part of a hosted service, SaaS offering, or
commercial product without first obtaining a commercial license from
Active Thing.
You may combine this software with other code, provided that such
combination does not circumvent the restrictions of this License.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. In no event shall
the authors or copyright holders be liable for any claim, damages, or other
liability arising from the use of this software.
—————————————————————————————————————————————————————————————————————————————
Web : activething.com | wiawiaw.com
git : g.activething.com | github.com/activething
Correo : dev@activething.com
—————————————————————————————————————————————————————————————————————————————
No deseo caminar sobre el agua", dijo Siddhartha.
Que los antiguos chamanes se contenten con tales habilidades.
—— Hermann Hesse, Siddhartha
—————————————————————————————————————————————————————————————————————————————
Copyright (c) 2025 Active Thing
————————————————————————————————————————————————————————————————————————————— */
package ansi2
import "strconv"
// Offsets de bytes para cada componente
const (
idxFgOffset = 0
idxBgOffset = 1
idxTsOffset = 2
// Máscaras para extraer los componentes del uint32
idxFgMask = 0xFF << (8 * idxFgOffset)
idxBgMask = 0xFF << (8 * idxBgOffset)
idxTsMask = 0x3F << (8 * idxTsOffset)
// Constantes de escape ANSI para colores indexados
ansiForegIndex = "38;5;"
ansiBackgIndex = "48;5;"
)
type (
IndexStyle uint32
)
// MakeIndexStyle crea un estilo de color indexado a partir de sus componentes.
func MakeIndexStyle(fg, bg, styles uint8) IndexStyle {
return IndexStyle(0).
SetForeground(fg).
SetBackground(bg).
SetTextStyle(styles)
}
func (_ IndexStyle) ColorType () ANSIColorType { return ANSIColor8Bit }
// HasForeground comprueba si el color de primer plano está definido.
func (s IndexStyle) HasForeground() bool { return s&idxFgMask != 0 }
// Foreground extrae el índice del color de primer plano.
func (s IndexStyle) Foreground() uint8 { return uint8(s >> (8 * idxFgOffset)) }
func (s IndexStyle) SetForeground(fgColor uint8) IndexStyle {
return IndexStyle((uint32(s) &^ idxFgMask) | (uint32(fgColor) << (8 * idxFgOffset))) }
// HasBackground comprueba si el color de fondo está definido.
func (s IndexStyle) HasBackground() bool { return s&idxBgMask != 0 }
// Background extrae el índice del color de fondo.
func (s IndexStyle) Background() uint8 { return uint8(s >> (8 * idxBgOffset)) }
func (s IndexStyle) SetBackground(bgColor uint8) IndexStyle {
return IndexStyle((uint32(s) &^ idxBgMask) | (uint32(bgColor) << (8 * idxBgOffset))) }
// HasTextStyle comprueba si hay algún estilo de texto aplicado.
func (s IndexStyle) HasTextStyle() bool { return s&idxTsMask != 0 }
// TextStyle extrae los bits de los estilos de texto.
func (s IndexStyle) TextStyle() uint8 { return uint8(s >> (8 * idxTsOffset)) }
func (s IndexStyle) SetTextStyle(textStyle uint8) IndexStyle {
// 1. Limpiamos los bits de estilo existentes en el uint64.
// 2. Limpiamos el valor de entrada textStyle con la máscara para sanitizarlo.
// 3. Desplazamos el valor sanitizado a su posición y lo combinamos.
return IndexStyle((uint32(s) &^ idxTsMask) | (uint32(textStyle & ansiTsMask) << (8 * idxTsOffset)))
}
func (s IndexStyle) AddTextStyle(textStyle uint8) IndexStyle {
return s | (IndexStyle(textStyle & ansiTsMask) << (8 * idxTsOffset)) }
func (s IndexStyle) DelTextStyle(textStyle uint8) IndexStyle {
return s &^ (IndexStyle(textStyle & ansiTsMask) << (8 * idxTsOffset)) }
func (s IndexStyle) ANSICode () Style {
if s == 0 {
return ""
}
buf := make([]byte,0,64)
return Style(append(buf,s.toCodes(buf)...))
}
func (s IndexStyle) Apply(text string) string {
if s == 0 || len(text) == 0 {
return text
}
buf := make([]byte,0,64)
buf = s.toCodes(buf)
buf = append(buf, []byte(text)...)
buf = append(buf, ansiCodeEnd...)
return string(buf)
}
func (s IndexStyle) toCodes(buf []byte) []byte {
buf = append(buf, []byte(ansiCodeBegin)...)
hasCode := false
// Añadir color de primer plano
if s.HasForeground() {
buf = append(buf, []byte(ansiForegIndex)...)
buf = strconv.AppendUint(buf, uint64(s.Foreground()), 10)
hasCode = true
}
// Añadir color de fondo
if s.HasBackground() {
if hasCode {
buf = append(buf,ansiCodeSep)
}
buf = append(buf, []byte(ansiBackgIndex)...)
buf = strconv.AppendUint(buf, uint64(s.Background()), 10)
hasCode = true
}
if s.HasTextStyle() {
buf,hasCode = appendStyleText(buf,hasCode,s.TextStyle())
}
if !hasCode {
return buf
}
return append(buf, ansiCodeEndStyle)
}

@ -1,225 +0,0 @@
/* ——————————————————————————————————————————————————————————————————————————
Proyecto WIAWAIW
—————————————————————————————————————————————————————————————————————————————
Fichero RGBStyle.go
Package ansi2
Autor Juan V. Navarro juanvnl@activething.com
Creado 15/08/2025
—————————————————————————————————————————————————————————————————————————————
LICENSES AND TERMS OF USE
-------------------------
This software is licensed under the Elastic License v2.0 (the "License").
For full terms and additional information regarding permitted and prohibited
uses, please visit:
https://activething.com/wiawiaw/licenses
You may use, copy, modify, and redistribute this software internally within
your organization for any purpose, including research, development, and
testing, subject to the terms of this License.
You may NOT, however, use, provide, distribute, or make this software
available to any third party as part of a hosted service, SaaS offering, or
commercial product without first obtaining a commercial license from
Active Thing.
You may combine this software with other code, provided that such
combination does not circumvent the restrictions of this License.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. In no event shall
the authors or copyright holders be liable for any claim, damages, or other
liability arising from the use of this software.
—————————————————————————————————————————————————————————————————————————————
Web : activething.com | wiawiaw.com
git : g.activething.com | github.com/activething
Correo : dev@activething.com
—————————————————————————————————————————————————————————————————————————————
No deseo caminar sobre el agua", dijo Siddhartha.
Que los antiguos chamanes se contenten con tales habilidades.
—— Hermann Hesse, Siddhartha
—————————————————————————————————————————————————————————————————————————————
Copyright (c) 2025 Active Thing
————————————————————————————————————————————————————————————————————————————— */
package ansi2
import (
"strconv"
)
// Offsets de bytes para cada componente
const (
rgbFgOffset = 0
rgbBgOffset = 3
rgbTsOffset = 6
// rgbFgMask aísla los 3 bytes del color de primer plano (R, G, B)
rgbFgMask = 0xFFFFFF << (8 * rgbFgOffset)
// rgbBgMask aísla los 3 bytes del color de fondo (R, G, B)
rgbBgMask = 0xFFFFFF << (8 * rgbBgOffset)
// tsMax
rgbTsMask = ansiTsMask << (8 * rgbTsOffset)
rgbAnsiForeg = "38;2;"
rgbAnsiBackg = "48;2;"
)
type (
RGBStyle uint64
)
func MakeRGBStyle(fgColor, bgColor RGBColor, styles uint8) RGBStyle {
return RGBStyle(0).
SetForeground(fgColor).
SetBackground(bgColor).
SetTextStyle(styles)
}
func (_ RGBStyle) ColorType () ANSIColorType { return ANSIColor24Bit }
// HasForeground checks if a foreground color is set (if any of the RGB values are not 0)
func (s RGBStyle) HasForeground() bool { return s&rgbFgMask != 0 }
func (s RGBStyle) Foreground() (rgb RGBColor) {
rgb.R,rgb.G,rgb.B = s.getColors(rgbFgOffset)
return
}
func (s RGBStyle) SetForeground(color RGBColor) RGBStyle {
return s.setColorRGB(color,rgbFgOffset,rgbFgMask) }
// HasBackground checks if a background color is set
func (s RGBStyle) HasBackground() bool { return s&rgbBgMask != 0 }
func (s RGBStyle) Background() (rgb RGBColor) {
rgb.R,rgb.G,rgb.B = s.getColors(rgbBgOffset)
return
}
func (s RGBStyle) SetBackground(color RGBColor) RGBStyle {
return s.setColorRGB(color,rgbBgOffset,rgbBgMask) }
func (s RGBStyle) setColorRGB (rgb RGBColor, offset int, mask uint64) RGBStyle {
return RGBStyle(
(uint64(s) &^ mask) |
(uint64(rgb.R) << (8 * (offset + 0))) |
(uint64(rgb.G) << (8 * (offset + 1))) |
(uint64(rgb.B) << (8 * (offset + 2))))
}
func (s RGBStyle) getColors(offset int) (r,g,b uint8) {
r = uint8(s >> (8 * (offset + 0)))
g = uint8(s >> (8 * (offset + 1)))
b = uint8(s >> (8 * (offset + 2)))
return
}
func (s RGBStyle) HasTextStyle() bool { return s&rgbTsMask != 0 }
// TextStyle extrae el bitmask de estilos de texto.
func (s RGBStyle) TextStyle() uint8 { return uint8(s >> (8 * rgbTsOffset)) }
func (s RGBStyle) SetTextStyle(textStyle uint8) RGBStyle {
// 1. Limpiamos los bits de estilo existentes en el uint64.
// 2. Limpiamos el valor de entrada textStyle con la máscara para sanitizarlo.
// 3. Desplazamos el valor sanitizado a su posición y lo combinamos.
return RGBStyle((uint64(s) &^ rgbTsMask) | (uint64(textStyle & ansiTsMask) << (8 * rgbTsOffset)))
}
func (s RGBStyle) AddTextStyle(textStyle uint8) RGBStyle {
return s | (RGBStyle(textStyle&ansiTsMask) << (8 * rgbTsOffset)) }
func (s RGBStyle) DelTextStyle(textStyle uint8) RGBStyle {
return s &^ (RGBStyle(textStyle&ansiTsMask) << (8 * rgbTsOffset)) }
func (s RGBStyle) ANSICode () Style {
if s == 0 {
return ""
}
buf := make([]byte,0,64)
return Style(append(buf,s.toCodes(buf)...))
}
func (s RGBStyle) Apply (text string) string {
if s == 0 || text == "" {
return text
}
buf := make([]byte,0,defaultAnsiBufferSize)
buf = s.toCodes(buf)
buf = append(buf, []byte(text)...)
buf = append(buf, ansiCodeEnd...)
return string(buf)
}
func (s RGBStyle) toCodes(buf []byte) []byte {
buf = append(buf,[]byte(ansiCodeBegin)...)
hasCode := false
if s.HasForeground() {
buf,hasCode = s.appendRGB(buf,true)
}
if s.HasBackground() {
if hasCode {
buf = append(buf,ansiCodeSep)
}
buf,hasCode = s.appendRGB(buf,false)
}
st := s.TextStyle()
if st != 0 {
buf,hasCode = appendStyleText(buf,hasCode,st)
}
if !hasCode {
return buf
}
return append(buf,ansiCodeEndStyle)
}
func (s RGBStyle) appendRGB(buf []byte, isForeground bool) ([]byte,bool) {
var r,g,b uint8
if isForeground {
r,g,b = s.getColors(rgbFgOffset)
buf = append(buf, []byte(rgbAnsiForeg)...)
} else {
r,g,b = s.getColors(rgbBgOffset)
buf = append(buf, []byte(rgbAnsiBackg)...)
}
buf = strconv.AppendUint(buf, uint64(r), 10)
buf = append(buf, ansiCodeSep)
buf = strconv.AppendUint(buf, uint64(g), 10)
buf = append(buf, ansiCodeSep)
buf = strconv.AppendUint(buf, uint64(b), 10)
return buf,true
}
Loading…
Cancel
Save

Powered by TurnKey Linux.