1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
// SPDX-License-Identifier: GPL-3.0-or-later
package ui
import (
"github.com/diamondburned/gotk4/pkg/gtk/v4"
"krino/gui/internal/model"
)
// The colours a configuration is painted in. They are chosen to read on a
// light and a dark theme alike, since the window follows whatever GTK theme
// is in use (his request, 2026-09-16).
var spanColours = map[model.SpanKind]string{
model.SpanComment: "#8b8b8b",
model.SpanString: "#2e8b57",
model.SpanHead: "#3584e4",
model.SpanAction: "#c06014",
model.SpanParen: "#9a9a9a",
}
// highlighter paints a configuration in a TextView.
type highlighter struct {
buf *gtk.TextBuffer
tags map[model.SpanKind]*gtk.TextTag
on bool
}
// newHighlighter registers one tag per kind, once per buffer.
func newHighlighter(buf *gtk.TextBuffer) *highlighter {
h := &highlighter{buf: buf, tags: map[model.SpanKind]*gtk.TextTag{}, on: true}
table := buf.TagTable()
names := map[model.SpanKind]string{
model.SpanComment: "krino-comment",
model.SpanString: "krino-string",
model.SpanHead: "krino-head",
model.SpanAction: "krino-action",
model.SpanParen: "krino-paren",
}
for kind, name := range names {
t := gtk.NewTextTag(name)
t.SetObjectProperty("foreground", spanColours[kind])
if kind == model.SpanComment {
t.SetObjectProperty("style", 2) // PANGO_STYLE_ITALIC
}
table.Add(t)
h.tags[kind] = t
}
return h
}
// setEnabled turns the colours on or off.
func (h *highlighter) setEnabled(on bool) {
h.on = on
if !on {
h.clear()
}
}
// clear takes every colour off the buffer.
func (h *highlighter) clear() {
start, end := h.buf.Bounds()
h.buf.RemoveAllTags(start, end)
}
// paint colours the text now in the buffer.
func (h *highlighter) paint(text string) {
h.clear()
if !h.on {
return
}
for _, s := range model.Spans(text) {
if tag, ok := h.tags[s.Kind]; ok {
h.buf.ApplyTag(tag, h.buf.IterAtOffset(s.From), h.buf.IterAtOffset(s.To))
}
}
}
|