Merge pull request #2933 from JoeKar/feature/default-syntax

syntax: Provide default.yaml as fallback definition
This commit is contained in:
Jöran Karl 2024-04-18 19:38:35 +02:00 committed by GitHub
commit 0806addbd7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 108 additions and 39 deletions

View file

@ -109,7 +109,10 @@ func handleEvent() {
if e != nil {
screen.Events <- e
}
DoEvent()
for len(screen.DrawChan()) > 0 || len(screen.Events) > 0 {
DoEvent()
}
}
func injectKey(key tcell.Key, r rune, mod tcell.ModMask) {
@ -151,6 +154,16 @@ func openFile(file string) {
injectKey(tcell.KeyEnter, rune(tcell.KeyEnter), tcell.ModNone)
}
func findBuffer(file string) *buffer.Buffer {
var buf *buffer.Buffer
for _, b := range buffer.OpenBuffers {
if b.Path == file {
buf = b
}
}
return buf
}
func createTestFile(name string, content string) (string, error) {
testf, err := ioutil.TempFile("", name)
if err != nil {
@ -190,14 +203,7 @@ func TestSimpleEdit(t *testing.T) {
openFile(file)
var buf *buffer.Buffer
for _, b := range buffer.OpenBuffers {
if b.Path == file {
buf = b
}
}
if buf == nil {
if findBuffer(file) == nil {
t.Errorf("Could not find buffer %s", file)
return
}
@ -236,6 +242,11 @@ func TestMouse(t *testing.T) {
openFile(file)
if findBuffer(file) == nil {
t.Errorf("Could not find buffer %s", file)
return
}
// buffer:
// base content
// the selections need to happen at different locations to avoid a double click
@ -299,6 +310,11 @@ func TestSearchAndReplace(t *testing.T) {
openFile(file)
if findBuffer(file) == nil {
t.Errorf("Could not find buffer %s", file)
return
}
injectKey(tcell.KeyCtrlE, rune(tcell.KeyCtrlE), tcell.ModCtrl)
injectString(fmt.Sprintf("replaceall %s %s", "foo", "test_string"))
injectKey(tcell.KeyEnter, rune(tcell.KeyEnter), tcell.ModNone)

View file

@ -682,6 +682,64 @@ func calcHash(b *Buffer, out *[md5.Size]byte) error {
return nil
}
func parseDefFromFile(f config.RuntimeFile, header *highlight.Header) *highlight.Def {
data, err := f.Data()
if err != nil {
screen.TermMessage("Error loading syntax file " + f.Name() + ": " + err.Error())
return nil
}
if header == nil {
header, err = highlight.MakeHeaderYaml(data)
if err != nil {
screen.TermMessage("Error parsing header for syntax file " + f.Name() + ": " + err.Error())
return nil
}
}
file, err := highlight.ParseFile(data)
if err != nil {
screen.TermMessage("Error parsing syntax file " + f.Name() + ": " + err.Error())
return nil
}
syndef, err := highlight.ParseDef(file, header)
if err != nil {
screen.TermMessage("Error parsing syntax file " + f.Name() + ": " + err.Error())
return nil
}
return syndef
}
// findRealRuntimeSyntaxDef finds a specific syntax definition
// in the user's custom syntax files
func findRealRuntimeSyntaxDef(name string, header *highlight.Header) *highlight.Def {
for _, f := range config.ListRealRuntimeFiles(config.RTSyntax) {
if f.Name() == name {
syndef := parseDefFromFile(f, header)
if syndef != nil {
return syndef
}
}
}
return nil
}
// findRuntimeSyntaxDef finds a specific syntax definition
// in the runtime files
func findRuntimeSyntaxDef(name string, header *highlight.Header) *highlight.Def {
for _, f := range config.ListRuntimeFiles(config.RTSyntax) {
if f.Name() == name {
syndef := parseDefFromFile(f, header)
if syndef != nil {
return syndef
}
}
}
return nil
}
// UpdateRules updates the syntax rules and filetype for this buffer
// This is called when the colorscheme changes
func (b *Buffer) UpdateRules() {
@ -710,6 +768,10 @@ func (b *Buffer) UpdateRules() {
var header *highlight.Header
// search for the syntax file in the user's custom syntax files
for _, f := range config.ListRealRuntimeFiles(config.RTSyntax) {
if f.Name() == "default" {
continue
}
data, err := f.Data()
if err != nil {
screen.TermMessage("Error loading syntax file " + f.Name() + ": " + err.Error())
@ -766,7 +828,7 @@ func (b *Buffer) UpdateRules() {
}
if !foundDef {
// search in the default syntax files
// search for the syntax file in the runtime files
for _, f := range config.ListRuntimeFiles(config.RTSyntaxHeader) {
data, err := f.Data()
if err != nil {
@ -844,29 +906,7 @@ func (b *Buffer) UpdateRules() {
if syntaxFile != "" && !foundDef {
// we found a syntax file using a syntax header file
for _, f := range config.ListRuntimeFiles(config.RTSyntax) {
if f.Name() == syntaxFile {
data, err := f.Data()
if err != nil {
screen.TermMessage("Error loading syntax file " + f.Name() + ": " + err.Error())
continue
}
file, err := highlight.ParseFile(data)
if err != nil {
screen.TermMessage("Error parsing syntax file " + f.Name() + ": " + err.Error())
continue
}
syndef, err := highlight.ParseDef(file, header)
if err != nil {
screen.TermMessage("Error parsing syntax file " + f.Name() + ": " + err.Error())
continue
}
b.SyntaxDef = syndef
break
}
}
b.SyntaxDef = findRuntimeSyntaxDef(syntaxFile, header)
}
if b.SyntaxDef != nil && highlight.HasIncludes(b.SyntaxDef) {
@ -876,9 +916,10 @@ func (b *Buffer) UpdateRules() {
for _, f := range config.ListRuntimeFiles(config.RTSyntax) {
data, err := f.Data()
if err != nil {
screen.TermMessage("Error parsing syntax file " + f.Name() + ": " + err.Error())
screen.TermMessage("Error loading syntax file " + f.Name() + ": " + err.Error())
continue
}
header, err := highlight.MakeHeaderYaml(data)
if err != nil {
screen.TermMessage("Error parsing syntax file " + f.Name() + ": " + err.Error())
@ -907,9 +948,14 @@ func (b *Buffer) UpdateRules() {
if b.Highlighter == nil || syntaxFile != "" {
if b.SyntaxDef != nil {
b.Settings["filetype"] = b.SyntaxDef.FileType
} else {
// search for the default file in the user's custom syntax files
b.SyntaxDef = findRealRuntimeSyntaxDef("default", nil)
if b.SyntaxDef == nil {
// search for the default file in the runtime files
b.SyntaxDef = findRuntimeSyntaxDef("default", nil)
}
}
} else {
b.SyntaxDef = &highlight.EmptyDef
}
if b.SyntaxDef != nil {

View file

@ -67,9 +67,6 @@ func combineLineMatch(src, dst LineMatch) LineMatch {
// A State represents the region at the end of a line
type State *region
// EmptyDef is an empty definition.
var EmptyDef = Def{nil, &rules{}}
// LineStates is an interface for a buffer-like object which can also store the states and matches for every line
type LineStates interface {
LineBytes(n int) []byte

View file

@ -0,0 +1,10 @@
filetype: unknown
detect:
filename: ""
rules:
# Mails
- special: "[[:alnum:].%_+-]+@[[:alnum:].-]+"
# URLs
- identifier: "(https?|ftp|ssh)://\\S*[^])>\\s,.]"