v0.7.0 4c16dd8

color_policy.go RawHistoryFolder

1package theme
2
3import (
4	renderer "github.com/bnema/vev-vt"
5	"github.com/bnema/vev/internal/domain"
6	"github.com/bnema/vev/internal/domain/terminalcap"
7)
8
9// reducedColor reports whether chrome for c must be built from attributes and
10// terminal palette slots instead of RGB surfaces: 16-color and monochrome
11// attachments.
12func reducedColor(c terminalcap.ColorCapabilities) bool {
13	return c.Mode == terminalcap.ANSI16 || c.Mode == terminalcap.Monochrome
14}
15
16// ResolveForColor is Resolve for one attachment's color capability. TrueColor
17// and ANSI256 return exactly what Resolve returns. ANSI16 and Monochrome
18// replace the chrome styles with the reduced-color policy (see reducedStyles)
19// and mark the returned Theme so dimming uses the faint attribute instead of
20// RGB blends. Color is per attachment, so callers resolve once per attachment.
21func ResolveForColor(t Theme, policy domain.ThemeAccent, color terminalcap.ColorCapabilities) ResolvedTheme {
22	if !reducedColor(color) {
23		return Resolve(t, policy)
24	}
25	t.DimByAttribute = true
26	resolved := Resolve(t, policy) // resolved.Theme carries DimByAttribute
27	accent := resolved.Accent
28	slot := -1
29	if (accent.Known || accent.IndexedOnly) && accent.Slot < 16 {
30		slot = int(accent.Slot)
31	}
32	resolved.Styles = reducedStyles(slot, color.Mode == terminalcap.Monochrome)
33	return resolved
34}
35
36// reducedStyles builds the chrome for terminals that cannot show tinted RGB
37// surfaces. Surfaces keep the terminal's default background; hierarchy comes
38// from attributes, and the accent (when known) is only ever a palette slot
39// 0-15 so the terminal's own palette renders it:
40//
41//   - active tab, session name, selected rows, hint keys, search selection:
42//     bold reverse, so contrast is always the terminal's own fg/bg pair;
43//   - copy status, copy selection and the focused pane title: plain reverse
44//     (a selection keeps the text's own colors);
45//   - inactive tabs and bars: plain; secondary text, muted borders and
46//     unfocused titles: faint;
47//   - focused borders: bold, in the accent palette slot when there is one;
48//     warn borders: bold yellow (slot 3); errors share the focused border.
49//
50// Monochrome uses the same attributes with no color at all. The accent never
51// fills a background: a palette slot is not guaranteed to contrast with the
52// terminal background that reverse video would put on top of it.
53func reducedStyles(accentSlot int, mono bool) Styles {
54	plain := renderer.DefaultStyle()
55	withFG := func(s renderer.Style, slot int) renderer.Style {
56		if !mono && slot >= 0 {
57			s.Foreground = slot
58		}
59		return s
60	}
61	with := func(base renderer.Style, bold, italic, inverse, faint bool) renderer.Style {
62		base.Bold, base.Italic, base.Inverse = bold, italic, inverse
63		if faint {
64			base.Attrs |= renderer.AttrDim
65		}
66		return base
67	}
68	active := with(plain, true, false, true, false)
69	activeTitle := with(plain, false, false, true, false)
70	selectionMuted := with(plain, false, true, true, false)
71	faint := with(plain, false, false, false, true)
72	description := with(plain, false, true, false, true)
73	focusedBorder := with(withFG(plain, accentSlot), true, false, false, false)
74	warn := with(plain, true, true, false, false)
75	if !mono {
76		warn = with(withFG(plain, 3), true, false, false, false)
77	}
78	copySelection := with(plain, false, false, true, false)
79
80	s := Styles{
81		Reduced: true,
82
83		SurfaceBar:      plain,
84		SurfaceInactive: plain,
85		SurfaceRecent:   plain,
86		SurfaceActive:   active,
87		BorderMuted:     faint,
88		BorderActive:    focusedBorder,
89		BorderWarn:      warn,
90		NeutralBorder:   faint,
91
92		TabInactive:      plain,
93		TabInactiveTitle: faint,
94		TabActive:        active,
95		TabActiveTitle:   activeTitle,
96		MRURecent:        plain,
97
98		PickerBase:        plain,
99		PickerSelection:   active,
100		HintKey:           active,
101		PickerDescription: description,
102		PickerSeparator:   faint,
103		PromptBase:        plain,
104		CopyStatus:        with(plain, false, false, true, false),
105		SearchSelection:   active,
106	}
107	// Aliases consumed by render paths that have not migrated yet. Selection
108	// is the copy-mode selection role and StatusBar the focused pane title
109	// bar; both are plain reverse.
110	s.StatusBar = copySelection
111	s.Accent = s.SurfaceActive
112	s.Border = s.BorderMuted
113	s.Selection = copySelection
114	s.PaletteDesc = description
115	s.TabName = s.TabInactive
116	s.TabNameActive = s.TabActive
117	s.TabTitle = s.TabInactiveTitle
118	s.TabTitleActive = s.TabActiveTitle
119	s.PickerName = plain
120	s.PickerSelectionName = active
121	s.PickerSelectionMuted = selectionMuted
122	for count := range s.mruStyles {
123		for index := 0; index <= count; index++ {
124			s.mruStyles[count][index] = plain
125		}
126	}
127	return s
128}

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