mirror of
https://github.com/EnumeratedDev/typer.git
synced 2026-09-16 13:36:12 +00:00
Add simple syntax highlighting
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user