Files
typer/src/highlighting.go
T

110 lines
2.4 KiB
Go

package main
import (
"log"
"os"
"path/filepath"
"regexp"
"gopkg.in/yaml.v3"
)
type SyntaxRule struct {
Type string `yaml:"type"`
Regex string `yaml:"regex"`
Multiline bool `yaml:"multiline"`
}
type Syntax struct {
Filetype string `yaml:"filetype"`
Filenames string `yaml:"filenames"`
Rules []SyntaxRule `yaml:"rules"`
}
type ParsedSyntax struct {
StartIndex int
EndIndex int
Type string
}
var AvailableSyntaxes map[string]Syntax = make(map[string]Syntax)
func ReadSyntaxHighlighters() {
// Get syntax directory path
syntaxDirPath := GetConfigPath("syntax")
// Ensure directory exists at path
if stat, err := os.Stat(syntaxDirPath); syntaxDirPath == "" || err != nil || !stat.IsDir() {
return
}
// Get directory entries
entries, err := os.ReadDir(syntaxDirPath)
if err != nil {
log.Fatalf("Could not read syntax directory: %s", err)
}
// Read entries in directory
for _, entry := range entries {
entryPath := filepath.Join(syntaxDirPath, entry.Name())
data, err := os.ReadFile(entryPath)
if err != nil {
log.Fatalf("Could not read syntax file (%s): %s", entryPath, err)
}
syntax := Syntax{}
err = yaml.Unmarshal(data, &syntax)
if err != nil {
log.Fatalf("Could not read syntax file (%s): %s", entryPath, err)
}
if _, ok := AvailableSyntaxes[syntax.Filetype]; !ok {
AvailableSyntaxes[syntax.Filetype] = syntax
}
}
}
func HighlightString(s string, filetype string) (parsedSyntaxes []ParsedSyntax, err error) {
// Get syntax for filetype
syntax, ok := AvailableSyntaxes[filetype]
if !ok {
return nil, nil
}
for _, rule := range syntax.Rules {
regex := rule.Regex
if rule.Multiline {
regex = "(?m)" + rule.Regex
}
r, err := regexp.Compile(regex)
if err != nil {
return nil, err
}
matches := r.FindAllStringIndex(s, -1)
for _, match := range matches {
skip := false
for _, parsedSyntax := range parsedSyntaxes {
if (match[0] >= parsedSyntax.StartIndex && match[0] < parsedSyntax.EndIndex) || (match[1] >= parsedSyntax.StartIndex && match[1] < parsedSyntax.EndIndex) {
skip = true
}
}
if skip {
continue
}
parsedSyntax := ParsedSyntax{
StartIndex: match[0],
EndIndex: match[1],
Type: rule.Type,
}
parsedSyntaxes = append(parsedSyntaxes, parsedSyntax)
}
}
return parsedSyntaxes, nil
}