syntax highlighting configs are back... make it work again!

This commit is contained in:
Felix Angell 2021-01-10 21:59:31 +00:00
parent 68c3a94c12
commit 88696f37c9
3 changed files with 159 additions and 133 deletions

View File

@ -15,6 +15,7 @@ import (
"math" "math"
"os" "os"
"path" "path"
"regexp"
"runtime" "runtime"
"strings" "strings"
"time" "time"
@ -1205,12 +1206,15 @@ type syntaxRuneInfo struct {
// dimensions of the last character we rendered // dimensions of the last character we rendered
var lastCharW, lastCharH int var lastCharW, lastCharH int
func lexFindMatches(matches *map[int]syntaxRuneInfo, currLine string, toMatch map[string]bool, bg uint32, fg uint32) { func lexFindMatches(matches *map[int]syntaxRuneInfo, currLine string, toMatch []string, bg uint32, fg uint32) {
lexer := lex.New(currLine) lexer := lex.New(currLine)
tokenStream := lexer.Tokenize() tokenStream := lexer.Tokenize()
for _, tok := range tokenStream { for _, tok := range tokenStream {
if _, ok := toMatch[tok.Lexeme]; ok { // hashset for match.
(*matches)[tok.Start] = syntaxRuneInfo{bg, fg, len(tok.Lexeme)} for _, ms := range toMatch {
if strings.Compare(ms, tok.Lexeme) == 0 {
(*matches)[tok.Start] = syntaxRuneInfo{bg, fg, len(tok.Lexeme)}
}
} }
} }
} }
@ -1267,9 +1271,11 @@ func (b *Buffer) syntaxHighlightLine(currLine string) map[int]syntaxRuneInfo {
for syntaxIndex, syntax := range subjects { for syntaxIndex, syntax := range subjects {
if syntax.Pattern != "" { if syntax.Pattern != "" {
for charIndex := 0; charIndex < len(currLine); charIndex++ { for charIndex := 0; charIndex < len(currLine); charIndex++ {
a := string(currLine[charIndex:]) a := currLine[charIndex:]
matched := syntax.CompiledPattern.FindStringIndex(a) patt := lazyCompileRegExPattern(syntax.Pattern)
matched := patt.FindStringIndex(a)
if matched != nil { if matched != nil {
if _, ok := matches[charIndex]; !ok { if _, ok := matches[charIndex]; !ok {
matchedStrLen := matched[1] - matched[0] matchedStrLen := matched[1] - matched[0]
@ -1288,7 +1294,7 @@ func (b *Buffer) syntaxHighlightLine(currLine string) map[int]syntaxRuneInfo {
} }
} else { } else {
colouring := colours[syntaxIndex] colouring := colours[syntaxIndex]
lexFindMatches(&matches, currLine, syntax.MatchList, colouring.bg, colouring.fg) lexFindMatches(&matches, currLine, syntax.Match, colouring.bg, colouring.fg)
} }
} }
@ -1300,6 +1306,21 @@ func (b *Buffer) syntaxHighlightLine(currLine string) map[int]syntaxRuneInfo {
return matches return matches
} }
var patts = map[string]*regexp.Regexp{}
// FIXME
func lazyCompileRegExPattern(pattern string) *regexp.Regexp {
if cachedPattern, ok := patts[pattern]; ok {
return cachedPattern
}
compiledPattern, err := regexp.Compile(pattern)
if err != nil {
panic(err)
}
patts[pattern] = compiledPattern
return compiledPattern
}
func (b *Buffer) renderAt(ctx *strife.Renderer, rx int, ry int) { func (b *Buffer) renderAt(ctx *strife.Renderer, rx int, ry int) {
x, y := b.GetPos() x, y := b.GetPos()
w, h := b.GetSize() w, h := b.GetSize()

View File

@ -3,26 +3,36 @@ package cfg
import ( import (
"errors" "errors"
"log" "log"
"regexp"
"strconv" "strconv"
"strings"
) )
type PhiEditorConfig struct { type PhiEditorConfig struct {
Editor *EditorConfig `toml:"editor"` Editor *EditorConfig `toml:"editor"`
Cursor *CursorConfig `toml:"cursor"` Cursor *CursorConfig `toml:"cursor"`
Render *RenderConfig `toml:"render"` Render *RenderConfig `toml:"render"`
Theme *ThemeConfig `toml:"theme"` Theme *ThemeConfig `toml:"theme"`
Associations map[string]FileAssociations `toml:"file_associations"` Associations map[string]FileAssociations `toml:"file_associations"`
Commands map[string]Command `toml:"commands"` Commands map[string]Command `toml:"commands"`
LanguageAssociations map[string]*LanguageSyntaxConfig
associations map[string]*LanguageSyntaxConfig
} }
// GetSyntaxConfig returns a pointer to the parsed // GetSyntaxConfig returns a pointer to the parsed
// syntax language file for the given file extension // syntax language file for the given file extension
// e.g. what syntax def we need for a .cpp file or a .h file // e.g. what syntax def we need for a .cpp file or a .h file
func (p *PhiEditorConfig) GetSyntaxConfig(ext string) (*LanguageSyntaxConfig, error) { func (p *PhiEditorConfig) GetSyntaxConfig(ext string) (*LanguageSyntaxConfig, error) {
if val, ok := p.associations[ext]; ok { // fixme relationship is wrong way round so for now we have to iterate over keys.. very st upid
var theKey string
for key, assoc := range p.Associations {
for _, assocExt := range assoc.Extensions {
if strings.Compare(ext, assocExt) == 0 {
theKey = key
}
}
}
if val, ok := p.LanguageAssociations[theKey]; ok {
return val, nil return val, nil
} }
return nil, errors.New("no language for extension '" + ext + "'") return nil, errors.New("no language for extension '" + ext + "'")
@ -37,9 +47,6 @@ type SyntaxCriteria struct {
Background uint32 `toml:"background"` Background uint32 `toml:"background"`
Match []string `toml:"match"` Match []string `toml:"match"`
Pattern string `toml:"pattern"` Pattern string `toml:"pattern"`
CompiledPattern *regexp.Regexp
MatchList map[string]bool
} }
type Command struct { type Command struct {
@ -196,8 +203,11 @@ func NewDefaultConfig() *PhiEditorConfig {
"md": {Extensions: []string{".md", ".markdown"}}, "md": {Extensions: []string{".md", ".markdown"}},
"toml": {Extensions: []string{".toml"}}, "toml": {Extensions: []string{".toml"}},
}, },
LanguageAssociations: map[string]*LanguageSyntaxConfig{
// TODO syntax defaults "go": GoConfig(),
associations: map[string]*LanguageSyntaxConfig{}, "c": CConfig(),
"md": MarkdownConfig(),
"toml": TOMLConfig(),
},
} }
} }

View File

@ -4,119 +4,114 @@ type LanguageSyntaxConfig struct {
Syntax map[string]*SyntaxCriteria `toml:"syntax"` Syntax map[string]*SyntaxCriteria `toml:"syntax"`
} }
func NewLanguageSyntaxConfig() *LanguageSyntaxConfig { func MarkdownConfig() *LanguageSyntaxConfig {
return &LanguageSyntaxConfig{Syntax: map[string]*SyntaxCriteria{}} return &LanguageSyntaxConfig{Syntax: map[string]*SyntaxCriteria{
"header": {
Foreground: 0xff00ff,
Pattern: "(?m)^#{1,6}.*",
},
}}
} }
var DefaultSyntaxSet = map[string]string{} func TOMLConfig() *LanguageSyntaxConfig {
return &LanguageSyntaxConfig{Syntax: map[string]*SyntaxCriteria{
func RegisterSyntax(name string, syntaxTomlDef string) { "declaration": {
DefaultSyntaxSet[name] = syntaxTomlDef Foreground: 0xf8f273,
Pattern: `(\[)(.*)(\])`,
},
"identifier": {
Foreground: 0xf0a400,
Pattern: `\b([a-z]|[A-Z])+(_|([a-z]|[A-Z])+)*\b`,
},
"symbol": {
Match: []string{"="},
Foreground: 0xf8f273,
},
}}
} }
func init() { func CConfig() *LanguageSyntaxConfig {
// TOML return &LanguageSyntaxConfig{Syntax: map[string]*SyntaxCriteria{
RegisterSyntax("toml", `[syntax.toml] "type": {
[syntax.declaration] Foreground: 0xf8f273,
foreground = 0xf8f273 Match: []string{
pattern = '(\[)(.*)(\])' "int", "char", "bool", "float", "double", "void",
"uint8_t", "uint16_t", "uint32_t", "uint64_t",
[syntax.identifier] "int8_t", "int16_t", "int32_t", "int64_t", "const",
foreground = 0xf0a400 },
pattern = '\b([a-z]|[A-Z])+(_|([a-z]|[A-Z])+)*\b' },
"keyword": {
[syntax.symbol] Foreground: 0xf0a400,
match = ["="] Match: []string{
foreground = 0xf8f273 "for", "break", "if", "else", "continue", "return",
`) "goto", "extern", "const", "typedef",
"struct", "union", "register", "enum",
// C LANGUAGE SYNTAX HIGHLIGHTING "do", "static", "sizeof", "volatile", "unsigned",
"switch", "case", "default",
RegisterSyntax("c", `[syntax.c] },
[syntax.type] },
foreground = 0xf8f273 "string_literal": {
match = [ Foreground: 0x4b79fc,
"int", "char", "bool", "float", "double", "void", Pattern: `\"([^\\\"]|\\.)*\"`,
"uint8_t", "uint16_t", "uint32_t", "uint64_t", },
"int8_t", "int16_t", "int32_t", "int64_t", "const" "directive": {
] Foreground: 0xf0a400,
Pattern: `^\\s*#\\s*include\\s+(?:<[^>]*>|\"[^\"]*\")\\s*`,
[syntax.keyword] },
foreground = 0xf0a400 "symbol": {
match = [ Foreground: 0xf0a400,
"for", "break", "if", "else", "continue", "return", Match: []string{
"goto", "extern", "const", "typedef", "+=", "-=", "*=", "/=", ">>", "<<", "==", "!=",
"struct", "union", "register", "enum", ">=", "<=", "||", "&&",
"do", "static", "sizeof", "volatile", "unsigned", "=", ":", ";", "*", "&", "+", "-", "/", "%",
"switch", "case", "default" "^", "#", "!", "@", "<", ">", ".", ",",
] },
},
[syntax.string_literal] "comment": {
foreground = 0x4b79fc Foreground: 0x4b79fc,
pattern = "\"([^\\\"]|\\.)*\"" Pattern: `//.*`,
},
[syntax.directive] }}
foreground = 0xf0a400 }
pattern = "^\\s*#\\s*include\\s+(?:<[^>]*>|\"[^\"]*\")\\s*"
func GoConfig() *LanguageSyntaxConfig {
[syntax.symbol] return &LanguageSyntaxConfig{Syntax: map[string]*SyntaxCriteria{
foreground = 0xf0a400 "keyword": {
match = [ Foreground: 0xf0a400,
"+=", "-=", "*=", "/=", ">>", "<<", "==", "!=", Match: []string{
">=", "<=", "||", "&&", "break", "default", "func", "interface", "select",
"=", ":", ";", "*", "&", "+", "-", "/", "%", "case", "defer", "go", "map", "struct",
"^", "#", "!", "@", "<", ">", ".", "," "chan", "else", "goto", "package", "switch",
] "const", "fallthrough", "if", "range", "type",
"continue", "for", "import", "return", "var",
[syntax.comment] },
foreground = 0x4b79fc },
pattern = '//.*'`) "type": {
Foreground: 0xf8f273,
// GO LANGUAGE SYNTAX HIGHLIGHTING Match: []string{
"int", "string", "uint", "rune",
RegisterSyntax("go", `[syntax.go] "int8", "int16", "int32", "int64",
[syntax.keyword] "uint8", "uint16", "uint32", "uint64",
foreground = 0xf0a400 "byte", "float32", "float64", "complex64",
match = [ "complex128", "uintptr",
"break", "default", "func", "interface", "select", },
"case", "defer", "go", "map", "struct", },
"chan", "else", "goto", "package", "switch", "comment": {
"const", "fallthrough", "if", "range", "type", Foreground: 0x4b79fc,
"continue", "for", "import", "return", "var", Pattern: `//.*`,
] },
"string_literal": {
[syntax.type] Foreground: 0x4b79fc,
foreground = 0xf8f273 Pattern: `\"([^\\\"]|\\.)*\"`,
match = [ },
"int", "string", "uint", "rune", "symbol": {
"int8", "int16", "int32", "int64", Foreground: 0xf0a400,
"uint8", "uint16", "uint32", "uint64", Match: []string{
"byte", "float32", "float64", "complex64", "+=", "-=", "*=", "/=", ">>", "<<", "==", "!=", ":=",
"complex128", "uintptr", ">=", "<=", "||", "&&",
] "=", ":", ";", "*", "&", "+", "-", "/", "%",
"^", "#", "!", "@", "<", ">", ".", ",",
[syntax.comment] },
foreground = 0x4b79fc },
pattern = '//.*' }}
[syntax.string_literal]
foreground = 0x4b79fc
pattern = "\"([^\\\"]|\\.)*\""
[syntax.symbol]
foreground = 0xf0a400
match = [
"+=", "-=", "*=", "/=", ">>", "<<", "==", "!=", ":=",
">=", "<=", "||", "&&",
"=", ":", ";", "*", "&", "+", "-", "/", "%",
"^", "#", "!", "@", "<", ">", ".", ","
]`)
RegisterSyntax("md", `[syntax.md]
[syntax.header]
foreground = 0xff00ff
pattern = '(?m)^#{1,6}.*'
`)
// your syntax here!
} }