styles.go RawHistoryFolder

1package theme
2
3import (
4	"math"
5
6	renderer "github.com/bnema/vev-vt"
7	"github.com/bnema/vev/internal/domain"
8)
9
10const accentContrastMin = 3.0
11
12// RelativeLuminance returns a color's WCAG 2.x relative luminance.
13func RelativeLuminance(color renderer.RGB) float64 {
14	linearize := func(channel uint8) float64 {
15		srgb := float64(channel) / 255
16		if srgb <= 0.04045 {
17			return srgb / 12.92
18		}
19		return math.Pow((srgb+0.055)/1.055, 2.4)
20	}
21
22	return 0.2126*linearize(color.R) +
23		0.7152*linearize(color.G) +
24		0.0722*linearize(color.B)
25}
26
27// ContrastRatio returns the WCAG 2.x contrast ratio between two colors.
28func ContrastRatio(a, b renderer.RGB) float64 {
29	aLuminance := RelativeLuminance(a)
30	bLuminance := RelativeLuminance(b)
31	lighter := math.Max(aLuminance, bLuminance)
32	darker := math.Min(aLuminance, bLuminance)
33	return (lighter + 0.05) / (darker + 0.05)
34}
35
36// PulseColor derives the attention pulse color at intensity while preserving
37// the base style's remaining attributes.
38func PulseColor(base renderer.Style, intensity float64) renderer.Style {
39	style := base
40	style.Bold = true
41	if base.HasForegroundRGB && base.HasBackgroundRGB {
42		style.ForegroundRGB = Blend(base.BackgroundRGB, base.ForegroundRGB, intensity)
43	} else {
44		style.HasForegroundRGB = false
45		style.Foreground = 244 + int(intensity*11)
46	}
47	return style
48}
49
50// MRUFade fades an MRU style by position, reaching 60 percent of the terminal
51// background color at the oldest entry.
52func MRUFade(base renderer.Style, t Theme, i, count int) renderer.Style {
53	if count <= 1 || !base.HasForegroundRGB || !base.HasBackgroundRGB || !t.HasBG {
54		return base
55	}
56	amount := (float64(i) / float64(count-1)) * 0.6
57	base.ForegroundRGB = Blend(base.ForegroundRGB, t.Background, amount)
58	base.BackgroundRGB = Blend(base.BackgroundRGB, t.Background, amount)
59	return base
60}
61
62// Styles is the complete semantic set of terminal chrome styles. The legacy
63// aliases remain until daemon renderers consume the semantic fields directly.
64type Styles struct {
65	// mruStyles are all position/count combinations that status composition
66	// can display. They keep OKLab interpolation out of render paths.
67	mruStyles [9][9]renderer.Style
68
69	SurfaceBar      renderer.Style
70	SurfaceInactive renderer.Style
71	SurfaceRecent   renderer.Style
72	SurfaceActive   renderer.Style
73	BorderMuted     renderer.Style
74	BorderActive    renderer.Style
75	// BorderWarn is the amber-hued warn-severity border. Unlike every other
76	// role in this camaïeu palette it does not blend toward the resolved
77	// accent color: it keeps the accent's lightness/chroma band but shifts
78	// hue to a fixed amber target (see warnHueDegrees), so Warn reads as
79	// amber and stays distinct from Error regardless of the accent hue.
80	BorderWarn renderer.Style
81	// NeutralBorder is the non-accent structural border for pane dividers and
82	// unfocused pane title bars. It is resolved with the rest of the immutable
83	// chrome snapshot so composition never derives theme colors.
84	NeutralBorder renderer.Style
85
86	TabInactive      renderer.Style
87	TabInactiveTitle renderer.Style
88	TabActive        renderer.Style
89	TabActiveTitle   renderer.Style
90	MRURecent        renderer.Style
91
92	PickerBase      renderer.Style
93	PickerSelection renderer.Style
94	// HintKey is the keycap badge style for key hints: an accent background
95	// over " key " padding, distinct from PickerSelection's full-line emphasis.
96	HintKey           renderer.Style
97	PickerDescription renderer.Style
98	PickerSeparator   renderer.Style
99	PromptBase        renderer.Style
100	CopyStatus        renderer.Style
101	SearchSelection   renderer.Style
102
103	// Compatibility aliases for pre-cache render paths.
104	StatusBar            renderer.Style
105	Accent               renderer.Style
106	Border               renderer.Style
107	Selection            renderer.Style
108	PaletteDesc          renderer.Style
109	TabName              renderer.Style
110	TabNameActive        renderer.Style
111	TabTitle             renderer.Style
112	TabTitleActive       renderer.Style
113	PickerName           renderer.Style
114	PickerSelectionName  renderer.Style
115	PickerSelectionMuted renderer.Style
116}
117
118// NewStyles applies the default automatic policy. New callers that own a
119// policy should use Resolve and retain its complete immutable result.
120func NewStyles(t Theme) Styles {
121	return Resolve(t, domain.ThemeAccent{Mode: domain.ThemeAccentAuto}).Styles
122}
123
124// MRUStyle returns the position-dependent recent-session surface. Color
125// interpolation stays owned by theme; renderers consume only this cached
126// semantic style snapshot.
127func (s Styles) MRUStyle(index, count int) renderer.Style {
128	if count <= 0 || count > len(s.mruStyles) {
129		return s.MRURecent
130	}
131	if index < 0 {
132		index = 0
133	}
134	if index >= count {
135		index = count - 1
136	}
137	return s.mruStyles[count-1][index]
138}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 12

Tags 11

↑↓ moveenter openesc close