Skip to content

Commit

Permalink
Synthesise meta style-entries on demand.
Browse files Browse the repository at this point in the history
This includes line highlighting, numbers, etc.

Fixes #211.
  • Loading branch information
alecthomas committed Dec 31, 2018
1 parent 69c9a26 commit 2a59c2c
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 33 deletions.
24 changes: 0 additions & 24 deletions formatters/html/html.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,34 +99,10 @@ func (f *Formatter) Format(w io.Writer, style *chroma.Style, iterator chroma.Ite
return f.writeHTML(w, style, iterator.Tokens())
}

// Ensure that style entries exist for highlighting, etc.
func (f *Formatter) restyle(style *chroma.Style) (*chroma.Style, error) {
builder := style.Builder()
bg := builder.Get(chroma.Background)
// If we don't have a line highlight colour, make one that is 10% brighter/darker than the background.
if !style.Has(chroma.LineHighlight) {
highlight := chroma.StyleEntry{Background: bg.Background}
highlight.Background = highlight.Background.BrightenOrDarken(0.1)
builder.AddEntry(chroma.LineHighlight, highlight)
}
// If we don't have line numbers, use the text colour but 20% brighter/darker
if !style.Has(chroma.LineNumbers) {
text := chroma.StyleEntry{Colour: bg.Colour}
text.Colour = text.Colour.BrightenOrDarken(0.5)
builder.AddEntry(chroma.LineNumbers, text)
builder.AddEntry(chroma.LineNumbersTable, text)
}
return builder.Build()
}

// We deliberately don't use html/template here because it is two orders of magnitude slower (benchmarked).
//
// OTOH we need to be super careful about correct escaping...
func (f *Formatter) writeHTML(w io.Writer, style *chroma.Style, tokens []chroma.Token) (err error) { // nolint: gocyclo
style, err = f.restyle(style)
if err != nil {
return err
}
css := f.styleToCSS(style)
if !f.Classes {
for t, style := range css {
Expand Down
42 changes: 33 additions & 9 deletions style.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,15 +247,7 @@ func (s *Style) Builder() *StyleBuilder {
//
// This is distinct from Get() which will merge parent tokens.
func (s *Style) Has(ttype TokenType) bool {
return !s.get(ttype).IsZero()
}

func (s *Style) get(ttype TokenType) StyleEntry {
out := s.entries[ttype]
if out.IsZero() && s.parent != nil {
return s.parent.get(ttype)
}
return out
return !s.get(ttype).IsZero() || s.synthesisable(ttype)
}

// Get a style entry. Will try sub-category or category if an exact match is not found, and
Expand All @@ -268,6 +260,38 @@ func (s *Style) Get(ttype TokenType) StyleEntry {
s.get(ttype.SubCategory()))
}

func (s *Style) get(ttype TokenType) StyleEntry {
out := s.entries[ttype]
if out.IsZero() && s.synthesisable(ttype) {
out = s.synthesise(ttype)
}
if out.IsZero() && s.parent != nil {
return s.parent.get(ttype)
}
return out
}

func (s *Style) synthesise(ttype TokenType) StyleEntry {
bg := s.get(Background)
text := StyleEntry{Colour: bg.Colour}
text.Colour = text.Colour.BrightenOrDarken(0.5)

switch ttype {
// If we don't have a line highlight colour, make one that is 10% brighter/darker than the background.
case LineHighlight:
return StyleEntry{Background: bg.Background.BrightenOrDarken(0.1)}

// If we don't have line numbers, use the text colour but 20% brighter/darker
case LineNumbers, LineNumbersTable:
return text
}
return StyleEntry{}
}

func (s *Style) synthesisable(ttype TokenType) bool {
return ttype == LineHighlight || ttype == LineNumbers || ttype == LineNumbersTable
}

// ParseStyleEntry parses a Pygments style entry.
func ParseStyleEntry(entry string) (StyleEntry, error) { // nolint: gocyclo
out := StyleEntry{}
Expand Down
13 changes: 13 additions & 0 deletions style_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,16 @@ func TestStyleClone(t *testing.T) {
assert.Equal(t, "#00ff00 bg:#ffffff", clone.Get(Comment).String())
assert.Equal(t, "bg:#ffffff", parent.Get(Comment).String())
}

func TestSynthesisedStyleEntries(t *testing.T) {
style, err := NewStyle("test", StyleEntries{
Background: "bg:#ffffff",
})
assert.NoError(t, err)
assert.True(t, style.Has(LineHighlight))
assert.True(t, style.Has(LineNumbersTable))
assert.True(t, style.Has(LineNumbers))
assert.Equal(t, "bg:#e5e5e5", style.Get(LineHighlight).String())
assert.Equal(t, "#7f7f7f bg:#ffffff", style.Get(LineNumbers).String())
assert.Equal(t, "#7f7f7f bg:#ffffff", style.Get(LineNumbersTable).String())
}

0 comments on commit 2a59c2c

Please sign in to comment.