Working by-line syntax highlighting
This commit is contained in:
parent
d1d55277f7
commit
ff039df5d0
2 changed files with 61 additions and 39 deletions
|
@ -6,6 +6,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -208,17 +209,24 @@ func GetRules(buf *Buffer) ([]SyntaxRule, string) {
|
||||||
|
|
||||||
// SyntaxMatches is an alias to a map from character numbers to styles,
|
// SyntaxMatches is an alias to a map from character numbers to styles,
|
||||||
// so map[3] represents the style of the third character
|
// so map[3] represents the style of the third character
|
||||||
type SyntaxMatches map[int]tcell.Style
|
type SyntaxMatches [][]tcell.Style
|
||||||
|
|
||||||
// Match takes a buffer and returns the syntax matches a map specifying how it should be syntax highlighted
|
// Match takes a buffer and returns the syntax matches a map specifying how it should be syntax highlighted
|
||||||
func Match(rules []SyntaxRule, buf *Buffer, v *View) SyntaxMatches {
|
func Match(v *View) SyntaxMatches {
|
||||||
m := make(SyntaxMatches)
|
buf := v.buf
|
||||||
|
rules := v.buf.rules
|
||||||
|
|
||||||
lineStart := v.updateLines[0]
|
viewStart := v.topline
|
||||||
lineEnd := v.updateLines[1] + 1
|
viewEnd := v.topline + v.height
|
||||||
if lineStart < 0 {
|
if viewEnd > len(buf.lines) {
|
||||||
// Don't need to update syntax highlighting
|
viewEnd = len(buf.lines)
|
||||||
return m
|
}
|
||||||
|
|
||||||
|
lines := buf.lines[viewStart:viewEnd]
|
||||||
|
matches := make(SyntaxMatches, len(lines))
|
||||||
|
|
||||||
|
for i, line := range lines {
|
||||||
|
matches[i] = make([]tcell.Style, len(line))
|
||||||
}
|
}
|
||||||
|
|
||||||
totalStart := v.topline - synLinesUp
|
totalStart := v.topline - synLinesUp
|
||||||
|
@ -230,35 +238,35 @@ func Match(rules []SyntaxRule, buf *Buffer, v *View) SyntaxMatches {
|
||||||
totalEnd = len(buf.lines)
|
totalEnd = len(buf.lines)
|
||||||
}
|
}
|
||||||
|
|
||||||
if lineEnd > len(buf.lines) {
|
|
||||||
lineEnd = len(buf.lines)
|
|
||||||
}
|
|
||||||
|
|
||||||
lines := buf.lines[lineStart:lineEnd]
|
|
||||||
str := strings.Join(buf.lines[totalStart:totalEnd], "\n")
|
str := strings.Join(buf.lines[totalStart:totalEnd], "\n")
|
||||||
startNum := v.cursor.loc + v.cursor.Distance(0, totalStart)
|
startNum := v.cursor.loc + v.cursor.Distance(0, totalStart)
|
||||||
toplineNum := v.cursor.loc + v.cursor.Distance(0, v.topline)
|
toplineNum := v.cursor.loc + v.cursor.Distance(0, v.topline)
|
||||||
|
|
||||||
for _, rule := range rules {
|
for _, rule := range rules {
|
||||||
if rule.startend && rule.regex.MatchString(str) {
|
if rule.startend {
|
||||||
|
if rule.regex.MatchString(str) {
|
||||||
indicies := rule.regex.FindAllStringIndex(str, -1)
|
indicies := rule.regex.FindAllStringIndex(str, -1)
|
||||||
for _, value := range indicies {
|
for _, value := range indicies {
|
||||||
value[0] += startNum
|
value[0] += startNum
|
||||||
value[1] += startNum
|
value[1] += startNum
|
||||||
for i := value[0]; i < value[1]; i++ {
|
for i := value[0]; i < value[1]; i++ {
|
||||||
|
colNum, lineNum := GetPos(i, buf)
|
||||||
|
v.m.Message(strconv.Itoa(lineNum) + ", " + strconv.Itoa(colNum))
|
||||||
if i >= toplineNum {
|
if i >= toplineNum {
|
||||||
m[i] = rule.style
|
if lineNum != -1 && colNum != -1 {
|
||||||
|
matches[lineNum][colNum] = rule.style
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for _, line := range lines {
|
for lineN, line := range lines {
|
||||||
if rule.regex.MatchString(line) {
|
if rule.regex.MatchString(line) {
|
||||||
indicies := rule.regex.FindAllStringIndex(str, -1)
|
indicies := rule.regex.FindAllStringIndex(line, -1)
|
||||||
for _, value := range indicies {
|
for _, value := range indicies {
|
||||||
value[0] += toplineNum
|
|
||||||
value[1] += toplineNum
|
|
||||||
for i := value[0]; i < value[1]; i++ {
|
for i := value[0]; i < value[1]; i++ {
|
||||||
m[i] = rule.style
|
matches[lineN][i] = rule.style
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,5 +274,22 @@ func Match(rules []SyntaxRule, buf *Buffer, v *View) SyntaxMatches {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return m
|
return matches
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPos returns an x, y position given a character location in the buffer
|
||||||
|
func GetPos(loc int, buf *Buffer) (int, int) {
|
||||||
|
charNum := 0
|
||||||
|
x, y := 0, 0
|
||||||
|
|
||||||
|
for i, line := range buf.lines {
|
||||||
|
if charNum+Count(line) > loc {
|
||||||
|
y = i
|
||||||
|
x = loc - charNum
|
||||||
|
return x, y
|
||||||
|
}
|
||||||
|
charNum += Count(line) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1, -1
|
||||||
}
|
}
|
||||||
|
|
21
src/view.go
21
src/view.go
|
@ -91,7 +91,7 @@ func NewViewWidthHeight(buf *Buffer, m *Messenger, w, h int) *View {
|
||||||
|
|
||||||
// Update the syntax highlighting for the entire buffer at the start
|
// Update the syntax highlighting for the entire buffer at the start
|
||||||
v.UpdateLines(v.topline, v.topline+v.height)
|
v.UpdateLines(v.topline, v.topline+v.height)
|
||||||
// v.matches = Match(v.buf.rules, v.buf, v)
|
v.matches = Match(v)
|
||||||
|
|
||||||
// Set mouseReleased to true because we assume the mouse is not being pressed when
|
// Set mouseReleased to true because we assume the mouse is not being pressed when
|
||||||
// the editor is opened
|
// the editor is opened
|
||||||
|
@ -407,12 +407,16 @@ func (v *View) HandleEvent(event tcell.Event) {
|
||||||
v.UpdateLines(v.topline, v.topline+v.height)
|
v.UpdateLines(v.topline, v.topline+v.height)
|
||||||
case tcell.KeyPgUp:
|
case tcell.KeyPgUp:
|
||||||
v.PageUp()
|
v.PageUp()
|
||||||
|
relocate = false
|
||||||
case tcell.KeyPgDn:
|
case tcell.KeyPgDn:
|
||||||
v.PageDown()
|
v.PageDown()
|
||||||
|
relocate = false
|
||||||
case tcell.KeyCtrlU:
|
case tcell.KeyCtrlU:
|
||||||
v.HalfPageUp()
|
v.HalfPageUp()
|
||||||
|
relocate = false
|
||||||
case tcell.KeyCtrlD:
|
case tcell.KeyCtrlD:
|
||||||
v.HalfPageDown()
|
v.HalfPageDown()
|
||||||
|
relocate = false
|
||||||
case tcell.KeyRune:
|
case tcell.KeyRune:
|
||||||
// Insert a character
|
// Insert a character
|
||||||
if v.cursor.HasSelection() {
|
if v.cursor.HasSelection() {
|
||||||
|
@ -479,12 +483,12 @@ func (v *View) HandleEvent(event tcell.Event) {
|
||||||
v.Relocate()
|
v.Relocate()
|
||||||
}
|
}
|
||||||
|
|
||||||
// v.matches = Match(v.buf.rules, v.buf, v)
|
v.matches = Match(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DisplayView renders the view to the screen
|
// DisplayView renders the view to the screen
|
||||||
func (v *View) DisplayView() {
|
func (v *View) DisplayView() {
|
||||||
matches := make(SyntaxMatches)
|
matches := make(SyntaxMatches, len(v.matches))
|
||||||
|
|
||||||
// The character number of the character in the top left of the screen
|
// The character number of the character in the top left of the screen
|
||||||
charNum := v.cursor.loc + v.cursor.Distance(0, v.topline)
|
charNum := v.cursor.loc + v.cursor.Distance(0, v.topline)
|
||||||
|
@ -528,17 +532,10 @@ func (v *View) DisplayView() {
|
||||||
|
|
||||||
// Write the line
|
// Write the line
|
||||||
tabchars := 0
|
tabchars := 0
|
||||||
for _, ch := range line {
|
for colN, ch := range line {
|
||||||
var lineStyle tcell.Style
|
var lineStyle tcell.Style
|
||||||
// Does the current character need to be syntax highlighted?
|
// Does the current character need to be syntax highlighted?
|
||||||
if st, ok := v.matches[charNum]; ok {
|
highlightStyle = v.matches[lineN][colN]
|
||||||
highlightStyle = st
|
|
||||||
} else if st, ok := v.lastMatches[charNum]; ok {
|
|
||||||
highlightStyle = st
|
|
||||||
} else {
|
|
||||||
highlightStyle = tcell.StyleDefault
|
|
||||||
}
|
|
||||||
matches[charNum] = highlightStyle
|
|
||||||
|
|
||||||
if v.cursor.HasSelection() &&
|
if v.cursor.HasSelection() &&
|
||||||
(charNum >= v.cursor.selectionStart && charNum <= v.cursor.selectionEnd ||
|
(charNum >= v.cursor.selectionStart && charNum <= v.cursor.selectionEnd ||
|
||||||
|
|
Loading…
Reference in a new issue