mirror of
https://github.com/zyedidia/micro
synced 2024-09-30 05:06:02 +00:00
Cache syntax highlighting rules
This commit is contained in:
parent
e2f25947cc
commit
a35af11924
|
@ -95,7 +95,7 @@ color brightyellow "\b(setup|loop)\b"
|
|||
color brightcyan "^[[:space:]]*#[[:space:]]*(define|include(_next)?|(un|ifn?)def|endif|el(if|se)|if|warning|error|pragma)"
|
||||
|
||||
##
|
||||
color brightmagenta "'([^'\]|(\\["'abfnrtv\\]))'" "'\\(([0-3]?[0-7]{1,2}))'" "'\\x[0-9A-Fa-f]{1,2}'"
|
||||
color brightmagenta "'([^'\\]|(\\["'abfnrtv\\]))'" "'\\(([0-3]?[0-7]{1,2}))'" "'\\x[0-9A-Fa-f]{1,2}'"
|
||||
|
||||
## GCC builtins
|
||||
color cyan "__attribute__[[:space:]]*\(\([^)]*\)\)" "__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
|
||||
|
|
|
@ -16,7 +16,7 @@ color brightblue "\b(split|sprintf|strtonum|sub|substr|tolower|toupper)\b"
|
|||
color brightblue "\b(mktime|strftime|systime)\b"
|
||||
color brightblue "\b(and|compl|lshift|or|rshift|xor)\b"
|
||||
color brightblue "\b(bindtextdomain|dcgettext|dcngettext)\b"
|
||||
color magenta "/.*[^\]/"
|
||||
color magenta "/.*[^\\]/"
|
||||
color yellow ""(\\.|[^"])*"|'(\\.|[^'])*'"
|
||||
color magenta "\\."
|
||||
color brightblack "(^|[[:space:]])#([^{].*)?$"
|
||||
|
|
|
@ -9,7 +9,7 @@ color statement "\b(for|if|while|do|else|case|default|switch)\b"
|
|||
color statement "\b(try|throw|catch|operator|new|delete)\b"
|
||||
color statement "\b(goto|continue|break|return)\b"
|
||||
color preproc "^[[:space:]]*#[[:space:]]*(define|include|(un|ifn?)def|endif|el(if|se)|if|warning|error)"
|
||||
color brightmagenta "'([^'\]|(\\["'abfnrtv\\]))'" "'\\(([0-3]?[0-7]{1,2}))'" "'\\x[0-9A-Fa-f]{1,2}'"
|
||||
color constant "'([^'\\]|(\\["'abfnrtv\\]))'" "'\\(([0-3]?[0-7]{1,2}))'" "'\\x[0-9A-Fa-f]{1,2}'"
|
||||
|
||||
##
|
||||
## GCC builtins
|
||||
|
|
|
@ -77,7 +77,7 @@ color constant "q"\{.*\}""
|
|||
color constant "q"\[.*\]""
|
||||
color constant "q"<.*>""
|
||||
color constant (s) "q"[^({[<"][^"]*$.*?^[^"]+""
|
||||
color constant "q"([^({[<"]).*\1""
|
||||
color constant "q"([^({[<"]).*""
|
||||
|
||||
### TokenString
|
||||
### True token strings require nesting, so, again, they can't be implemented accurately here.
|
||||
|
|
|
@ -27,7 +27,7 @@ type Buffer struct {
|
|||
lines []string
|
||||
|
||||
// Syntax highlighting rules
|
||||
rules string
|
||||
rules []SyntaxRule
|
||||
// File type of the buffer
|
||||
filetype string
|
||||
}
|
||||
|
|
|
@ -10,7 +10,17 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
var syntaxFiles map[[2]*regexp.Regexp][2]string
|
||||
type FileTypeRules struct {
|
||||
filetype string
|
||||
rules []SyntaxRule
|
||||
}
|
||||
|
||||
type SyntaxRule struct {
|
||||
regex *regexp.Regexp
|
||||
style tcell.Style
|
||||
}
|
||||
|
||||
var syntaxFiles map[[2]*regexp.Regexp]FileTypeRules
|
||||
|
||||
// LoadSyntaxFiles loads the syntax files from the default directory ~/.micro
|
||||
func LoadSyntaxFiles() {
|
||||
|
@ -35,7 +45,7 @@ func JoinRule(rule string) string {
|
|||
func LoadSyntaxFilesFromDir(dir string) {
|
||||
InitColorscheme()
|
||||
|
||||
syntaxFiles = make(map[[2]*regexp.Regexp][2]string)
|
||||
syntaxFiles = make(map[[2]*regexp.Regexp]FileTypeRules)
|
||||
files, _ := ioutil.ReadDir(dir)
|
||||
for _, f := range files {
|
||||
if filepath.Ext(f.Name()) == ".micro" {
|
||||
|
@ -49,12 +59,13 @@ func LoadSyntaxFilesFromDir(dir string) {
|
|||
|
||||
syntaxParser := regexp.MustCompile(`syntax "(.*?)"\s+"(.*)"+`)
|
||||
headerParser := regexp.MustCompile(`header "(.*)"`)
|
||||
ruleParser := regexp.MustCompile(`color (.*?)\s+(?:\((.*?)\)\s+)?"(.*)"`)
|
||||
|
||||
var syntaxRegex *regexp.Regexp
|
||||
var headerRegex *regexp.Regexp
|
||||
var filetype string
|
||||
var rules string
|
||||
for _, line := range lines {
|
||||
var rules []SyntaxRule
|
||||
for lineNum, line := range lines {
|
||||
if strings.TrimSpace(line) == "" ||
|
||||
strings.TrimSpace(line)[0] == '#' {
|
||||
// Ignore this line
|
||||
|
@ -66,8 +77,9 @@ func LoadSyntaxFilesFromDir(dir string) {
|
|||
if len(syntaxMatches) == 3 {
|
||||
if syntaxRegex != nil {
|
||||
regexes := [2]*regexp.Regexp{syntaxRegex, headerRegex}
|
||||
syntaxFiles[regexes] = [2]string{rules, filetype}
|
||||
syntaxFiles[regexes] = FileTypeRules{filetype, rules}
|
||||
}
|
||||
rules = rules[:0]
|
||||
|
||||
filetype = string(syntaxMatches[1])
|
||||
extensions := JoinRule(string(syntaxMatches[2]))
|
||||
|
@ -96,12 +108,34 @@ func LoadSyntaxFilesFromDir(dir string) {
|
|||
continue
|
||||
}
|
||||
} else {
|
||||
rules += line + "\n"
|
||||
if ruleParser.MatchString(line) {
|
||||
submatch := ruleParser.FindSubmatch([]byte(line))
|
||||
color := string(submatch[1])
|
||||
var regexStr string
|
||||
if len(submatch) == 4 {
|
||||
regexStr = "(?m" + string(submatch[2]) + ")" + JoinRule(string(submatch[3]))
|
||||
} else if len(submatch) == 3 {
|
||||
regexStr = "(?m)" + JoinRule(string(submatch[2]))
|
||||
}
|
||||
regex, err := regexp.Compile(regexStr)
|
||||
if err != nil {
|
||||
fmt.Println(f.Name(), lineNum, err)
|
||||
continue
|
||||
}
|
||||
|
||||
st := tcell.StyleDefault
|
||||
if _, ok := colorscheme[color]; ok {
|
||||
st = colorscheme[color]
|
||||
} else {
|
||||
st = StringToStyle(color)
|
||||
}
|
||||
rules = append(rules, SyntaxRule{regex, st})
|
||||
}
|
||||
}
|
||||
}
|
||||
if syntaxRegex != nil {
|
||||
regexes := [2]*regexp.Regexp{syntaxRegex, headerRegex}
|
||||
syntaxFiles[regexes] = [2]string{rules, filetype}
|
||||
syntaxFiles[regexes] = FileTypeRules{filetype, rules}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -109,22 +143,22 @@ func LoadSyntaxFilesFromDir(dir string) {
|
|||
|
||||
// GetRules finds the syntax rules that should be used for the buffer
|
||||
// and returns them. It also returns the filetype of the file
|
||||
func GetRules(buf *Buffer) (string, string) {
|
||||
func GetRules(buf *Buffer) ([]SyntaxRule, string) {
|
||||
for r := range syntaxFiles {
|
||||
if r[0] != nil && r[0].MatchString(buf.path) {
|
||||
return syntaxFiles[r][0], syntaxFiles[r][1]
|
||||
return syntaxFiles[r].rules, syntaxFiles[r].filetype
|
||||
} else if r[1] != nil && r[1].MatchString(buf.lines[0]) {
|
||||
return syntaxFiles[r][0], syntaxFiles[r][1]
|
||||
return syntaxFiles[r].rules, syntaxFiles[r].filetype
|
||||
}
|
||||
}
|
||||
return "", "Unknown"
|
||||
return nil, "Unknown"
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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 {
|
||||
func Match(rules []SyntaxRule, buf *Buffer, v *View) map[int]tcell.Style {
|
||||
start := v.topline - synLinesUp
|
||||
end := v.topline + v.height + synLinesDown
|
||||
if start < 0 {
|
||||
|
@ -137,42 +171,16 @@ func Match(rules string, buf *Buffer, v *View) map[int]tcell.Style {
|
|||
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+(?:\((.*?)\)\s+)?"(.*)"`)
|
||||
for _, line := range lines {
|
||||
if strings.TrimSpace(line) == "" {
|
||||
// Ignore this line
|
||||
continue
|
||||
}
|
||||
submatch := parser.FindSubmatch([]byte(line))
|
||||
color := string(submatch[1])
|
||||
var regexStr string
|
||||
if len(submatch) == 4 {
|
||||
regexStr = "(?m" + string(submatch[2]) + ")" + JoinRule(string(submatch[3]))
|
||||
} else if len(submatch) == 3 {
|
||||
regexStr = "(?m)" + JoinRule(string(submatch[2]))
|
||||
}
|
||||
regex, err := regexp.Compile(regexStr)
|
||||
if err != nil {
|
||||
// Error with the regex!
|
||||
continue
|
||||
}
|
||||
st := tcell.StyleDefault
|
||||
if _, ok := colorscheme[color]; ok {
|
||||
st = colorscheme[color]
|
||||
} else {
|
||||
st = StringToStyle(color)
|
||||
}
|
||||
|
||||
if regex.MatchString(str) {
|
||||
indicies := regex.FindAllStringIndex(str, -1)
|
||||
for _, rule := range rules {
|
||||
if rule.regex.MatchString(str) {
|
||||
indicies := rule.regex.FindAllStringIndex(str, -1)
|
||||
for _, value := range indicies {
|
||||
value[0] += startNum
|
||||
value[1] += startNum
|
||||
for i := value[0]; i < value[1]; i++ {
|
||||
if i >= toplineNum {
|
||||
m[i] = st
|
||||
m[i] = rule.style
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue