parent
e7a4c9e898
commit
aef026a192
@ -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,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,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
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -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…
Reference in new issue