@@ -193,7 +193,7 @@ func DialogTitle(t *styles.Styles, title string, width int, fromColor, toColor c
remainingWidth := width - length
if remainingWidth > 0 {
lines := strings.Repeat(char, remainingWidth)
- lines = styles.ApplyForegroundGrad(t, lines, fromColor, toColor)
+ lines = styles.ApplyForegroundGrad(t.Base, lines, fromColor, toColor)
title = title + " " + lines
}
return title
@@ -3,10 +3,13 @@ package main
import (
"fmt"
"math/rand/v2"
+ "os"
"charm.land/lipgloss/v2"
"github.com/charmbracelet/crush/internal/ui/logo"
+ "github.com/charmbracelet/crush/internal/ui/styles"
"github.com/charmbracelet/x/exp/slice"
+ "github.com/charmbracelet/x/term"
)
func renderLetterforms(stretch bool) string {
@@ -42,8 +45,26 @@ func renderLetterforms(stretch bool) string {
}
func main() {
+ w, _, err := term.GetSize(os.Stdout.Fd())
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Could not get terminal size: %s", err)
+ }
+
+ s := styles.DefaultStyles()
+ opts := logo.Opts{
+ FieldColor: s.LogoFieldColor,
+ TitleColorA: s.LogoTitleColorA,
+ TitleColorB: s.LogoTitleColorB,
+ CharmColor: s.LogoCharmColor,
+ VersionColor: s.LogoVersionColor,
+ Width: w,
+ }
+
+ lipgloss.Println(logo.Render(s.Base, "v1.0.0", false, opts))
+ lipgloss.Println(logo.Render(s.Base, "v1.0.0", true, opts))
+
fmt.Println(renderLetterforms(false))
- for range 10 {
+ for range 5 {
fmt.Println(renderLetterforms(true))
}
}
@@ -23,8 +23,9 @@ type Opts struct {
TitleColorA color.Color // left gradient ramp point
TitleColorB color.Color // right gradient ramp point
CharmColor color.Color // Charm™ text color
- VersionColor color.Color // Version text color
+ VersionColor color.Color // version text color
Width int // width of the rendered logo, used for truncation
+ Hyper bool // whether it is Crush or Hypercrush
}
// Render renders the Crush logo. Set the argument to true to render the narrow
@@ -32,7 +33,7 @@ type Opts struct {
//
// The compact argument determines whether it renders compact for the sidebar
// or wider for the main pane.
-func Render(s *styles.Styles, version string, compact bool, o Opts) string {
+func Render(base lipgloss.Style, version string, compact bool, o Opts) string {
const charm = " Charm™"
fg := func(c color.Color, s string) string {
@@ -52,12 +53,11 @@ func Render(s *styles.Styles, version string, compact bool, o Opts) string {
if !compact {
stretchIndex = cachedRandN(len(letterforms))
}
-
crush := renderWord(spacing, stretchIndex, letterforms...)
crushWidth := lipgloss.Width(crush)
b := new(strings.Builder)
for r := range strings.SplitSeq(crush, "\n") {
- fmt.Fprintln(b, styles.ApplyForegroundGrad(s, r, o.TitleColorA, o.TitleColorB))
+ fmt.Fprintln(b, styles.ApplyForegroundGrad(base, r, o.TitleColorA, o.TitleColorB))
}
crush = b.String()
@@ -117,7 +117,7 @@ func Render(s *styles.Styles, version string, compact bool, o Opts) string {
// smaller windows or sidebar usage.
func SmallRender(t *styles.Styles, width int) string {
title := t.Base.Foreground(t.Secondary).Render("Charm™")
- title = fmt.Sprintf("%s %s", title, styles.ApplyBoldForegroundGrad(t, "Crush", t.Secondary, t.Primary))
+ title = fmt.Sprintf("%s %s", title, styles.ApplyBoldForegroundGrad(t.Base, "Crush", t.Secondary, t.Primary))
remainingWidth := width - lipgloss.Width(title) - 1 // 1 for the space after "Crush"
if remainingWidth > 0 {
lines := strings.Repeat("╱", remainingWidth)
@@ -5,7 +5,7 @@ import (
"image/color"
"strings"
- "github.com/lucasb-eyer/go-colorful"
+ "charm.land/lipgloss/v2"
"github.com/rivo/uniseg"
)
@@ -13,12 +13,12 @@ import (
// rendered with a horizontal gradient foreground from color1 to color2. Each
// string in the returned slice corresponds to a grapheme cluster in the input
// string. If bold is true, the rendered strings will be bolded.
-func ForegroundGrad(t *Styles, input string, bold bool, color1, color2 color.Color) []string {
+func ForegroundGrad(base lipgloss.Style, input string, bold bool, color1, color2 color.Color) []string {
if input == "" {
return []string{""}
}
if len(input) == 1 {
- style := t.Base.Foreground(color1)
+ style := base.Foreground(color1)
if bold {
style.Bold(true)
}
@@ -30,9 +30,9 @@ func ForegroundGrad(t *Styles, input string, bold bool, color1, color2 color.Col
clusters = append(clusters, string(gr.Runes()))
}
- ramp := blendColors(len(clusters), color1, color2)
+ ramp := lipgloss.Blend1D(len(clusters), color1, color2)
for i, c := range ramp {
- style := t.Base.Foreground(c)
+ style := base.Foreground(c)
if bold {
style.Bold(true)
}
@@ -43,12 +43,12 @@ func ForegroundGrad(t *Styles, input string, bold bool, color1, color2 color.Col
// ApplyForegroundGrad renders a given string with a horizontal gradient
// foreground.
-func ApplyForegroundGrad(t *Styles, input string, color1, color2 color.Color) string {
+func ApplyForegroundGrad(base lipgloss.Style, input string, color1, color2 color.Color) string {
if input == "" {
return ""
}
var o strings.Builder
- clusters := ForegroundGrad(t, input, false, color1, color2)
+ clusters := ForegroundGrad(base, input, false, color1, color2)
for _, c := range clusters {
fmt.Fprint(&o, c)
}
@@ -57,61 +57,14 @@ func ApplyForegroundGrad(t *Styles, input string, color1, color2 color.Color) st
// ApplyBoldForegroundGrad renders a given string with a horizontal gradient
// foreground.
-func ApplyBoldForegroundGrad(t *Styles, input string, color1, color2 color.Color) string {
+func ApplyBoldForegroundGrad(base lipgloss.Style, input string, color1, color2 color.Color) string {
if input == "" {
return ""
}
var o strings.Builder
- clusters := ForegroundGrad(t, input, true, color1, color2)
+ clusters := ForegroundGrad(base, input, true, color1, color2)
for _, c := range clusters {
fmt.Fprint(&o, c)
}
return o.String()
}
-
-// blendColors returns a slice of colors blended between the given keys.
-// Blending is done in Hcl to stay in gamut.
-func blendColors(size int, stops ...color.Color) []color.Color {
- if len(stops) < 2 {
- return nil
- }
-
- stopsPrime := make([]colorful.Color, len(stops))
- for i, k := range stops {
- stopsPrime[i], _ = colorful.MakeColor(k)
- }
-
- numSegments := len(stopsPrime) - 1
- blended := make([]color.Color, 0, size)
-
- // Calculate how many colors each segment should have.
- segmentSizes := make([]int, numSegments)
- baseSize := size / numSegments
- remainder := size % numSegments
-
- // Distribute the remainder across segments.
- for i := range numSegments {
- segmentSizes[i] = baseSize
- if i < remainder {
- segmentSizes[i]++
- }
- }
-
- // Generate colors for each segment.
- for i := range numSegments {
- c1 := stopsPrime[i]
- c2 := stopsPrime[i+1]
- segmentSize := segmentSizes[i]
-
- for j := range segmentSize {
- var t float64
- if segmentSize > 1 {
- t = float64(j) / float64(segmentSize-1)
- }
- c := c1.BlendHcl(c2, t)
- blended = append(blended, c)
- }
- }
-
- return blended
-}