func FuncBody(t *testing.T) { expect := expect.New(t) src := ` package foo func (*Foo) Foo(baz Baz) { baz.Bar() } ` s := syntax.New(syntax.DefaultTheme) err := s.Parse(src) expect(err).To.Be.Nil().Else.FailNow() layers := s.Layers() firstParens := layers[syntax.DefaultTheme.Rainbow.New()] expect(firstParens.Spans()).To.Have.Len(6).Else.FailNow() expect(firstParens.Spans()[0]).To.Pass(position{src: src, match: "("}) expect(firstParens.Spans()[1]).To.Pass(position{src: src, match: ")"}) expect(firstParens.Spans()[2]).To.Pass(position{src: src, match: "(", idx: 1}) expect(firstParens.Spans()[3]).To.Pass(position{src: src, match: ")", idx: 1}) expect(firstParens.Spans()[4]).To.Pass(position{src: src, match: "{"}) expect(firstParens.Spans()[5]).To.Pass(position{src: src, match: "}"}) secondParens := layers[syntax.DefaultTheme.Rainbow.New()] expect(secondParens.Spans()).To.Have.Len(2).Else.FailNow() expect(secondParens.Spans()[0]).To.Pass(position{src: src, match: "(", idx: 2}) expect(secondParens.Spans()[1]).To.Pass(position{src: src, match: ")", idx: 2}) }
func AssignStmt(t *testing.T) { expect := expect.New(t) src := ` package foo func main() { x := 0.1 y = "foo" }` s := syntax.New(syntax.DefaultTheme) err := s.Parse(src) expect(err).To.Be.Nil() layers := s.Layers() expect(layers).To.Have.Len(6) nums := layers[syntax.DefaultTheme.Colors.Num] expect(nums.Spans()).To.Have.Len(1) expect(nums.Spans()[0]).To.Pass(position{src: src, match: "0.1"}) strings := layers[syntax.DefaultTheme.Colors.String] expect(strings.Spans()).To.Have.Len(1) expect(strings.Spans()[0]).To.Pass(position{src: src, match: `"foo"`}) }
func Array(t *testing.T) { expect := expect.New(t) src := ` package foo func main() { var v [3]string v := [...]string{"foo"} } ` s := syntax.New(syntax.DefaultTheme) err := s.Parse(src) expect(err).To.Be.Nil().Else.FailNow() layers := s.Layers() // Ditch the function color syntax.DefaultTheme.Rainbow.New() arrParens := layers[syntax.DefaultTheme.Rainbow.New()] expect(arrParens.Spans()).To.Have.Len(6).Else.FailNow() expect(arrParens.Spans()[0]).To.Pass(position{src: src, match: "["}) expect(arrParens.Spans()[1]).To.Pass(position{src: src, match: "]"}) expect(arrParens.Spans()[2]).To.Pass(position{src: src, match: "[", idx: 1}) expect(arrParens.Spans()[3]).To.Pass(position{src: src, match: "]", idx: 1}) expect(arrParens.Spans()[4]).To.Pass(position{src: src, match: "{", idx: 1}) expect(arrParens.Spans()[5]).To.Pass(position{src: src, match: "}"}) typs := layers[syntax.DefaultTheme.Colors.Type] expect(typs.Spans()).To.Have.Len(2).Else.FailNow() expect(typs.Spans()[0]).To.Pass(position{src: src, match: "string"}) expect(typs.Spans()[1]).To.Pass(position{src: src, match: "string", idx: 1}) }
func TestUnicode(t *testing.T) { expect := expect.New(t) src := ` package foo func µ() string { var þ = "Ωð" return þ } ` s := syntax.New(syntax.DefaultTheme) err := s.Parse(src) expect(err).To.Be.Nil() layers := s.Layers() keywords := layers[syntax.DefaultTheme.Colors.Keyword] expect(keywords.Spans()).To.Have.Len(4) expect(keywords.Spans()[2]).To.Pass(position{src: src, match: "var"}) expect(keywords.Spans()[3]).To.Pass(position{src: src, match: "return"}) strings := layers[syntax.DefaultTheme.Colors.String] expect(strings.Spans()).To.Have.Len(1) expect(strings.Spans()[0]).To.Pass(position{src: src, match: `"Ωð"`}) }
func CommClause(t *testing.T) { expect := expect.New(t) src := ` package foo func main() { switch { case foo == "bar": x = 1 case y == false: default: println("bacon") } }` s := syntax.New(syntax.DefaultTheme) err := s.Parse(src) expect(err).To.Be.Nil() layers := s.Layers() expect(layers).To.Have.Len(9) keywords := layers[syntax.DefaultTheme.Colors.Keyword] expect(keywords.Spans()).To.Have.Len(6) expect(keywords.Spans()[3]).To.Pass(position{src: src, match: "case"}) expect(keywords.Spans()[4]).To.Pass(position{src: src, match: "case", idx: 1}) expect(keywords.Spans()[5]).To.Pass(position{src: src, match: "default"}) strings := layers[syntax.DefaultTheme.Colors.String] expect(strings.Spans()).To.Have.Len(2) expect(strings.Spans()[0]).To.Pass(position{src: src, match: `"bar"`}) expect(strings.Spans()[1]).To.Pass(position{src: src, match: `"bacon"`}) nums := layers[syntax.DefaultTheme.Colors.Num] expect(nums.Spans()).To.Have.Len(1) expect(nums.Spans()[0]).To.Pass(position{src: src, match: "1"}) builtins := layers[syntax.DefaultTheme.Colors.Builtin] expect(builtins.Spans()).To.Have.Len(1) expect(builtins.Spans()[0]).To.Pass(position{src: src, match: "println"}) }
func TestPackageDocs(t *testing.T) { expect := expect.New(t) src := ` // Package foo does stuff. // It is also a thing. package foo ` s := syntax.New(syntax.DefaultTheme) err := s.Parse(src) expect(err).To.Be.Nil() layers := s.Layers() expect(layers).To.Have.Len(2) comments := layers[syntax.DefaultTheme.Colors.Comment] expect(comments.Spans()).To.Have.Len(1) comment := "// Package foo does stuff.\n" + "// It is also a thing." expect(comments.Spans()[0]).To.Pass(position{src: src, match: comment}) }
func (e *CodeEditor) Init(driver gxui.Driver, theme *basic.Theme, font gxui.Font, file, headerText string) { e.theme = theme e.driver = driver e.history = NewHistory() e.syntax = syntax.New(syntax.DefaultTheme) e.adapter = &suggestions.Adapter{} e.suggestions = e.CreateSuggestionList() e.suggestions.SetAdapter(e.adapter) e.CodeEditor.Init(e, driver, theme, font) e.CodeEditor.SetScrollBarEnabled(true) e.SetDesiredWidth(math.MaxSize.W) e.watcherSetup() e.OnTextChanged(func(changes []gxui.TextBoxEdit) { e.hasChanges = true // TODO: only update layers that changed. err := e.syntax.Parse(e.Text()) layers := e.syntax.Layers() layerSlice := make(gxui.CodeSyntaxLayers, 0, len(layers)) for _, layer := range layers { layerSlice = append(layerSlice, layer) } e.SetSyntaxLayers(layerSlice) // TODO: display the error in some pane of the editor _ = err e.history.Add(changes...) }) e.filepath = file e.open(headerText) e.SetTextColor(theme.TextBoxDefaultStyle.FontColor) e.SetMargin(math.Spacing{L: 3, T: 3, R: 3, B: 3}) e.SetPadding(math.Spacing{L: 3, T: 3, R: 3, B: 3}) e.SetBorderPen(gxui.TransparentPen) }
func Slice(t *testing.T) { expect := expect.New(t) src := ` package foo func main() { var v [3]string u := v[:] x := []string{"foo"} y := x[1:] z := x[:1] } ` s := syntax.New(syntax.DefaultTheme) err := s.Parse(src) expect(err).To.Be.Nil().Else.FailNow() layers := s.Layers() // Ditch the function color syntax.DefaultTheme.Rainbow.New() arrParens := layers[syntax.DefaultTheme.Rainbow.New()] expect(arrParens.Spans()).To.Have.Len(12).Else.FailNow() // 0 and 1 are the [3]string, for an array type. expect(arrParens.Spans()[2]).To.Pass(position{src: src, match: "[", idx: 1}) expect(arrParens.Spans()[3]).To.Pass(position{src: src, match: "]", idx: 1}) expect(arrParens.Spans()[4]).To.Pass(position{src: src, match: "[", idx: 2}) expect(arrParens.Spans()[5]).To.Pass(position{src: src, match: "]", idx: 2}) expect(arrParens.Spans()[6]).To.Pass(position{src: src, match: "{", idx: 1}) expect(arrParens.Spans()[7]).To.Pass(position{src: src, match: "}"}) expect(arrParens.Spans()[8]).To.Pass(position{src: src, match: "[", idx: 3}) expect(arrParens.Spans()[9]).To.Pass(position{src: src, match: "]", idx: 3}) expect(arrParens.Spans()[10]).To.Pass(position{src: src, match: "[", idx: 4}) expect(arrParens.Spans()[11]).To.Pass(position{src: src, match: "]", idx: 4}) }
func TestKeywords(t *testing.T) { expect := expect.New(t) src := ` package foo import "time" var f map[string]string const s = 0 type foo struct {} type bar interface{} func Foo(in chan string) string { wait := make(chan struct{}) go func() { var done chan<- struct{} = wait defer close(done) for range in { } }() var exitAfter <-chan struct{} = wait goto FOO FOO: for { if true { break } else if false { continue } else { panic("foo") } } switch { case true: fallthrough default: return "foo" } <-done select { case <-time.After(time.Second): default: } } ` s := syntax.New(syntax.DefaultTheme) err := s.Parse(src) expect(err).To.Be.Nil().Else.FailNow() layers := s.Layers() keywords := layers[syntax.DefaultTheme.Colors.Keyword] expect(keywords.Spans()[0]).To.Pass(position{src: src, match: "package"}) expect(keywords.Spans()[1]).To.Pass(position{src: src, match: "import"}) expect(keywords.Spans()[2]).To.Pass(position{src: src, match: "var"}) expect(keywords.Spans()[3]).To.Pass(position{src: src, match: "map"}) expect(keywords.Spans()[4]).To.Pass(position{src: src, match: "const"}) expect(keywords.Spans()[5]).To.Pass(position{src: src, match: "type"}) expect(keywords.Spans()[6]).To.Pass(position{src: src, match: "struct"}) expect(keywords.Spans()[7]).To.Pass(position{src: src, idx: 1, match: "type"}) expect(keywords.Spans()[8]).To.Pass(position{src: src, match: "interface"}) expect(keywords.Spans()[9]).To.Pass(position{src: src, match: "func"}) expect(keywords.Spans()[10]).To.Pass(position{src: src, match: "chan"}) expect(keywords.Spans()[11]).To.Pass(position{src: src, idx: 1, match: "chan"}) expect(keywords.Spans()[12]).To.Pass(position{src: src, idx: 1, match: "struct"}) expect(keywords.Spans()[13]).To.Pass(position{src: src, match: "go"}) expect(keywords.Spans()[14]).To.Pass(position{src: src, idx: 1, match: "func"}) expect(keywords.Spans()[15]).To.Pass(position{src: src, idx: 1, match: "var"}) expect(keywords.Spans()[16]).To.Pass(position{src: src, match: "chan<-"}) expect(keywords.Spans()[17]).To.Pass(position{src: src, idx: 2, match: "struct"}) expect(keywords.Spans()[18]).To.Pass(position{src: src, match: "defer"}) expect(keywords.Spans()[19]).To.Pass(position{src: src, match: "for"}) expect(keywords.Spans()[20]).To.Pass(position{src: src, match: "range"}) expect(keywords.Spans()[21]).To.Pass(position{src: src, idx: 2, match: "var"}) expect(keywords.Spans()[22]).To.Pass(position{src: src, match: "<-chan"}) expect(keywords.Spans()[23]).To.Pass(position{src: src, idx: 3, match: "struct"}) expect(keywords.Spans()[24]).To.Pass(position{src: src, match: "goto"}) expect(keywords.Spans()[25]).To.Pass(position{src: src, idx: 1, match: "for"}) expect(keywords.Spans()[26]).To.Pass(position{src: src, match: "if"}) expect(keywords.Spans()[27]).To.Pass(position{src: src, match: "break"}) expect(keywords.Spans()[28]).To.Pass(position{src: src, match: "else"}) expect(keywords.Spans()[29]).To.Pass(position{src: src, idx: 1, match: "if"}) expect(keywords.Spans()[30]).To.Pass(position{src: src, match: "continue"}) expect(keywords.Spans()[31]).To.Pass(position{src: src, idx: 1, match: "else"}) expect(keywords.Spans()[32]).To.Pass(position{src: src, match: "switch"}) expect(keywords.Spans()[33]).To.Pass(position{src: src, match: "case"}) expect(keywords.Spans()[34]).To.Pass(position{src: src, match: "fallthrough"}) expect(keywords.Spans()[35]).To.Pass(position{src: src, match: "default"}) expect(keywords.Spans()[36]).To.Pass(position{src: src, match: "return"}) expect(keywords.Spans()[37]).To.Pass(position{src: src, match: "select"}) expect(keywords.Spans()[38]).To.Pass(position{src: src, idx: 1, match: "case"}) expect(keywords.Spans()[39]).To.Pass(position{src: src, idx: 1, match: "default"}) }
func TestBuiltins(t *testing.T) { expect := expect.New(t) src := ` package foo func foo() { defer recover() append([]string{"foo"}, "bar") cap([]string{"foo"}) copy([]string{""}, []string{"foo"}) delete(map[string]string{"foo": "bar"}, "foo") len([]string{""}) new(struct{}) print("foo") println("foo") ch := make(chan struct{}) close(ch) comp := complex(1, -1) imag(comp) real(comp) v := nil panic("foo") } ` s := syntax.New(syntax.DefaultTheme) err := s.Parse(src) expect(err).To.Be.Nil().Else.FailNow() layers := s.Layers() builtins := layers[syntax.DefaultTheme.Colors.Builtin] expect(builtins.Spans()).To.Have.Len(15).Else.FailNow() expect(builtins.Spans()[0]).To.Pass(position{src: src, match: "recover"}) expect(builtins.Spans()[1]).To.Pass(position{src: src, match: "append"}) expect(builtins.Spans()[2]).To.Pass(position{src: src, match: "cap"}) expect(builtins.Spans()[3]).To.Pass(position{src: src, match: "copy"}) expect(builtins.Spans()[4]).To.Pass(position{src: src, match: "delete"}) expect(builtins.Spans()[5]).To.Pass(position{src: src, match: "len"}) expect(builtins.Spans()[6]).To.Pass(position{src: src, match: "new"}) expect(builtins.Spans()[7]).To.Pass(position{src: src, match: "print"}) expect(builtins.Spans()[8]).To.Pass(position{src: src, match: "println"}) expect(builtins.Spans()[9]).To.Pass(position{src: src, match: "make"}) expect(builtins.Spans()[10]).To.Pass(position{src: src, match: "close"}) expect(builtins.Spans()[11]).To.Pass(position{src: src, match: "complex"}) expect(builtins.Spans()[12]).To.Pass(position{src: src, match: "imag"}) expect(builtins.Spans()[13]).To.Pass(position{src: src, match: "real"}) expect(builtins.Spans()[14]).To.Pass(position{src: src, match: "panic"}) nils := layers[syntax.DefaultTheme.Colors.Nil] expect(nils.Spans()).To.Have.Len(1).Else.FailNow() expect(nils.Spans()[0]).To.Pass(position{src: src, match: "nil"}) // Test that we're not highlighting these as both idents and builtins. idents := layers[syntax.DefaultTheme.Colors.Ident] expect(idents.Spans()).To.Have.Len(6) }