-
-
Notifications
You must be signed in to change notification settings - Fork 298
/
highlighter.go
68 lines (55 loc) · 1.53 KB
/
highlighter.go
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
package highlight
import (
"sync"
"src.elv.sh/pkg/ui"
)
const latesBufferSize = 128
// Highlighter is a code highlighter that can deliver results asynchronously.
type Highlighter struct {
cfg Config
lates chan struct{}
cacheMutex sync.Mutex
cache cache
}
type cache struct {
code string
styledCode ui.Text
tips []ui.Text
}
func NewHighlighter(cfg Config) *Highlighter {
return &Highlighter{cfg: cfg, lates: make(chan struct{}, latesBufferSize)}
}
// Get returns the highlighted code and static errors found in the code as tips.
func (hl *Highlighter) Get(code string) (ui.Text, []ui.Text) {
hl.cacheMutex.Lock()
defer hl.cacheMutex.Unlock()
if code == hl.cache.code {
return hl.cache.styledCode, hl.cache.tips
}
lateCb := func(styledCode ui.Text) {
hl.cacheMutex.Lock()
if hl.cache.code != code {
// Late result was delivered after code has changed. Unlock and
// return.
hl.cacheMutex.Unlock()
return
}
hl.cache.styledCode = styledCode
// The channel send below might block, so unlock the state first.
hl.cacheMutex.Unlock()
hl.lates <- struct{}{}
}
styledCode, tips := highlight(code, hl.cfg, lateCb)
hl.cache = cache{code, styledCode, tips}
return styledCode, tips
}
// LateUpdates returns a channel for notifying late updates.
func (hl *Highlighter) LateUpdates() <-chan struct{} {
return hl.lates
}
// InvalidateCache invalidates the cached highlighting result.
func (hl *Highlighter) InvalidateCache() {
hl.cacheMutex.Lock()
defer hl.cacheMutex.Unlock()
hl.cache = cache{}
}