v0.7.0 36c429d

history_styleset.go RawHistoryFolder

1package vt
2
3import (
4	"iter"
5	"slices"
6
7	renderer "github.com/bnema/vev-vt/core"
8)
9
10// styleSetInline is the number of distinct styles kept in a linear slice
11// before the set switches to a map. Typical rows use a handful of styles, where
12// a short compare loop beats hashing the 56-byte Style key.
13const styleSetInline = 16
14
15// styleSet is a reusable set of canonical styles for one history row. It keeps
16// small sets in a slice and only builds a map for high-cardinality rows. The
17// zero value is empty and ready to use.
18type styleSet struct {
19	small []renderer.Style
20	large map[renderer.Style]struct{}
21}
22
23func (s *styleSet) reset() {
24	s.small = s.small[:0]
25	if len(s.large) > maxRetainedStyleScratch {
26		s.large = nil
27	} else {
28		clear(s.large)
29	}
30}
31
32func (s *styleSet) add(style renderer.Style) {
33	if len(s.large) > 0 {
34		s.large[style] = struct{}{}
35		return
36	}
37	if slices.Contains(s.small, style) {
38		return
39	}
40	if len(s.small) < styleSetInline {
41		s.small = append(s.small, style)
42		return
43	}
44	if s.large == nil {
45		s.large = make(map[renderer.Style]struct{}, 2*styleSetInline)
46	}
47	for _, existing := range s.small {
48		s.large[existing] = struct{}{}
49	}
50	s.large[style] = struct{}{}
51	s.small = s.small[:0]
52}
53
54func (s *styleSet) len() int {
55	if len(s.large) > 0 {
56		return len(s.large)
57	}
58	return len(s.small)
59}
60
61// all yields each style once, in unspecified order.
62func (s *styleSet) all() iter.Seq[renderer.Style] {
63	return func(yield func(renderer.Style) bool) {
64		if len(s.large) > 0 {
65			for style := range s.large {
66				if !yield(style) {
67					return
68				}
69			}
70			return
71		}
72		for _, style := range s.small {
73			if !yield(style) {
74				return
75			}
76		}
77	}
78}

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 2

Tags 13

↑↓ moveenter openesc close