diff --git a/.golangci.yml b/.golangci.yml index 996de84..e47053f 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -17,6 +17,7 @@ linters: - gochecknoglobals - funlen - godox + - wsl linters-settings: govet: diff --git a/.travis.yml b/.travis.yml index 4bcf48c..75dfcc2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ sudo: false language: go script: - go test -v ./... - - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s v1.19.1 + - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | bash -s v1.20.0 - ./bin/golangci-lint run - git clean -fdx . after_success: diff --git a/cmd/chroma/main.go b/cmd/chroma/main.go index 1240e45..a6a2f8d 100644 --- a/cmd/chroma/main.go +++ b/cmd/chroma/main.go @@ -41,7 +41,7 @@ command, for Go. List bool `help:"List lexers, styles and formatters."` Unbuffered bool `help:"Do not buffer output."` Trace bool `help:"Trace lexer states as they are traversed."` - Check bool `help:"Do not format, check for tokenization errors instead."` + Check bool `help:"Do not format, check for tokenisation errors instead."` Filename string `help:"Filename to use for selecting a lexer when reading from stdin."` Lexer string `help:"Lexer to use when formatting." default:"autodetect" short:"l" enum:"${lexers}"` @@ -117,15 +117,12 @@ func main() { } defer w.Flush() // nolint: errcheck - if cli.JSON { + switch { + case cli.JSON: cli.Formatter = "json" - } - - if cli.HTML { + case cli.HTML: cli.Formatter = "html" - } - - if cli.SVG { + case cli.SVG: cli.Formatter = "svg" } @@ -149,47 +146,7 @@ func main() { } if cli.Formatter == "html" { - options := []html.Option{ - html.TabWidth(cli.HTMLTabWidth), - html.BaseLineNumber(cli.HTMLBaseLine), - } - if cli.HTMLPrefix != "" { - options = append(options, html.ClassPrefix(cli.HTMLPrefix)) - } - if !cli.HTMLInlineStyles { - options = append(options, html.WithClasses()) - } - if !cli.HTMLOnly { - options = append(options, html.Standalone()) - } - if cli.HTMLLines { - options = append(options, html.WithLineNumbers()) - } - if cli.HTMLLinesTable { - options = append(options, html.LineNumbersInTable()) - } - if cli.HTMLPreventSurroundingPre { - options = append(options, html.PreventSurroundingPre()) - } - if len(cli.HTMLHighlight) > 0 { - ranges := [][2]int{} - for _, span := range strings.Split(cli.HTMLHighlight, ",") { - parts := strings.Split(span, ":") - if len(parts) > 2 { - ctx.Fatalf("range should be N[:M], not %q", span) - } - start, err := strconv.ParseInt(parts[0], 10, 64) - ctx.FatalIfErrorf(err, "min value of range should be integer not %q", parts[0]) - end := start - if len(parts) == 2 { - end, err = strconv.ParseInt(parts[1], 10, 64) - ctx.FatalIfErrorf(err, "max value of range should be integer not %q", parts[1]) - } - ranges = append(ranges, [2]int{int(start), int(end)}) - } - options = append(options, html.HighlightLines(ranges)) - } - formatters.Register("html", html.New(options...)) + configureHTMLFormatter(ctx) } if len(cli.Files) == 0 { contents, err := ioutil.ReadAll(os.Stdin) @@ -208,6 +165,50 @@ func main() { } } +func configureHTMLFormatter(ctx *kong.Context) { + options := []html.Option{ + html.TabWidth(cli.HTMLTabWidth), + html.BaseLineNumber(cli.HTMLBaseLine), + } + if cli.HTMLPrefix != "" { + options = append(options, html.ClassPrefix(cli.HTMLPrefix)) + } + if !cli.HTMLInlineStyles { + options = append(options, html.WithClasses()) + } + if !cli.HTMLOnly { + options = append(options, html.Standalone()) + } + if cli.HTMLLines { + options = append(options, html.WithLineNumbers()) + } + if cli.HTMLLinesTable { + options = append(options, html.LineNumbersInTable()) + } + if cli.HTMLPreventSurroundingPre { + options = append(options, html.PreventSurroundingPre()) + } + if len(cli.HTMLHighlight) > 0 { + ranges := [][2]int{} + for _, span := range strings.Split(cli.HTMLHighlight, ",") { + parts := strings.Split(span, ":") + if len(parts) > 2 { + ctx.Fatalf("range should be N[:M], not %q", span) + } + start, err := strconv.ParseInt(parts[0], 10, 64) + ctx.FatalIfErrorf(err, "min value of range should be integer not %q", parts[0]) + end := start + if len(parts) == 2 { + end, err = strconv.ParseInt(parts[1], 10, 64) + ctx.FatalIfErrorf(err, "max value of range should be integer not %q", parts[1]) + } + ranges = append(ranges, [2]int{int(start), int(end)}) + } + options = append(options, html.HighlightLines(ranges)) + } + formatters.Register("html", html.New(options...)) +} + func listAll() { fmt.Println("lexers:") sort.Sort(lexers.Registry.Lexers) diff --git a/delegate.go b/delegate.go index 021aeef..5cef01b 100644 --- a/delegate.go +++ b/delegate.go @@ -34,7 +34,7 @@ type insertion struct { tokens []Token } -func (d *delegatingLexer) Tokenise(options *TokeniseOptions, text string) (Iterator, error) { +func (d *delegatingLexer) Tokenise(options *TokeniseOptions, text string) (Iterator, error) { // nolint: gocognit tokens, err := Tokenise(Coalesce(d.language), options, text) if err != nil { return nil, err diff --git a/formatters/tty_indexed.go b/formatters/tty_indexed.go index 693c9b1..6354cc4 100644 --- a/formatters/tty_indexed.go +++ b/formatters/tty_indexed.go @@ -200,6 +200,7 @@ func findClosest(table *ttyTable, seeking chroma.Colour) chroma.Colour { } func styleToEscapeSequence(table *ttyTable, style *chroma.Style) map[chroma.TokenType]string { + style = clearBackground(style) out := map[chroma.TokenType]string{} for _, ttype := range style.Types() { entry := style.Get(ttype) @@ -208,6 +209,17 @@ func styleToEscapeSequence(table *ttyTable, style *chroma.Style) map[chroma.Toke return out } +// Clear the background colour. +func clearBackground(style *chroma.Style) *chroma.Style { + builder := style.Builder() + bg := builder.Get(chroma.Background) + bg.Background = 0 + bg.NoInherit = true + builder.AddEntry(chroma.Background, bg) + style, _ = builder.Build() + return style +} + type indexedTTYFormatter struct { table *ttyTable } diff --git a/formatters/tty_truecolour.go b/formatters/tty_truecolour.go index 40ec6de..b02e636 100644 --- a/formatters/tty_truecolour.go +++ b/formatters/tty_truecolour.go @@ -11,6 +11,7 @@ import ( var TTY16m = Register("terminal16m", chroma.FormatterFunc(trueColourFormatter)) func trueColourFormatter(w io.Writer, style *chroma.Style, it chroma.Iterator) error { + style = clearBackground(style) for token := it(); token != chroma.EOF; token = it() { entry := style.Get(token.Type) if !entry.IsZero() { diff --git a/go.mod b/go.mod index 70318b8..116d86a 100644 --- a/go.mod +++ b/go.mod @@ -20,3 +20,5 @@ require ( ) replace github.com/GeertJohan/go.rice => github.com/alecthomas/go.rice v1.0.1-0.20190719113735-961b99d742e7 + +go 1.13 diff --git a/lexers/h/http.go b/lexers/h/http.go index a7b5ba0..0a1264c 100644 --- a/lexers/h/http.go +++ b/lexers/h/http.go @@ -65,7 +65,7 @@ func httpBodyContentTypeLexer(lexer Lexer) Lexer { return &httpBodyContentTyper{ type httpBodyContentTyper struct{ Lexer } -func (d *httpBodyContentTyper) Tokenise(options *TokeniseOptions, text string) (Iterator, error) { +func (d *httpBodyContentTyper) Tokenise(options *TokeniseOptions, text string) (Iterator, error) { // nolint: gocognit var contentType string var isContentType bool var subIterator Iterator diff --git a/regexp.go b/regexp.go index 44ff149..59126db 100644 --- a/regexp.go +++ b/regexp.go @@ -255,7 +255,7 @@ func (l *LexerState) Get(key interface{}) interface{} { } // Iterator returns the next Token from the lexer. -func (l *LexerState) Iterator() Token { +func (l *LexerState) Iterator() Token { // nolint: gocognit for l.Pos < len(l.Text) && len(l.Stack) > 0 { // Exhaust the iterator stack, if any. for len(l.iteratorStack) > 0 {