From 88696f37c9eb57a68234808d2aca86c4024c5b64 Mon Sep 17 00:00:00 2001 From: Felix Angell Date: Sun, 10 Jan 2021 21:59:31 +0000 Subject: [PATCH] syntax highlighting configs are back... make it work again! --- internal/buff/buffer.go | 33 ++++-- internal/cfg/config.go | 42 +++++--- internal/cfg/syntax.go | 217 ++++++++++++++++++++-------------------- 3 files changed, 159 insertions(+), 133 deletions(-) diff --git a/internal/buff/buffer.go b/internal/buff/buffer.go index 61de7cf..ca26048 100644 --- a/internal/buff/buffer.go +++ b/internal/buff/buffer.go @@ -15,6 +15,7 @@ import ( "math" "os" "path" + "regexp" "runtime" "strings" "time" @@ -1205,12 +1206,15 @@ type syntaxRuneInfo struct { // dimensions of the last character we rendered 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) tokenStream := lexer.Tokenize() for _, tok := range tokenStream { - if _, ok := toMatch[tok.Lexeme]; ok { - (*matches)[tok.Start] = syntaxRuneInfo{bg, fg, len(tok.Lexeme)} + // hashset for match. + 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 { if syntax.Pattern != "" { 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 _, ok := matches[charIndex]; !ok { matchedStrLen := matched[1] - matched[0] @@ -1288,7 +1294,7 @@ func (b *Buffer) syntaxHighlightLine(currLine string) map[int]syntaxRuneInfo { } } else { 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 } +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) { x, y := b.GetPos() w, h := b.GetSize() diff --git a/internal/cfg/config.go b/internal/cfg/config.go index 61f2906..822e3cc 100644 --- a/internal/cfg/config.go +++ b/internal/cfg/config.go @@ -3,26 +3,36 @@ package cfg import ( "errors" "log" - "regexp" "strconv" + "strings" ) type PhiEditorConfig struct { - Editor *EditorConfig `toml:"editor"` - Cursor *CursorConfig `toml:"cursor"` - Render *RenderConfig `toml:"render"` - Theme *ThemeConfig `toml:"theme"` - Associations map[string]FileAssociations `toml:"file_associations"` - Commands map[string]Command `toml:"commands"` - - associations map[string]*LanguageSyntaxConfig + Editor *EditorConfig `toml:"editor"` + Cursor *CursorConfig `toml:"cursor"` + Render *RenderConfig `toml:"render"` + Theme *ThemeConfig `toml:"theme"` + Associations map[string]FileAssociations `toml:"file_associations"` + Commands map[string]Command `toml:"commands"` + LanguageAssociations map[string]*LanguageSyntaxConfig } // GetSyntaxConfig returns a pointer to the parsed // syntax language file for the given file extension // e.g. what syntax def we need for a .cpp file or a .h file 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 nil, errors.New("no language for extension '" + ext + "'") @@ -37,9 +47,6 @@ type SyntaxCriteria struct { Background uint32 `toml:"background"` Match []string `toml:"match"` Pattern string `toml:"pattern"` - - CompiledPattern *regexp.Regexp - MatchList map[string]bool } type Command struct { @@ -196,8 +203,11 @@ func NewDefaultConfig() *PhiEditorConfig { "md": {Extensions: []string{".md", ".markdown"}}, "toml": {Extensions: []string{".toml"}}, }, - - // TODO syntax defaults - associations: map[string]*LanguageSyntaxConfig{}, + LanguageAssociations: map[string]*LanguageSyntaxConfig{ + "go": GoConfig(), + "c": CConfig(), + "md": MarkdownConfig(), + "toml": TOMLConfig(), + }, } } diff --git a/internal/cfg/syntax.go b/internal/cfg/syntax.go index 8929ab7..f8ca867 100644 --- a/internal/cfg/syntax.go +++ b/internal/cfg/syntax.go @@ -4,119 +4,114 @@ type LanguageSyntaxConfig struct { Syntax map[string]*SyntaxCriteria `toml:"syntax"` } -func NewLanguageSyntaxConfig() *LanguageSyntaxConfig { - return &LanguageSyntaxConfig{Syntax: map[string]*SyntaxCriteria{}} +func MarkdownConfig() *LanguageSyntaxConfig { + return &LanguageSyntaxConfig{Syntax: map[string]*SyntaxCriteria{ + "header": { + Foreground: 0xff00ff, + Pattern: "(?m)^#{1,6}.*", + }, + }} } -var DefaultSyntaxSet = map[string]string{} - -func RegisterSyntax(name string, syntaxTomlDef string) { - DefaultSyntaxSet[name] = syntaxTomlDef +func TOMLConfig() *LanguageSyntaxConfig { + return &LanguageSyntaxConfig{Syntax: map[string]*SyntaxCriteria{ + "declaration": { + Foreground: 0xf8f273, + Pattern: `(\[)(.*)(\])`, + }, + "identifier": { + Foreground: 0xf0a400, + Pattern: `\b([a-z]|[A-Z])+(_|([a-z]|[A-Z])+)*\b`, + }, + "symbol": { + Match: []string{"="}, + Foreground: 0xf8f273, + }, + }} } -func init() { - // TOML - RegisterSyntax("toml", `[syntax.toml] -[syntax.declaration] -foreground = 0xf8f273 -pattern = '(\[)(.*)(\])' - -[syntax.identifier] -foreground = 0xf0a400 -pattern = '\b([a-z]|[A-Z])+(_|([a-z]|[A-Z])+)*\b' - -[syntax.symbol] -match = ["="] -foreground = 0xf8f273 -`) - - // C LANGUAGE SYNTAX HIGHLIGHTING - - RegisterSyntax("c", `[syntax.c] -[syntax.type] -foreground = 0xf8f273 -match = [ - "int", "char", "bool", "float", "double", "void", - "uint8_t", "uint16_t", "uint32_t", "uint64_t", - "int8_t", "int16_t", "int32_t", "int64_t", "const" -] - -[syntax.keyword] -foreground = 0xf0a400 -match = [ - "for", "break", "if", "else", "continue", "return", - "goto", "extern", "const", "typedef", - "struct", "union", "register", "enum", - "do", "static", "sizeof", "volatile", "unsigned", - "switch", "case", "default" -] - -[syntax.string_literal] -foreground = 0x4b79fc -pattern = "\"([^\\\"]|\\.)*\"" - -[syntax.directive] -foreground = 0xf0a400 -pattern = "^\\s*#\\s*include\\s+(?:<[^>]*>|\"[^\"]*\")\\s*" - -[syntax.symbol] -foreground = 0xf0a400 -match = [ - "+=", "-=", "*=", "/=", ">>", "<<", "==", "!=", - ">=", "<=", "||", "&&", - "=", ":", ";", "*", "&", "+", "-", "/", "%", - "^", "#", "!", "@", "<", ">", ".", "," -] - -[syntax.comment] -foreground = 0x4b79fc -pattern = '//.*'`) - - // GO LANGUAGE SYNTAX HIGHLIGHTING - - RegisterSyntax("go", `[syntax.go] -[syntax.keyword] -foreground = 0xf0a400 -match = [ - "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.type] -foreground = 0xf8f273 -match = [ - "int", "string", "uint", "rune", - "int8", "int16", "int32", "int64", - "uint8", "uint16", "uint32", "uint64", - "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! +func CConfig() *LanguageSyntaxConfig { + return &LanguageSyntaxConfig{Syntax: map[string]*SyntaxCriteria{ + "type": { + Foreground: 0xf8f273, + Match: []string{ + "int", "char", "bool", "float", "double", "void", + "uint8_t", "uint16_t", "uint32_t", "uint64_t", + "int8_t", "int16_t", "int32_t", "int64_t", "const", + }, + }, + "keyword": { + Foreground: 0xf0a400, + Match: []string{ + "for", "break", "if", "else", "continue", "return", + "goto", "extern", "const", "typedef", + "struct", "union", "register", "enum", + "do", "static", "sizeof", "volatile", "unsigned", + "switch", "case", "default", + }, + }, + "string_literal": { + Foreground: 0x4b79fc, + Pattern: `\"([^\\\"]|\\.)*\"`, + }, + "directive": { + Foreground: 0xf0a400, + Pattern: `^\\s*#\\s*include\\s+(?:<[^>]*>|\"[^\"]*\")\\s*`, + }, + "symbol": { + Foreground: 0xf0a400, + Match: []string{ + "+=", "-=", "*=", "/=", ">>", "<<", "==", "!=", + ">=", "<=", "||", "&&", + "=", ":", ";", "*", "&", "+", "-", "/", "%", + "^", "#", "!", "@", "<", ">", ".", ",", + }, + }, + "comment": { + Foreground: 0x4b79fc, + Pattern: `//.*`, + }, + }} +} + +func GoConfig() *LanguageSyntaxConfig { + return &LanguageSyntaxConfig{Syntax: map[string]*SyntaxCriteria{ + "keyword": { + 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", + }, + }, + "type": { + Foreground: 0xf8f273, + Match: []string{ + "int", "string", "uint", "rune", + "int8", "int16", "int32", "int64", + "uint8", "uint16", "uint32", "uint64", + "byte", "float32", "float64", "complex64", + "complex128", "uintptr", + }, + }, + "comment": { + Foreground: 0x4b79fc, + Pattern: `//.*`, + }, + "string_literal": { + Foreground: 0x4b79fc, + Pattern: `\"([^\\\"]|\\.)*\"`, + }, + "symbol": { + Foreground: 0xf0a400, + Match: []string{ + "+=", "-=", "*=", "/=", ">>", "<<", "==", "!=", ":=", + ">=", "<=", "||", "&&", + "=", ":", ";", "*", "&", "+", "-", "/", "%", + "^", "#", "!", "@", "<", ">", ".", ",", + }, + }, + }} }