history_policy.go RawHistoryFolder

1package daemon
2
3import (
4	"context"
5	"time"
6
7	vt "github.com/bnema/vev-vt"
8	"github.com/bnema/vev/internal/domain"
9)
10
11func historyConfigFor(policy domain.ScrollbackConfig) vt.HistoryConfig {
12	if policy.Megabytes == 0 {
13		return vt.HistoryConfig{}
14	}
15	return vt.HistoryConfig{MaxBytes: policy.Megabytes * 1_000_000, MaxRows: policy.Lines}
16}
17
18func (d *Daemon) currentHistoryConfig() vt.HistoryConfig {
19	policy := d.scrollbackConfig.Load()
20	if policy == nil {
21		return historyConfigFor(domain.DefaultScrollbackConfig())
22	}
23	return historyConfigFor(*policy)
24}
25
26// historyPanes gathers references without holding a session/tab lock while
27// touching history. Include hidden floating panes; deduplicate a pane that moves
28// between tabs while the separate session snapshots are being collected.
29func (d *Daemon) historyPanes() []*pane {
30	var panes []*pane
31	seen := make(map[*pane]struct{})
32	for _, sess := range d.sessionsSnapshot() {
33		sess.mu.Lock()
34		tabs := append([]*tab(nil), sess.tabs...)
35		sess.mu.Unlock()
36		for _, tb := range tabs {
37			if tb == nil {
38				continue
39			}
40			tb.mu.Lock()
41			current := tb.panesSnapshot()
42			if tb.floating.pane != nil {
43				current = append(current, tb.floating.pane)
44			}
45			tb.mu.Unlock()
46			for _, p := range current {
47				if p == nil {
48					continue
49				}
50				if _, exists := seen[p]; exists {
51					continue
52				}
53				seen[p] = struct{}{}
54				panes = append(panes, p)
55			}
56		}
57	}
58	return panes
59}
60
61func (d *Daemon) applyHistoryLimitsToPane(p *pane) {
62	p.mu.Lock()
63	var err error
64	if p.history != nil {
65		// Load inside the pane lock so an older concurrent reload cannot install
66		// a stale policy after a newer reload has already published its value.
67		err = p.history.SetLimits(d.currentHistoryConfig())
68	}
69	p.mu.Unlock()
70	if err != nil {
71		d.log.Warn("cannot apply scrollback limits", "err", err)
72	}
73}
74
75func (d *Daemon) applyHistoryLimits() {
76	for _, p := range d.historyPanes() {
77		d.applyHistoryLimitsToPane(p)
78	}
79}
80
81// Keep background compression infrequent and bounded; it must not compete
82// with interactive output when many panes retain history.
83const historyMaintenanceInterval = 5 * time.Second
84
85// historyMaintenance is application scheduling, not a VT-owned worker. It
86// visits one history page per pane per interval and skips busy/resizing panes.
87func (d *Daemon) historyMaintenance(ctx context.Context) {
88	timer := d.clock.NewTimer(historyMaintenanceInterval)
89	defer timer.Stop()
90	for {
91		select {
92		case <-ctx.Done():
93			return
94		case <-timer.C():
95			d.compressIdleHistories()
96			timer.Reset(historyMaintenanceInterval)
97		}
98	}
99}
100
101func (d *Daemon) compressIdleHistories() {
102	for _, p := range d.historyPanes() {
103		if !p.mu.TryLock() {
104			continue
105		}
106		var err error
107		if p.history != nil && !p.resizeApplying {
108			_, err = p.history.CompressIdle(1)
109		}
110		p.mu.Unlock()
111		if err != nil {
112			d.log.Warn("cannot compress idle scrollback", "err", err)
113		}
114	}
115}

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