Skip to content

Commit

Permalink
feat(ansi): export XParseColor function
Browse files Browse the repository at this point in the history
  • Loading branch information
aymanbagabas committed Nov 21, 2024
1 parent dd1bfe4 commit 8be3b5a
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 8 deletions.
5 changes: 4 additions & 1 deletion ansi/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@ module github.com/charmbracelet/x/ansi

go 1.18

require github.com/rivo/uniseg v0.4.7
require (
github.com/lucasb-eyer/go-colorful v1.2.0
github.com/rivo/uniseg v0.4.7
)
2 changes: 2 additions & 0 deletions ansi/go.sum
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
7 changes: 0 additions & 7 deletions ansi/style.go
Original file line number Diff line number Diff line change
Expand Up @@ -487,10 +487,3 @@ func underlineColorString(c Color) string {
}
return defaultUnderlineColorAttr
}

func shift(v uint32) uint32 {
if v > 0xff {
return v >> 8
}
return v
}
63 changes: 63 additions & 0 deletions ansi/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ package ansi
import (
"fmt"
"image/color"
"strconv"
"strings"

"github.com/lucasb-eyer/go-colorful"
)

// colorToHexString returns a hex string representation of a color.
Expand All @@ -27,3 +31,62 @@ func colorToHexString(c color.Color) string {
func rgbToHex(r, g, b uint32) uint32 {
return r<<16 + g<<8 + b
}

type shiftable interface {
~uint | ~uint16 | ~uint32 | ~uint64
}

func shift[T shiftable](x T) T {
if x > 0xff {
x >>= 8
}
return x
}

// XParseColor is a helper function that parses a string into a color.Color. It
// provides a similar interface to the XParseColor function in Xlib. It
// supports the following formats:
//
// - #RGB
// - #RRGGBB
// - rgb:RRRR/GGGG/BBBB
// - rgba:RRRR/GGGG/BBBB/AAAA
//
// If the string is not a valid color, nil is returned.
//
// See: https://linux.die.net/man/3/xparsecolor
func XParseColor(s string) color.Color {
switch {
case strings.HasPrefix(s, "#"):
c, err := colorful.Hex(s)
if err != nil {
return nil
}

return c
case strings.HasPrefix(s, "rgb:"):
parts := strings.Split(s[4:], "/")
if len(parts) != 3 {
return nil
}

r, _ := strconv.ParseUint(parts[0], 16, 32)
g, _ := strconv.ParseUint(parts[1], 16, 32)
b, _ := strconv.ParseUint(parts[2], 16, 32)

return color.RGBA{uint8(shift(r)), uint8(shift(g)), uint8(shift(b)), 255} //nolint:gosec
case strings.HasPrefix(s, "rgba:"):
parts := strings.Split(s[5:], "/")
if len(parts) != 4 {
return nil
}

r, _ := strconv.ParseUint(parts[0], 16, 32)
g, _ := strconv.ParseUint(parts[1], 16, 32)
b, _ := strconv.ParseUint(parts[2], 16, 32)
a, _ := strconv.ParseUint(parts[3], 16, 32)

return color.RGBA{uint8(shift(r)), uint8(shift(g)), uint8(shift(b)), uint8(shift(a))} //nolint:gosec
}
return nil
}

0 comments on commit 8be3b5a

Please sign in to comment.