From d429dc3df2c99d1810542ee94a54cd36a9c1e6a2 Mon Sep 17 00:00:00 2001 From: Zachary Yedidia Date: Mon, 21 Mar 2016 12:07:48 -0400 Subject: [PATCH] Major optimization for syntax highlighting --- highlighter.go | 38 ++++++++++++++++++++++++++++---------- micro.go | 5 ++++- view.go | 9 +++++---- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/highlighter.go b/highlighter.go index 103a78ef..381b3510 100644 --- a/highlighter.go +++ b/highlighter.go @@ -121,18 +121,25 @@ func GetRules(buf *Buffer) (string, string) { // Match takes a buffer and returns a map specifying how it should be syntax highlighted // The map is from character numbers to styles, so map[3] represents the style change // at the third character in the buffer -func Match(rules string, buf *Buffer) map[int]tcell.Style { - // rules := strings.TrimSpace(GetRules(buf)) - str := buf.text +// Note that this map only stores changes in styles, not each character's style +func Match(rules string, buf *Buffer, v *View) map[int]tcell.Style { + start := v.topline - synLinesUp + end := v.topline + v.height + synLinesDown + if start < 0 { + start = 0 + } + if end > len(buf.lines) { + end = len(buf.lines) + } + str := strings.Join(buf.lines[start:end], "\n") + startNum := v.cursor.loc + v.cursor.Distance(0, start) + toplineNum := v.cursor.loc + v.cursor.Distance(0, v.topline) lines := strings.Split(rules, "\n") m := make(map[int]tcell.Style) parser := regexp.MustCompile(`color (.*?)\s+"(.*)"`) for _, line := range lines { - if strings.TrimSpace(line) == "" || - strings.TrimSpace(line)[0] == '#' || - strings.HasPrefix(line, "syntax") || - strings.HasPrefix(line, "header") { + if strings.TrimSpace(line) == "" { // Ignore this line continue } @@ -148,14 +155,25 @@ func Match(rules string, buf *Buffer) map[int]tcell.Style { if regex.MatchString(str) { indicies := regex.FindAllStringIndex(str, -1) for _, value := range indicies { + value[0] += startNum + value[1] += startNum for i := value[0] + 1; i < value[1]; i++ { if _, exists := m[i]; exists { delete(m, i) } } - m[value[0]] = st - if _, exists := m[value[1]]; !exists { - m[value[1]] = tcell.StyleDefault + + if value[0] < toplineNum && value[1] > toplineNum { + m[toplineNum] = st + } + + if value[0] >= toplineNum { + m[value[0]] = st + } + if value[1] >= toplineNum { + if _, exists := m[value[1]]; !exists { + m[value[1]] = tcell.StyleDefault + } } } } diff --git a/micro.go b/micro.go index 0c62f6f0..05ae4746 100644 --- a/micro.go +++ b/micro.go @@ -10,7 +10,9 @@ import ( ) const ( - tabSize = 4 + tabSize = 4 + synLinesUp = 100 + synLinesDown = 100 ) func main() { @@ -71,6 +73,7 @@ func main() { redraw := 2 for { if redraw == 2 { + v.matches = Match(v.buf.rules, v.buf, v) s.Clear() v.Display() v.cursor.Display() diff --git a/view.go b/view.go index 94b28753..e608f1fc 100644 --- a/view.go +++ b/view.go @@ -23,6 +23,9 @@ type View struct { mouseReleased bool + // Syntax highlighting matches + matches map[int]tcell.Style + s tcell.Screen } @@ -301,8 +304,6 @@ func (v *View) Display() { charNum := v.cursor.loc + v.cursor.Distance(0, v.topline) - matches := Match(v.buf.rules, v.buf) - // Convert the length of buffer to a string, and get the length of the string // We are going to have to offset by that amount maxLineLength := len(strconv.Itoa(len(v.buf.lines))) @@ -338,7 +339,7 @@ func (v *View) Display() { tabchars := 0 for _, ch := range line { var lineStyle tcell.Style - st, ok := matches[charNum] + st, ok := v.matches[charNum] if ok { highlightStyle = st } @@ -365,7 +366,7 @@ func (v *View) Display() { x++ } x = 0 - st, ok := matches[charNum] + st, ok := v.matches[charNum] if ok { highlightStyle = st }