From 953f5a0eff873fe94ff6d946a18511bc580c873b Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Tue, 28 Jan 2020 20:54:14 -0500 Subject: [PATCH] Highlight in parallel --- cmd/micro/micro.go | 19 ++++++++++++++-- internal/buffer/buffer.go | 13 ++++++++--- internal/buffer/line_array.go | 42 +++++++++++++++++++++++++++++++---- 3 files changed, 65 insertions(+), 9 deletions(-) diff --git a/cmd/micro/micro.go b/cmd/micro/micro.go index 3e2f95fa..fb5ce220 100644 --- a/cmd/micro/micro.go +++ b/cmd/micro/micro.go @@ -7,6 +7,7 @@ import ( "os" "runtime" "sort" + "time" "github.com/go-errors/errors" isatty "github.com/mattn/go-isatty" @@ -240,6 +241,22 @@ func main() { } }() + // clear the drawchan so we don't redraw excessively + // if someone requested a redraw before we started displaying + for len(screen.DrawChan) > 0 { + <-screen.DrawChan + } + + var event tcell.Event + + // wait for initial resize event + select { + case event = <-events: + action.Tabs.HandleEvent(event) + case <-time.After(20 * time.Millisecond): + // time out after 10ms + } + for { // Display everything screen.Screen.Fill(' ', config.DefStyle) @@ -252,8 +269,6 @@ func main() { action.InfoBar.Display() screen.Screen.Show() - var event tcell.Event - // Check for new events select { case f := <-shell.Jobs: diff --git a/internal/buffer/buffer.go b/internal/buffer/buffer.go index e4af6be5..01fe167f 100644 --- a/internal/buffer/buffer.go +++ b/internal/buffer/buffer.go @@ -10,6 +10,7 @@ import ( "path/filepath" "strconv" "strings" + "sync" "time" "unicode/utf8" @@ -117,6 +118,7 @@ type Buffer struct { Highlighter *highlight.Highlighter // Modifications is the list of modified regions for syntax highlighting Modifications []Loc + HighlightLock sync.Mutex // Hash of the original buffer -- empty if fastdirty is on origHash [md5.Size]byte @@ -610,7 +612,9 @@ func (b *Buffer) UpdateRules() { } if b.Highlighter == nil || syntaxFile != "" { - b.Settings["filetype"] = b.SyntaxDef.FileType + if b.SyntaxDef != nil { + b.Settings["filetype"] = b.SyntaxDef.FileType + } } else { b.SyntaxDef = &highlight.EmptyDef } @@ -618,8 +622,11 @@ func (b *Buffer) UpdateRules() { if b.SyntaxDef != nil { b.Highlighter = highlight.NewHighlighter(b.SyntaxDef) if b.Settings["syntax"].(bool) { - b.Highlighter.HighlightStates(b) - b.Highlighter.HighlightMatches(b, 0, b.End().Y) + go func() { + b.Highlighter.HighlightStates(b) + b.Highlighter.HighlightMatches(b, 0, b.End().Y) + screen.DrawChan <- true + }() } } } diff --git a/internal/buffer/line_array.go b/internal/buffer/line_array.go index dcbf2e43..0aa69d7a 100644 --- a/internal/buffer/line_array.go +++ b/internal/buffer/line_array.go @@ -3,6 +3,7 @@ package buffer import ( "bufio" "io" + "sync" "unicode/utf8" "github.com/zyedidia/micro/pkg/highlight" @@ -38,6 +39,7 @@ type Line struct { state highlight.State match highlight.LineMatch rehighlight bool + lock sync.Mutex } const ( @@ -124,12 +126,22 @@ func NewLineArray(size uint64, endings FileFormat, reader io.Reader) *LineArray if err != nil { if err == io.EOF { - la.lines = Append(la.lines, Line{data[:], nil, nil, false}) + la.lines = Append(la.lines, Line{ + data: data[:], + state: nil, + match: nil, + rehighlight: false, + }) } // Last line was read break } else { - la.lines = Append(la.lines, Line{data[:dlen-1], nil, nil, false}) + la.lines = Append(la.lines, Line{ + data: data[:dlen-1], + state: nil, + match: nil, + rehighlight: false, + }) } n++ } @@ -155,9 +167,19 @@ func (la *LineArray) Bytes() []byte { // newlineBelow adds a newline below the given line number func (la *LineArray) newlineBelow(y int) { - la.lines = append(la.lines, Line{[]byte{' '}, nil, nil, false}) + la.lines = append(la.lines, Line{ + data: []byte{' '}, + state: nil, + match: nil, + rehighlight: false, + }) copy(la.lines[y+2:], la.lines[y+1:]) - la.lines[y+1] = Line{[]byte{}, la.lines[y].state, nil, false} + la.lines[y+1] = Line{ + data: []byte{}, + state: la.lines[y].state, + match: nil, + rehighlight: false, + } } // Inserts a byte array at a given location @@ -285,28 +307,40 @@ func (la *LineArray) LineBytes(n int) []byte { // State gets the highlight state for the given line number func (la *LineArray) State(lineN int) highlight.State { + la.lines[lineN].lock.Lock() + defer la.lines[lineN].lock.Unlock() return la.lines[lineN].state } // SetState sets the highlight state at the given line number func (la *LineArray) SetState(lineN int, s highlight.State) { + la.lines[lineN].lock.Lock() + defer la.lines[lineN].lock.Unlock() la.lines[lineN].state = s } // SetMatch sets the match at the given line number func (la *LineArray) SetMatch(lineN int, m highlight.LineMatch) { + la.lines[lineN].lock.Lock() + defer la.lines[lineN].lock.Unlock() la.lines[lineN].match = m } // Match retrieves the match for the given line number func (la *LineArray) Match(lineN int) highlight.LineMatch { + la.lines[lineN].lock.Lock() + defer la.lines[lineN].lock.Unlock() return la.lines[lineN].match } func (la *LineArray) Rehighlight(lineN int) bool { + la.lines[lineN].lock.Lock() + defer la.lines[lineN].lock.Unlock() return la.lines[lineN].rehighlight } func (la *LineArray) SetRehighlight(lineN int, on bool) { + la.lines[lineN].lock.Lock() + defer la.lines[lineN].lock.Unlock() la.lines[lineN].rehighlight = on }