turbo-editors/turbo-corepublic Fork 0
v0.9.0
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-core.git
git clone ssh://git@rickub.com/turbo-editors/turbo-core.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

view_draw.go · 107 lines · 2.9 KBGo Blame HistoryRaw
🛟 Updated. 28d5985 k33g 17h ago1package terminal
2
3import (
4 "github.com/gdamore/tcell/v2"
5
6 "codeberg.org/turbo-editors/turbo-core/theme"
7 "codeberg.org/turbo-editors/turbo-core/ui"
8)
9
10// Draw paints the terminal's grid.
11func (v *View) Draw(p *ui.Painter, th *theme.Theme) {
12 v.mu.Lock()
13 defer v.mu.Unlock()
14
15 area := p.Size()
16 base := th.Style(theme.KeyTerminalText)
17 p.Fill(area, ' ', base)
18
19 for row := range area.H {
20 v.drawLine(p, v.lineAt(row), row, area.W, base)
21 }
22 v.drawCursor(p, th)
23}
24
25// drawLine paints one row of the grid.
26func (v *View) drawLine(p *ui.Painter, line Line, row, width int, base tcell.Style) {
27 for col, cell := range line {
28 if col >= width {
29 return
30 }
31 p.SetCell(col, row, cell.Rune, resolve(cell.Style, base))
32 }
33}
34
35// resolve fills a cell's unset colours in from the theme.
36//
37// A program that has said nothing about colour gets the theme's, which is what
38// lets a terminal window look like the rest of the editor instead of like the
39// terminal's own defaults.
40func resolve(style, base tcell.Style) tcell.Style {
41 foreground, background, _ := style.Decompose()
42 baseForeground, baseBackground, _ := base.Decompose()
43
44 if foreground == tcell.ColorDefault {
45 style = style.Foreground(baseForeground)
46 }
47 if background == tcell.ColorDefault {
48 style = style.Background(baseBackground)
49 }
50 return style
51}
52
53// drawCursor marks where the shell's cursor is.
54//
55// It is drawn only on the live screen: a cursor shown while the user is
56// reading back through the history would point at a line the shell is not
57// writing to.
58func (v *View) drawCursor(p *ui.Painter, th *theme.Theme) {
59 screen := v.parser.Screen()
60 if v.scrollOffset != 0 || !screen.CursorVisible() || !v.Focused() {
61 return
62 }
63
64 cursor := screen.Cursor()
65 character, _ := p.CellAt(cursor.Col, cursor.Row)
66 p.SetCell(cursor.Col, cursor.Row, character, th.Style(theme.KeyTerminalCursor))
67 p.ShowCursor(cursor.Col, cursor.Row)
68}
69
70// lineAt returns the line to show on a visible row, which comes from the
71// history when the view has been scrolled back.
72//
73// It must be called with the lock held.
74func (v *View) lineAt(row int) Line {
75 screen := v.parser.Screen()
76 index := screen.ScrollbackLen() - v.scrollOffset + row
77
78 if index < screen.ScrollbackLen() {
79 return screen.ScrollbackLine(index)
80 }
81 return screen.Line(index - screen.ScrollbackLen())
82}
83
84// ScrollOffset returns how many lines back into the history the view is
85// looking. Zero is the live screen.
86func (v *View) ScrollOffset() int {
87 v.mu.Lock()
88 defer v.mu.Unlock()
89 return v.scrollOffset
90}
91
92// ScrollBy moves the view back through the history, or forwards towards the
93// live screen with a negative count. It stops at either end.
94func (v *View) ScrollBy(lines int) {
95 v.mu.Lock()
96 defer v.mu.Unlock()
97
98 v.scrollOffset = min(max(v.scrollOffset+lines, 0), v.parser.Screen().ScrollbackLen())
99}
100
101// ScrollToBottom goes back to the live screen, which is where any key press
102// puts the view.
103func (v *View) ScrollToBottom() {
104 v.mu.Lock()
105 defer v.mu.Unlock()
106 v.scrollOffset = 0
107}