v0.7.0 36c429d

screen_snapshot.go RawHistoryFolder

1package vt
2
3import (
4	renderer "github.com/bnema/vev-vt/core"
5	"github.com/bnema/vev-vt/graphics"
6)
7
8// CursorSnapshot is the cursor state captured with a visible screen snapshot.
9type CursorSnapshot struct {
10	Row      int
11	Col      int
12	Visible  bool
13	Style    int
14	StyleSet bool
15}
16
17// ModeSnapshot is the renderer-relevant VT mode state captured with a screen.
18type ModeSnapshot struct {
19	AlternateScreen    bool
20	BracketedPaste     bool
21	SynchronizedUpdate bool
22	ColorSchemeMode    bool
23	MouseTracking      int
24	MouseSGR           bool
25	// KittyKeyboard is the active screen's kitty keyboard enhancement flags.
26	KittyKeyboard int
27}
28
29// ScreenSnapshot is an owned immutable capture of the active terminal
30// viewport. It implements core.CellSource, and Row returns caller-owned storage.
31type ScreenSnapshot struct {
32	frame             renderer.Frame
33	bounds            []LineBound
34	rowIDs            []RowID
35	cursor            CursorSnapshot
36	modes             ModeSnapshot
37	autoWrap          bool
38	applicationCursor bool
39	title             string
40	graphics          *graphics.Snapshot
41	nextRowID         RowID
42}
43
44// Snapshot captures the active visible viewport without mutating Screen,
45// history, or pending damage. Screen remains single-owner; callers must
46// serialize Snapshot with Write, Resize, and host mutations.
47func (s *Screen) Snapshot() ScreenSnapshot {
48	if s == nil {
49		return ScreenSnapshot{}
50	}
51	cursorStyle, cursorStyleSet := s.CursorStyle()
52	mouseTracking, mouseSGR := s.MouseMode()
53	nextRowID := s.nextRowID
54	if nextRowID < ^RowID(0) {
55		nextRowID++
56	}
57	return ScreenSnapshot{
58		frame:             s.frame.Clone(),
59		bounds:            s.LineBounds(),
60		rowIDs:            s.RowIDs(),
61		nextRowID:         nextRowID,
62		autoWrap:          s.AutoWrapMode(),
63		applicationCursor: s.ApplicationCursorMode(),
64		cursor: CursorSnapshot{
65			Row:      s.CursorRow(),
66			Col:      s.CursorCol(),
67			Visible:  s.CursorVisible(),
68			Style:    cursorStyle,
69			StyleSet: cursorStyleSet,
70		},
71		modes: ModeSnapshot{
72			AlternateScreen:    s.AltScreenActive(),
73			BracketedPaste:     s.BracketedPasteMode(),
74			SynchronizedUpdate: s.SyncUpdateActive(),
75			ColorSchemeMode:    s.ColorSchemeMode(),
76			MouseTracking:      mouseTracking,
77			MouseSGR:           mouseSGR,
78			KittyKeyboard:      s.KittyKeyboardFlags(),
79		},
80		title:    s.TerminalTitle(),
81		graphics: s.GraphicsSnapshot(),
82	}
83}
84
85func (s ScreenSnapshot) Columns() int { return s.frame.Width }
86func (s ScreenSnapshot) Rows() int    { return s.frame.Height }
87
88// Cell returns the semantic cell at x, y.
89func (s ScreenSnapshot) Cell(x, y int) renderer.Cell { return s.frame.Cell(x, y) }
90
91// Row returns an owned copy of row y, or nil when y is out of range.
92func (s ScreenSnapshot) Row(y int) []renderer.Cell {
93	if y < 0 || y >= s.frame.Height {
94		return nil
95	}
96	return s.frame.Row(y)
97}
98
99func (s ScreenSnapshot) Bound(y int) LineBound {
100	if y < 0 || y >= len(s.bounds) {
101		return LineBound{}
102	}
103	return s.bounds[y]
104}
105
106// RowIDs returns an owned copy of the visible physical-row identities.
107func (s ScreenSnapshot) RowIDs() []RowID { return append([]RowID(nil), s.rowIDs...) }
108
109// RowID returns the identity of visible row y, or zero when out of range.
110func (s ScreenSnapshot) RowID(y int) RowID {
111	if y < 0 || y >= len(s.rowIDs) {
112		return 0
113	}
114	return s.rowIDs[y]
115}
116
117// NextRowID returns the next identity allocated by the captured screen.
118func (s ScreenSnapshot) NextRowID() RowID {
119	if s.nextRowID == 0 {
120		return 1
121	}
122	return s.nextRowID
123}
124
125func (s ScreenSnapshot) Cursor() CursorSnapshot { return s.cursor }
126func (s ScreenSnapshot) Modes() ModeSnapshot    { return s.modes }
127
128// AutoWrapMode reports whether DEC private mode 7 (DECAWM) was enabled in the
129// captured screen.
130func (s ScreenSnapshot) AutoWrapMode() bool { return s.autoWrap }
131
132// ApplicationCursorMode reports whether DEC private mode 1 (DECCKM) was enabled
133// in the captured screen.
134func (s ScreenSnapshot) ApplicationCursorMode() bool { return s.applicationCursor }
135
136func (s ScreenSnapshot) Title() string { return s.title }
137
138// Graphics returns the immutable graphics scene snapshot for the active
139// screen buffer, or nil when that buffer has not used Kitty graphics.
140func (s ScreenSnapshot) Graphics() *graphics.Snapshot { return s.graphics }

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