mirror of
https://github.com/alecthomas/chroma.git
synced 2025-07-01 00:35:06 +02:00
Emit error tokens when there's a group mismatch.
Also don't panic/recover, as we no longer use panic to report "real" errors. Fixes #295.
This commit is contained in:
@ -91,11 +91,6 @@ func (h highlightRanges) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
|
|||||||
func (h highlightRanges) Less(i, j int) bool { return h[i][0] < h[j][0] }
|
func (h highlightRanges) Less(i, j int) bool { return h[i][0] < h[j][0] }
|
||||||
|
|
||||||
func (f *Formatter) Format(w io.Writer, style *chroma.Style, iterator chroma.Iterator) (err error) {
|
func (f *Formatter) Format(w io.Writer, style *chroma.Style, iterator chroma.Iterator) (err error) {
|
||||||
defer func() {
|
|
||||||
if perr := recover(); perr != nil {
|
|
||||||
err = perr.(error)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return f.writeHTML(w, style, iterator.Tokens())
|
return f.writeHTML(w, style, iterator.Tokens())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ package html
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@ -50,14 +49,6 @@ func TestSplitTokensIntoLines(t *testing.T) {
|
|||||||
assert.Equal(t, expected, actual)
|
assert.Equal(t, expected, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIteratorPanicRecovery(t *testing.T) {
|
|
||||||
it := func() chroma.Token {
|
|
||||||
panic(errors.New("bad"))
|
|
||||||
}
|
|
||||||
err := New().Format(ioutil.Discard, styles.Fallback, it)
|
|
||||||
assert.Error(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFormatterStyleToCSS(t *testing.T) {
|
func TestFormatterStyleToCSS(t *testing.T) {
|
||||||
builder := styles.Get("github").Builder()
|
builder := styles.Get("github").Builder()
|
||||||
builder.Add(chroma.LineHighlight, "bg:#ffffcc")
|
builder.Add(chroma.LineHighlight, "bg:#ffffcc")
|
||||||
|
@ -62,11 +62,6 @@ type Formatter struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *Formatter) Format(w io.Writer, style *chroma.Style, iterator chroma.Iterator) (err error) {
|
func (f *Formatter) Format(w io.Writer, style *chroma.Style, iterator chroma.Iterator) (err error) {
|
||||||
defer func() {
|
|
||||||
if perr := recover(); perr != nil {
|
|
||||||
err = perr.(error)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
f.writeSVG(w, style, iterator.Tokens())
|
f.writeSVG(w, style, iterator.Tokens())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -225,11 +225,6 @@ type indexedTTYFormatter struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *indexedTTYFormatter) Format(w io.Writer, style *chroma.Style, it chroma.Iterator) (err error) {
|
func (c *indexedTTYFormatter) Format(w io.Writer, style *chroma.Style, it chroma.Iterator) (err error) {
|
||||||
defer func() {
|
|
||||||
if perr := recover(); perr != nil {
|
|
||||||
err = perr.(error)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
theme := styleToEscapeSequence(c.table, style)
|
theme := styleToEscapeSequence(c.table, style)
|
||||||
for token := it(); token != chroma.EOF; token = it() {
|
for token := it(); token != chroma.EOF; token = it() {
|
||||||
// TODO: Cache token lookups?
|
// TODO: Cache token lookups?
|
||||||
|
1
go.mod
1
go.mod
@ -14,6 +14,7 @@ require (
|
|||||||
github.com/gorilla/mux v1.7.3
|
github.com/gorilla/mux v1.7.3
|
||||||
github.com/mattn/go-colorable v0.0.9
|
github.com/mattn/go-colorable v0.0.9
|
||||||
github.com/mattn/go-isatty v0.0.4
|
github.com/mattn/go-isatty v0.0.4
|
||||||
|
github.com/pkg/errors v0.8.1
|
||||||
github.com/sergi/go-diff v1.0.0 // indirect
|
github.com/sergi/go-diff v1.0.0 // indirect
|
||||||
github.com/stretchr/testify v1.3.0
|
github.com/stretchr/testify v1.3.0
|
||||||
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35 // indirect
|
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35 // indirect
|
||||||
|
@ -25,7 +25,7 @@ var Ballerina = internal.Register(MustNewLexer(
|
|||||||
{`(annotation|bind|but|endpoint|error|function|object|private|public|returns|service|type|var|with|worker)\b`, KeywordDeclaration, nil},
|
{`(annotation|bind|but|endpoint|error|function|object|private|public|returns|service|type|var|with|worker)\b`, KeywordDeclaration, nil},
|
||||||
{`(boolean|byte|decimal|float|int|json|map|nil|record|string|table|xml)\b`, KeywordType, nil},
|
{`(boolean|byte|decimal|float|int|json|map|nil|record|string|table|xml)\b`, KeywordType, nil},
|
||||||
{`(true|false|null)\b`, KeywordConstant, nil},
|
{`(true|false|null)\b`, KeywordConstant, nil},
|
||||||
{`import(\s+)`, ByGroups(KeywordNamespace, Text), Push("import")},
|
{`(import)(\s+)`, ByGroups(KeywordNamespace, Text), Push("import")},
|
||||||
{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
|
{`"(\\\\|\\"|[^"])*"`, LiteralString, nil},
|
||||||
{`'\\.'|'[^\\]'|'\\u[0-9a-fA-F]{4}'`, LiteralStringChar, nil},
|
{`'\\.'|'[^\\]'|'\\u[0-9a-fA-F]{4}'`, LiteralStringChar, nil},
|
||||||
{`(\.)((?:[^\W\d]|\$)[\w$]*)`, ByGroups(Operator, NameAttribute), nil},
|
{`(\.)((?:[^\W\d]|\$)[\w$]*)`, ByGroups(Operator, NameAttribute), nil},
|
||||||
|
@ -22,7 +22,7 @@ var Docker = internal.Register(MustNewLexer(
|
|||||||
{`(ONBUILD)((?:\s*\\?\s*))`, ByGroups(Keyword, Using(b.Bash)), nil},
|
{`(ONBUILD)((?:\s*\\?\s*))`, ByGroups(Keyword, Using(b.Bash)), nil},
|
||||||
{`(HEALTHCHECK)(((?:\s*\\?\s*)--\w+=\w+(?:\s*\\?\s*))*)`, ByGroups(Keyword, Using(b.Bash)), nil},
|
{`(HEALTHCHECK)(((?:\s*\\?\s*)--\w+=\w+(?:\s*\\?\s*))*)`, ByGroups(Keyword, Using(b.Bash)), nil},
|
||||||
{`(VOLUME|ENTRYPOINT|CMD|SHELL)((?:\s*\\?\s*))(\[.*?\])`, ByGroups(Keyword, Using(b.Bash), Using(j.JSON)), nil},
|
{`(VOLUME|ENTRYPOINT|CMD|SHELL)((?:\s*\\?\s*))(\[.*?\])`, ByGroups(Keyword, Using(b.Bash), Using(j.JSON)), nil},
|
||||||
{`(LABEL|ENV|ARG)(((?:\s*\\?\s*)\w+=\w+(?:\s*\\?\s*))*)`, ByGroups(Keyword, Using(b.Bash)), nil},
|
{`(LABEL|ENV|ARG)((?:(?:\s*\\?\s*)\w+=\w+(?:\s*\\?\s*))*)`, ByGroups(Keyword, Using(b.Bash)), nil},
|
||||||
{`((?:FROM|MAINTAINER|EXPOSE|WORKDIR|USER|STOPSIGNAL)|VOLUME)\b(.*)`, ByGroups(Keyword, LiteralString), nil},
|
{`((?:FROM|MAINTAINER|EXPOSE|WORKDIR|USER|STOPSIGNAL)|VOLUME)\b(.*)`, ByGroups(Keyword, LiteralString), nil},
|
||||||
{`((?:RUN|CMD|ENTRYPOINT|ENV|ARG|LABEL|ADD|COPY))`, Keyword, nil},
|
{`((?:RUN|CMD|ENTRYPOINT|ENV|ARG|LABEL|ADD|COPY))`, Keyword, nil},
|
||||||
{`(.*\\\n)*.+`, Using(b.Bash), nil},
|
{`(.*\\\n)*.+`, Using(b.Bash), nil},
|
||||||
|
3
lexers/testdata/ballerina.expected
vendored
3
lexers/testdata/ballerina.expected
vendored
@ -1,5 +1,6 @@
|
|||||||
[
|
[
|
||||||
{"type":"KeywordNamespace","value":" "},
|
{"type":"KeywordNamespace","value":"import"},
|
||||||
|
{"type":"Text","value":" "},
|
||||||
{"type":"NameNamespace","value":"ballerina"},
|
{"type":"NameNamespace","value":"ballerina"},
|
||||||
{"type":"Operator","value":"/"},
|
{"type":"Operator","value":"/"},
|
||||||
{"type":"Name","value":"http"},
|
{"type":"Name","value":"http"},
|
||||||
|
@ -35,9 +35,14 @@ func ByGroups(emitters ...Emitter) Emitter {
|
|||||||
return EmitterFunc(func(groups []string, lexer Lexer) Iterator {
|
return EmitterFunc(func(groups []string, lexer Lexer) Iterator {
|
||||||
iterators := make([]Iterator, 0, len(groups)-1)
|
iterators := make([]Iterator, 0, len(groups)-1)
|
||||||
// NOTE: If this panics, there is a mismatch with groups
|
// NOTE: If this panics, there is a mismatch with groups
|
||||||
|
if len(emitters) != len(groups)-1 {
|
||||||
|
iterators = append(iterators, Error.Emit(groups, lexer))
|
||||||
|
// panic(errors.Errorf("number of groups %q does not match number of emitters %v", groups, emitters))
|
||||||
|
} else {
|
||||||
for i, group := range groups[1:] {
|
for i, group := range groups[1:] {
|
||||||
iterators = append(iterators, emitters[i].Emit([]string{group}, lexer))
|
iterators = append(iterators, emitters[i].Emit([]string{group}, lexer))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return Concaterator(iterators...)
|
return Concaterator(iterators...)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user