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.

marks.go · 85 lines · 2.9 KBGo Blame HistoryRaw
🛟 Updated. 28d5985 k33g 17h ago1// Marks in the gutter: a character beside a line saying something is wrong
2// with it.
3
4package editor
5
6import "codeberg.org/turbo-editors/turbo-core/theme"
7
8// Severity is how serious a mark is.
9//
10// This is the editor's own type, not the language server's, and deliberately
11// so: this package colours and draws text, and knows nothing about protocols.
12// Whoever holds the diagnostics translates them into these on the way in.
13//
14// view.SetMarks(map[int]editor.Severity{41: editor.MarkError})
15type Severity int
16
17// The severities a mark may have, in the order a line's worst one is chosen.
18const (
19 // MarkNone is the zero value: a line with nothing wrong with it.
20 MarkNone Severity = iota
21 MarkHint
22 MarkInformation
23 MarkWarning
24 MarkError
25)
26
27// markGlyphs are what each severity draws. They are single characters from the
28// range every terminal font has, because the gutter has exactly one column to
29// spare and a glyph that renders as a box is worse than a letter.
30var markGlyphs = map[Severity]rune{
31 MarkError: '×',
32 MarkWarning: '!',
33 MarkInformation: 'i',
34 MarkHint: '·',
35}
36
37// markStyles are the theme keys each severity is drawn in.
38var markStyles = map[Severity]string{
39 MarkError: theme.KeyDiagnosticError,
40 MarkWarning: theme.KeyDiagnosticWarning,
41 MarkInformation: theme.KeyDiagnosticInfo,
42 MarkHint: theme.KeyDiagnosticInfo,
43}
44
45// SetMarks says which lines have something wrong with them, keyed by
46// zero-based line number.
47//
48// Passing nil clears them, which is what a file with nothing wrong wants.
49//
50// view.SetMarks(map[int]editor.Severity{0: editor.MarkWarning, 12: editor.MarkError})
51func (v *View) SetMarks(marks map[int]Severity) { v.marks = marks }
52
53// Marks returns what SetMarks was given.
54func (v *View) Marks() map[int]Severity { return v.marks }
55
56// markOf returns the severity to draw beside a line, and whether there is one.
57func (v *View) markOf(line int) (Severity, bool) {
58 severity, marked := v.marks[line]
59 if !marked || severity == MarkNone {
60 return MarkNone, false
61 }
62 return severity, true
63}
64
65// drawMark paints the mark for a line, in the column that separates the line
66// numbers from the text.
67//
68// That column rather than a new one: the gutter is already `digits + 1` wide,
69// the +1 being the separator, so a mark costs no layout and nothing has to be
70// recomputed — not the text's left edge, not the cursor's screen column, not
71// the column a mouse click lands on.
72//
73// The consequence is that hiding the line numbers hides the marks. The
74// alternative — a one-column gutter appearing when the numbers are off — would
75// make the text jump sideways the moment a server reported anything.
76func (v *View) drawMark(p *Painter, th *theme.Theme, row, line int) {
77 if !v.lineNumbers {
78 return
79 }
80 severity, marked := v.markOf(line)
81 if !marked {
82 return
83 }
84 p.Text(v.gutterWidth()-1, row, string(markGlyphs[severity]), th.Style(markStyles[severity]))
85}