1
0
mirror of https://github.com/alecthomas/chroma.git synced 2025-03-19 21:10:15 +02:00

Synthesise meta style-entries on demand.

This includes line highlighting, numbers, etc.

Fixes #211.
This commit is contained in:
Alec Thomas 2018-12-31 11:33:36 +11:00
parent 69c9a262c3
commit 2a59c2c77e
3 changed files with 46 additions and 33 deletions

View File

@ -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 {

View File

@ -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
@ -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{}

View File

@ -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())
}