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  }