-
Notifications
You must be signed in to change notification settings - Fork 68
Restore simplified color detection #33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,22 +2,26 @@ package ui | |||||||||||||||
|
|
||||||||||||||||
| import ( | ||||||||||||||||
| "image/color" | ||||||||||||||||
| "log/slog" | ||||||||||||||||
| "math" | ||||||||||||||||
| "os" | ||||||||||||||||
| "time" | ||||||||||||||||
|
|
||||||||||||||||
| "charm.land/lipgloss/v2" | ||||||||||||||||
| "github.com/charmbracelet/x/ansi" | ||||||||||||||||
| "github.com/lucasb-eyer/go-colorful" | ||||||||||||||||
| ) | ||||||||||||||||
|
|
||||||||||||||||
| // Palette holds all colors used by the UI. ANSI color fields always contain | ||||||||||||||||
| // BasicColor values so the terminal applies its own theme. Synthesized | ||||||||||||||||
| // colors (FocusOrange, BackgroundTint, LightText) are true-color RGB. | ||||||||||||||||
| // BasicColor values so the terminal applies its own theme. The synthesized | ||||||||||||||||
| // colors (FocusOrange, BackgroundTint, LightText) are true-color RGB when | ||||||||||||||||
| // the terminal supports it, or ANSI fallbacks otherwise. | ||||||||||||||||
| type Palette struct { | ||||||||||||||||
| // ANSI 16 — always BasicColor values for rendering | ||||||||||||||||
| Black, Red, Green, Yellow, Blue, Magenta, Cyan, White color.Color | ||||||||||||||||
| BrightBlack, BrightRed, BrightGreen, BrightYellow, BrightBlue, BrightMagenta, BrightCyan, BrightWhite color.Color | ||||||||||||||||
|
|
||||||||||||||||
| // Synthesized (always true-color RGB) | ||||||||||||||||
| // Synthesized (true-color RGB when supported, ANSI fallbacks otherwise) | ||||||||||||||||
| FocusOrange color.Color | ||||||||||||||||
| BackgroundTint color.Color | ||||||||||||||||
| LightText color.Color | ||||||||||||||||
|
|
@@ -30,19 +34,29 @@ type Palette struct { | |||||||||||||||
| Error color.Color // = Red | ||||||||||||||||
| Success color.Color // = Green | ||||||||||||||||
| Warning color.Color // = FocusOrange | ||||||||||||||||
| // Private: detected RGB samples for calculations | ||||||||||||||||
| samples [sampleCount]colorful.Color | ||||||||||||||||
| detected [sampleCount]bool | ||||||||||||||||
| isDark bool | ||||||||||||||||
|
|
||||||||||||||||
| isDark bool | ||||||||||||||||
| trueColor bool | ||||||||||||||||
| gradientGreen colorful.Color | ||||||||||||||||
| gradientOrange colorful.Color | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| // Gradient interpolates between green and FocusOrange in OKLCH. | ||||||||||||||||
| // t=0 returns green, t=1 returns orange. | ||||||||||||||||
| // t=0 returns green, t=1 returns orange. When true color is not | ||||||||||||||||
| // supported, the gradient is clamped to ANSI green/yellow/red. | ||||||||||||||||
| func (p *Palette) Gradient(t float64) color.Color { | ||||||||||||||||
| t = max(0, min(1, t)) | ||||||||||||||||
| greenSample := p.samples[int(ansi.Green)] | ||||||||||||||||
| orangeSample, _ := colorful.MakeColor(p.FocusOrange) | ||||||||||||||||
| return greenSample.BlendOkLch(orangeSample, t) | ||||||||||||||||
| if !p.trueColor { | ||||||||||||||||
| switch { | ||||||||||||||||
| case t < 0.33: | ||||||||||||||||
| return p.Green | ||||||||||||||||
| case t < 0.67: | ||||||||||||||||
| return p.Yellow | ||||||||||||||||
| default: | ||||||||||||||||
| return p.Red | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
| return p.gradientGreen.BlendOkLch(p.gradientOrange, t) | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| // HealthColor returns the palette color for the given health state. | ||||||||||||||||
|
|
@@ -57,9 +71,31 @@ func (p *Palette) HealthColor(h HealthState) color.Color { | |||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| // DefaultPalette returns a palette with ANSI BasicColor values and | ||||||||||||||||
| // fallback-derived synthesized colors. This is the package-init value. | ||||||||||||||||
| func DefaultPalette() *Palette { | ||||||||||||||||
| // SupportsTrueColor reports whether the terminal is likely to support | ||||||||||||||||
| // 24-bit color output. | ||||||||||||||||
| func (p *Palette) SupportsTrueColor() bool { | ||||||||||||||||
| return p.trueColor | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| // Detect queries the terminal for colors and updates the palette | ||||||||||||||||
| // accordingly. If detection succeeds (all 18 colors received), | ||||||||||||||||
| // synthesized colors are computed from the detected RGB values. | ||||||||||||||||
| // If COLORTERM indicates true-color support, synthesized colors | ||||||||||||||||
| // are computed from fallback samples. Otherwise the ANSI defaults | ||||||||||||||||
| // from defaultPalette are kept. | ||||||||||||||||
|
||||||||||||||||
| // from defaultPalette are kept. | |
| // from defaultPalette are kept. | |
| // | |
| // DetectTerminalColors requires the terminal to already be in raw mode; | |
| // callers of Detect are responsible for putting the terminal into raw mode | |
| // before calling this method and restoring the previous state afterwards. | |
| // Calling Detect without raw mode can lead to unreliable results or timeouts. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The doc comment says synthesized colors (including BackgroundTint) use “ANSI fallbacks otherwise”, but BackgroundTint is intentionally left nil when true color isn’t enabled. Consider updating the comment to reflect that BackgroundTint may be nil (and callers should guard), rather than implying an ANSI fallback exists.