diff --git a/cmd/micro/micro_test.go b/cmd/micro/micro_test.go index 4c5ca684..cd3dda22 100644 --- a/cmd/micro/micro_test.go +++ b/cmd/micro/micro_test.go @@ -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) diff --git a/internal/buffer/buffer.go b/internal/buffer/buffer.go index 6865fe12..0892df45 100644 --- a/internal/buffer/buffer.go +++ b/internal/buffer/buffer.go @@ -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 { diff --git a/pkg/highlight/highlighter.go b/pkg/highlight/highlighter.go index 10a78d5c..ebcd2aaa 100644 --- a/pkg/highlight/highlighter.go +++ b/pkg/highlight/highlighter.go @@ -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 diff --git a/runtime/syntax/default.yaml b/runtime/syntax/default.yaml new file mode 100644 index 00000000..f619ca67 --- /dev/null +++ b/runtime/syntax/default.yaml @@ -0,0 +1,10 @@ +filetype: unknown + +detect: + filename: "" + +rules: + # Mails + - special: "[[:alnum:].%_+-]+@[[:alnum:].-]+" + # URLs + - identifier: "(https?|ftp|ssh)://\\S*[^])>\\s,.]"