github.com/elves/elvish@v0.15.0/pkg/edit/highlight/highlighter.go (about) 1 package highlight 2 3 import ( 4 "sync" 5 6 "github.com/elves/elvish/pkg/ui" 7 ) 8 9 const latesBufferSize = 128 10 11 // Highlighter is a code highlighter that can deliver results asynchronously. 12 type Highlighter struct { 13 cfg Config 14 state state 15 lates chan struct{} 16 } 17 18 type state struct { 19 sync.Mutex 20 code string 21 styledCode ui.Text 22 errors []error 23 } 24 25 func NewHighlighter(cfg Config) *Highlighter { 26 return &Highlighter{cfg, state{}, make(chan struct{}, latesBufferSize)} 27 } 28 29 // Get returns the highlighted code and static errors found in the code. 30 func (hl *Highlighter) Get(code string) (ui.Text, []error) { 31 hl.state.Lock() 32 defer hl.state.Unlock() 33 if code == hl.state.code { 34 return hl.state.styledCode, hl.state.errors 35 } 36 37 lateCb := func(styledCode ui.Text) { 38 hl.state.Lock() 39 if hl.state.code != code { 40 // Late result was delivered after code has changed. Unlock and 41 // return. 42 hl.state.Unlock() 43 return 44 } 45 hl.state.styledCode = styledCode 46 // The channel send below might block, so unlock the state first. 47 hl.state.Unlock() 48 hl.lates <- struct{}{} 49 } 50 51 styledCode, errors := highlight(code, hl.cfg, lateCb) 52 53 hl.state.code = code 54 hl.state.styledCode = styledCode 55 hl.state.errors = errors 56 return styledCode, errors 57 } 58 59 // LateUpdates returns a channel for notifying late updates. 60 func (hl *Highlighter) LateUpdates() <-chan struct{} { 61 return hl.lates 62 }