mirror of
https://github.com/EnumeratedDev/typer.git
synced 2026-09-16 05:36:10 +00:00
110 lines
2.4 KiB
Go
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
|
|
}
|