From d12529ae612a5d63d38a92e28accfe91d66bf2bf Mon Sep 17 00:00:00 2001 From: Alec Thomas Date: Wed, 19 Jul 2017 23:51:16 -0700 Subject: [PATCH] HTML formatter + import all Pygments styles. --- Makefile | 2 - _tools/pygments2chroma.py | 4 +- _tools/style.py | 62 +++++++++++ cmd/chroma/main.go | 32 +++++- coalesce.go | 18 ++-- coalesce_test.go | 1 + colour.go | 23 +++- formatters/api.go | 19 +++- formatters/html/html.go | 188 +++++++++++++++++++++++++++++++++ formatters/html/html_test.go | 14 +++ formatters/tty_indexed.go | 8 +- lexer.go | 7 +- lexer_test.go | 1 + lexers/go.go | 2 +- lexers/lexer_benchmark_test.go | 33 ++++++ style.go | 139 +++++++++++++++--------- styles/abap.go | 20 ++++ styles/algol.go | 27 +++++ styles/algol_nu.go | 27 +++++ styles/api.go | 9 ++ styles/arduino.go | 27 +++++ styles/autumn.go | 44 ++++++++ styles/borland.go | 53 +++++----- styles/bw.go | 32 ++++++ styles/colorful.go | 60 +++++++++++ styles/default.go | 51 +++++++++ styles/emacs.go | 52 +++++++++ styles/friendly.go | 52 +++++++++ styles/fruity.go | 28 +++++ styles/igor.go | 18 ++++ styles/lovelace.go | 61 +++++++++++ styles/manni.go | 52 +++++++++ styles/monokai.go | 38 +++++++ styles/murphy.go | 60 +++++++++++ styles/native.go | 43 ++++++++ styles/paraiso-dark.go | 46 ++++++++ styles/paraiso-light.go | 46 ++++++++ styles/pastie.go | 53 ++++++++++ styles/perldoc.go | 45 ++++++++ styles/rainbow_dash.go | 48 +++++++++ styles/rrt.go | 20 ++++ styles/swapoff.go | 3 +- styles/tango.go | 80 ++++++++++++++ styles/trac.go | 71 +++++++------ styles/vim.go | 37 +++++++ styles/vs.go | 25 +++++ styles/xcode.go | 31 ++++++ tokentype_string.go | 165 +++++++++++++++-------------- types.go | 18 +++- 49 files changed, 1774 insertions(+), 221 deletions(-) delete mode 100644 Makefile create mode 100644 _tools/style.py create mode 100644 formatters/html/html.go create mode 100644 formatters/html/html_test.go create mode 100644 lexers/lexer_benchmark_test.go create mode 100644 styles/abap.go create mode 100644 styles/algol.go create mode 100644 styles/algol_nu.go create mode 100644 styles/arduino.go create mode 100644 styles/autumn.go create mode 100644 styles/bw.go create mode 100644 styles/colorful.go create mode 100644 styles/default.go create mode 100644 styles/emacs.go create mode 100644 styles/friendly.go create mode 100644 styles/fruity.go create mode 100644 styles/igor.go create mode 100644 styles/lovelace.go create mode 100644 styles/manni.go create mode 100644 styles/monokai.go create mode 100644 styles/murphy.go create mode 100644 styles/native.go create mode 100644 styles/paraiso-dark.go create mode 100644 styles/paraiso-light.go create mode 100644 styles/pastie.go create mode 100644 styles/perldoc.go create mode 100644 styles/rainbow_dash.go create mode 100644 styles/rrt.go create mode 100644 styles/tango.go create mode 100644 styles/vim.go create mode 100644 styles/vs.go create mode 100644 styles/xcode.go diff --git a/Makefile b/Makefile deleted file mode 100644 index 1b01725..0000000 --- a/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -tokentype_string.go: types.go - stringer -type TokenType diff --git a/_tools/pygments2chroma.py b/_tools/pygments2chroma.py index deb0fc6..4d043fe 100644 --- a/_tools/pygments2chroma.py +++ b/_tools/pygments2chroma.py @@ -91,7 +91,7 @@ def resolve_emitter(emitter): raise ValueError('only support "using" with lexer classes, not %r' % args) else: warning('unsupported emitter function %r' % emitter) - emitter = '??' + emitter = '?? %r ??' % emitter elif isinstance(emitter, _TokenType): emitter = str(emitter).replace('.', '')[5:] elif emitter is None: @@ -130,7 +130,7 @@ def translate_rules(rules): if isinstance(regex, str): regex = go_string(regex) elif isinstance(regex, pygments_lexer.words): - regex = '`%s(?:%s)%s`' % (regex.prefix, '|'.join(regex.words), regex.suffix) + regex = go_string('`%s(?:%s)%s`' % (regex.prefix, '|'.join(regex.words), regex.suffix)) else: raise ValueError('expected regex string but got %r' % regex) emitter = resolve_emitter(rule[1]) diff --git a/_tools/style.py b/_tools/style.py new file mode 100644 index 0000000..ef07315 --- /dev/null +++ b/_tools/style.py @@ -0,0 +1,62 @@ +import importlib +import sys + +import pystache +from pygments.style import Style +from pygments.token import Token + + +TEMPLATE = r''' +package styles + +import ( + "github.com/alecthomas/chroma" +) + +// {{upper_name}} style. +var {{upper_name}} = Register(chroma.NewStyle("{{name}}", chroma.StyleEntries{ +{{#styles}} + chroma.{{type}}: "{{style}}", +{{/styles}} +})) +''' + + +def to_camel_case(snake_str): + components = snake_str.split('_') + return ''.join(x.title() for x in components) + + +def translate_token_type(t): + if t == Token: + t = Token.Background + return "".join(map(str, t)) + + +def main(): + name = sys.argv[1] + package_name, symbol_name = sys.argv[2].rsplit(sep=".", maxsplit=1) + + package = importlib.import_module(package_name) + + style_cls = getattr(package, symbol_name) + + assert issubclass(style_cls, Style), 'can only translate from Style subclass' + + styles = dict(style_cls.styles) + bg = "bg:" + style_cls.background_color + if Token in styles: + styles[Token] += " " + bg + else: + styles[Token] = bg + context = { + 'upper_name': style_cls.__name__[:-5], + 'name': name, + 'styles': [{'type': translate_token_type(t), 'style': s} + for t, s in styles.items() if s], + } + print(pystache.render(TEMPLATE, context)) + + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/cmd/chroma/main.go b/cmd/chroma/main.go index 6e0e4f4..e09d8b3 100644 --- a/cmd/chroma/main.go +++ b/cmd/chroma/main.go @@ -14,6 +14,7 @@ import ( "github.com/alecthomas/chroma" "github.com/alecthomas/chroma/formatters" + "github.com/alecthomas/chroma/formatters/html" "github.com/alecthomas/chroma/lexers" "github.com/alecthomas/chroma/styles" ) @@ -22,9 +23,14 @@ var ( profileFlag = kingpin.Flag("profile", "Enable profiling to file.").Hidden().String() listFlag = kingpin.Flag("list", "List lexers, styles and formatters.").Bool() - lexerFlag = kingpin.Flag("lexer", "Lexer to use when formatting.").Default("autodetect").Short('l').String() - styleFlag = kingpin.Flag("style", "Style to use for formatting.").Short('s').Default("swapoff").String() - formatterFlag = kingpin.Flag("formatter", "Formatter to use.").Default("terminal").Short('f').String() + lexerFlag = kingpin.Flag("lexer", "Lexer to use when formatting.").PlaceHolder("autodetect").Short('l').Enum(lexers.Names(true)...) + styleFlag = kingpin.Flag("style", "Style to use for formatting.").Short('s').Default("swapoff").Enum(styles.Names()...) + formatterFlag = kingpin.Flag("formatter", "Formatter to use.").Default("terminal").Short('f').Enum(formatters.Names()...) + + htmlPrefixFlag = kingpin.Flag("html-prefix", "HTML CSS class prefix.").PlaceHolder("PREFIX").String() + htmlStylesFlag = kingpin.Flag("html-styles", "Output HTML CSS styles.").Bool() + htmlOnlyFlag = kingpin.Flag("html-only", "Output HTML fragment.").Bool() + htmlInlineStyleFlag = kingpin.Flag("html-inline-styles", "Output HTML with inline styles (no classes).").Bool() filesArgs = kingpin.Arg("files", "Files to highlight.").ExistingFiles() ) @@ -50,6 +56,24 @@ func main() { } w := bufio.NewWriterSize(os.Stdout, 16384) defer w.Flush() + if *formatterFlag == "html" { + options := []html.Option{} + if *htmlPrefixFlag != "" { + options = append(options, html.ClassPrefix(*htmlPrefixFlag)) + } + if !*htmlOnlyFlag { + options = append(options, html.Standalone()) + } + if !*htmlInlineStyleFlag { + options = append(options, html.WithClasses()) + } + if *htmlStylesFlag { + formatter := html.New(html.WithClasses()) + formatter.WriteStyles(w, styles.Get(*styleFlag)) + return + } + formatters.Register("html", html.New(options...)) + } writer := getWriter(w) if len(*filesArgs) == 0 { contents, err := ioutil.ReadAll(os.Stdin) @@ -100,7 +124,7 @@ func lex(path string, contents string, writer func(*chroma.Token)) { } func selexer(path, contents string) (lexer chroma.Lexer) { - if *lexerFlag != "autodetect" { + if *lexerFlag != "" { return lexers.Get(*lexerFlag) } if path != "" { diff --git a/coalesce.go b/coalesce.go index 19966fe..2d32b6a 100644 --- a/coalesce.go +++ b/coalesce.go @@ -10,18 +10,20 @@ type coalescer struct { } func (d *coalescer) Tokenise(options *TokeniseOptions, text string, out func(*Token)) error { - var last *Token - defer func() { out(last) }() + var prev *Token return d.Lexer.Tokenise(options, text, func(token *Token) { - if last == nil { - last = token + if prev == nil { + prev = token } else { - if last.Type == token.Type && len(last.Value) < 8192 { - last.Value += token.Value + if prev.Type == token.Type && len(prev.Value) < 8192 { + prev.Value += token.Value } else { - out(last) - last = token + out(prev) + prev = token } } + if token.Type == EOF { + out(token) + } }) } diff --git a/coalesce_test.go b/coalesce_test.go index 5b9f4b9..02964f9 100644 --- a/coalesce_test.go +++ b/coalesce_test.go @@ -16,6 +16,7 @@ func TestCoalesce(t *testing.T) { require.NoError(t, err) expected := []*Token{ &Token{Punctuation, "!@#$"}, + &Token{EOF, ""}, } require.Equal(t, expected, actual) } diff --git a/colour.go b/colour.go index d421be7..675590e 100644 --- a/colour.go +++ b/colour.go @@ -25,13 +25,32 @@ var ANSI2RGB = map[string]string{ "#ansifuchsia": "ff00ff", "#ansiturquoise": "00ffff", "#ansiwhite": "ffffff", + + // Aliases without the "ansi" prefix, because...why? + "#black": "000000", + "#darkred": "7f0000", + "#darkgreen": "007f00", + "#brown": "7f7fe0", + "#darkblue": "00007f", + "#purple": "7f007f", + "#teal": "007f7f", + "#lightgray": "e5e5e5", + // Normal + "#darkgray": "555555", + "#red": "ff0000", + "#green": "00ff00", + "#yellow": "ffff00", + "#blue": "0000ff", + "#fuchsia": "ff00ff", + "#turquoise": "00ffff", + "#white": "ffffff", } // Colour represents an RGB colour. type Colour int32 -// ParseColour in the forms #rgb, #rrggbb, or #ansi. Will panic -// if colour is in an invalid format. +// ParseColour in the forms #rgb, #rrggbb, #ansi, or #. +// Will panic if colour is in an invalid format. func ParseColour(colour string) Colour { colour = normaliseColour(colour) n, err := strconv.ParseUint(colour, 16, 32) diff --git a/formatters/api.go b/formatters/api.go index 29c43b6..f555533 100644 --- a/formatters/api.go +++ b/formatters/api.go @@ -4,12 +4,16 @@ import ( "io" "github.com/alecthomas/chroma" + "github.com/alecthomas/chroma/formatters/html" ) // NoOp formatter. -var NoOp = Register("noop", chroma.FormatterFunc(func(w io.Writer, s *chroma.Style) (func(*chroma.Token), error) { - return func(t *chroma.Token) { io.WriteString(w, t.Value) }, nil -})) +var ( + NoOp = Register("noop", chroma.FormatterFunc(func(w io.Writer, s *chroma.Style) (func(*chroma.Token), error) { + return func(t *chroma.Token) { io.WriteString(w, t.Value) }, nil + })) + htmlFull = Register("html", html.New(html.Standalone(), html.WithClasses())) +) // Fallback formatter. var Fallback = NoOp @@ -17,6 +21,15 @@ var Fallback = NoOp // Registry of Formatters. var Registry = map[string]chroma.Formatter{} +// Names of registered formatters. +func Names() []string { + out := []string{} + for name := range Registry { + out = append(out, name) + } + return out +} + // Get formatter by name. // // If the given formatter is not found, the Fallback formatter will be returned. diff --git a/formatters/html/html.go b/formatters/html/html.go new file mode 100644 index 0000000..1d8170f --- /dev/null +++ b/formatters/html/html.go @@ -0,0 +1,188 @@ +package html + +import ( + "fmt" + "html" + "io" + "sort" + "strings" + + "github.com/alecthomas/chroma" +) + +// Option sets an option of the HTML formatter. +type Option func(h *HTMLFormatter) + +// Standalone configures the HTML formatter for generating a standalone HTML document. +func Standalone() Option { return func(h *HTMLFormatter) { h.standalone = true } } + +// ClassPrefix sets the CSS class prefix. +func ClassPrefix(prefix string) Option { return func(h *HTMLFormatter) { h.prefix = prefix } } + +// WithClasses emits HTML using CSS classes, rather than inline styles. +func WithClasses() Option { return func(h *HTMLFormatter) { h.classes = true } } + +// New HTML formatter. +func New(options ...Option) *HTMLFormatter { + h := &HTMLFormatter{} + for _, option := range options { + option(h) + } + return h +} + +type HTMLFormatter struct { + standalone bool + prefix string + classes bool +} + +func (h *HTMLFormatter) Format(w io.Writer, style *chroma.Style) (func(*chroma.Token), error) { + if h.classes { + return h.formatWithClasses(w, style) + } + return h.formatWithoutClasses(w, style) +} + +func (h *HTMLFormatter) formatWithoutClasses(w io.Writer, style *chroma.Style) (func(*chroma.Token), error) { + classes := h.typeStyles(style) + bg := compressStyle(classes[chroma.Background]) + if h.standalone { + fmt.Fprint(w, "\n") + fmt.Fprintf(w, "\n", bg) + } + fmt.Fprintf(w, "
\n", bg)
+	for t, style := range classes {
+		classes[t] = compressStyle(style)
+	}
+	return func(token *chroma.Token) {
+		if token.Type == chroma.EOF {
+			fmt.Fprint(w, "
\n") + if h.standalone { + fmt.Fprint(w, "\n") + fmt.Fprint(w, "\n") + } + } else { + html := html.EscapeString(token.String()) + style := classes[token.Type] + if style == "" { + style = classes[token.Type.SubCategory()] + if style == "" { + style = classes[token.Type.Category()] + } + } + if style == "" { + fmt.Fprint(w, html) + } else { + fmt.Fprintf(w, "%s", style, html) + } + } + }, nil +} + +func compressStyle(s string) string { + s = strings.Replace(s, " ", "", -1) + parts := strings.Split(s, ";") + out := []string{} + for _, p := range parts { + if strings.Contains(p, "#") { + c := p[len(p)-6:] + if c[0] == c[1] && c[2] == c[3] && c[4] == c[5] { + p = p[:len(p)-6] + c[0:1] + c[2:3] + c[4:5] + } + } + out = append(out, p) + } + return strings.Join(out, ";") +} + +func (h *HTMLFormatter) formatWithClasses(w io.Writer, style *chroma.Style) (func(*chroma.Token), error) { + classes := h.typeStyles(style) + if h.standalone { + fmt.Fprint(w, "\n") + } + fmt.Fprint(w, "\n") + if h.standalone { + fmt.Fprint(w, "\n") + } + fmt.Fprint(w, "
\n")
+	return func(token *chroma.Token) {
+		if h.standalone && token.Type == chroma.EOF {
+			fmt.Fprint(w, "\n")
+			fmt.Fprint(w, "\n")
+		} else {
+			tt := token.Type
+			class := classes[tt]
+			if class == "" {
+				tt = tt.SubCategory()
+				class = classes[tt]
+				if class == "" {
+					tt = tt.Category()
+					class = classes[tt]
+				}
+			}
+			if class == "" {
+				fmt.Fprint(w, token)
+			} else {
+				html := html.EscapeString(token.String())
+				fmt.Fprintf(w, "%s", h.prefix, int(tt), html)
+			}
+		}
+	}, nil
+}
+
+// WriteStyles writes style definitions.
+func (h *HTMLFormatter) WriteStyles(w io.Writer, style *chroma.Style) {
+	classes := h.typeStyles(style)
+	fmt.Fprintf(w, "/* %s */ .chroma { %s }\n", chroma.Background, classes[chroma.Background])
+	tts := []int{}
+	for tt := range classes {
+		tts = append(tts, int(tt))
+	}
+	sort.Ints(tts)
+	for _, ti := range tts {
+		tt := chroma.TokenType(ti)
+		styles := classes[tt]
+		if tt < 0 {
+			continue
+		}
+		fmt.Fprintf(w, "/* %s */ .chroma .%ss%x { %s }\n", tt, h.prefix, int(tt), styles)
+	}
+}
+
+func (h *HTMLFormatter) typeStyles(style *chroma.Style) map[chroma.TokenType]string {
+	// Generate maps.
+	bg := style.Get(chroma.Background)
+	classes := map[chroma.TokenType]string{}
+	for t := range style.Entries {
+		e := style.Entries[t]
+		if t != chroma.Background {
+			e = e.Sub(bg)
+		}
+		styles := h.class(e)
+		classes[t] = strings.Join(styles, "; ")
+	}
+	return classes
+}
+
+func (h *HTMLFormatter) class(e *chroma.StyleEntry) []string {
+	styles := []string{}
+	if e.Colour.IsSet() {
+		styles = append(styles, "color: "+e.Colour.String())
+	}
+	if e.Background.IsSet() {
+		styles = append(styles, "background-color: "+e.Background.String())
+	}
+	if e.Bold {
+		styles = append(styles, "font-weight: bold")
+	}
+	if e.Italic {
+		styles = append(styles, "font-style: italic")
+	}
+	return styles
+}
diff --git a/formatters/html/html_test.go b/formatters/html/html_test.go
new file mode 100644
index 0000000..7761d63
--- /dev/null
+++ b/formatters/html/html_test.go
@@ -0,0 +1,14 @@
+package html
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestCompressStyle(t *testing.T) {
+	style := "color: #888888; background-color: #ffffff"
+	actual := compressStyle(style)
+	expected := "color:#888;background-color:#fff"
+	require.Equal(t, expected, actual)
+}
diff --git a/formatters/tty_indexed.go b/formatters/tty_indexed.go
index 19de55b..d844f4a 100644
--- a/formatters/tty_indexed.go
+++ b/formatters/tty_indexed.go
@@ -242,10 +242,10 @@ func (c *indexedTTYFormatter) Format(w io.Writer, style *chroma.Style) (func(*ch
 		if !ok {
 			clr, ok = theme[token.Type.SubCategory()]
 			if !ok {
-				clr, ok = theme[token.Type.Category()]
-				if !ok {
-					clr = theme[chroma.InheritStyle]
-				}
+				clr = theme[token.Type.Category()]
+				// if !ok {
+				// 	clr = theme[chroma.InheritStyle]
+				// }
 			}
 		}
 		if clr != "" {
diff --git a/lexer.go b/lexer.go
index 853e870..d3e0cac 100644
--- a/lexer.go
+++ b/lexer.go
@@ -68,8 +68,12 @@ type TokeniseOptions struct {
 	State string
 }
 
+// A Lexer for tokenising source code.
 type Lexer interface {
+	// Config describing the features of the Lexer.
 	Config() *Config
+	// Tokenise text and call out for each generated token.
+	// nil will be passed to out to signify the end of the stream.
 	Tokenise(options *TokeniseOptions, text string, out func(*Token)) error
 }
 
@@ -95,7 +99,7 @@ func (l Lexers) Pick(text string) Lexer {
 	return picked
 }
 
-// Analyser determines if this lexer is appropriate for the given text.
+// Analyser determines how appropriate this lexer is for the given text.
 type Analyser interface {
 	AnalyseText(text string) float32
 }
@@ -287,6 +291,7 @@ func (r *RegexLexer) Tokenise(options *TokeniseOptions, text string, out func(*T
 			rule.Type.Emit(state.Groups, r, out)
 		}
 	}
+	out(&Token{Type: EOF})
 	return nil
 }
 
diff --git a/lexer_test.go b/lexer_test.go
index 60e4a50..fe1ac6e 100644
--- a/lexer_test.go
+++ b/lexer_test.go
@@ -47,6 +47,7 @@ func TestSimpleLexer(t *testing.T) {
 		{Whitespace, " "},
 		{LiteralString, "10"},
 		{Whitespace, "\n"},
+		{EOF, ""},
 	}
 	require.Equal(t, expected, actual)
 }
diff --git a/lexers/go.go b/lexers/go.go
index 4d8080d..64a4b88 100644
--- a/lexers/go.go
+++ b/lexers/go.go
@@ -68,7 +68,7 @@ var Go = Register(MustNewLexer(
 		},
 	},
 ).SetAnalyser(func(text string) float32 {
-	if strings.Contains(text, "fmt.") {
+	if strings.Contains(text, "fmt.") && strings.Contains(text, "package ") {
 		return 0.5
 	}
 	if strings.Contains(text, "package ") {
diff --git a/lexers/lexer_benchmark_test.go b/lexers/lexer_benchmark_test.go
new file mode 100644
index 0000000..3617306
--- /dev/null
+++ b/lexers/lexer_benchmark_test.go
@@ -0,0 +1,33 @@
+package lexers
+
+import (
+	"testing"
+
+	"github.com/alecthomas/chroma"
+)
+
+const lexerBenchSource = `package chroma
+
+import (
+	"io"
+)
+
+// A Formatter for Chroma lexers.
+type Formatter interface {
+	// Format returns a formatting function for tokens.
+	Format(w io.Writer, style *Style) (func(*Token), error)
+}
+
+// A FormatterFunc is a Formatter implemented as a function.
+type FormatterFunc func(io.Writer, *Style) (func(*Token), error)
+
+func (f FormatterFunc) Format(w io.Writer, s *Style) (func(*Token), error) {
+	return f(w, s)
+}
+`
+
+func Benchmark(b *testing.B) {
+	for i := 0; i < b.N; i++ {
+		Go.Tokenise(nil, lexerBenchSource, func(t *chroma.Token) {})
+	}
+}
diff --git a/style.go b/style.go
index 148ece2..7922338 100644
--- a/style.go
+++ b/style.go
@@ -1,9 +1,9 @@
 package chroma
 
-import "strings"
-
-// InheritStyle from entry with this key.
-const InheritStyle TokenType = -1
+import (
+	"sort"
+	"strings"
+)
 
 // A StyleEntry in the Style map.
 type StyleEntry struct {
@@ -17,31 +17,54 @@ type StyleEntry struct {
 	Underline bool
 }
 
-func (e *StyleEntry) String() string {
+func (s *StyleEntry) String() string {
 	out := []string{}
-	if e.Bold {
+	if s.Bold {
 		out = append(out, "bold")
 	}
-	if e.Italic {
+	if s.Italic {
 		out = append(out, "italic")
 	}
-	if e.Underline {
+	if s.Underline {
 		out = append(out, "underline")
 	}
-	if e.Colour.IsSet() {
-		out = append(out, e.Colour.String())
+	if s.Colour.IsSet() {
+		out = append(out, s.Colour.String())
 	}
-	if e.Background.IsSet() {
-		out = append(out, "bg:"+e.Background.String())
+	if s.Background.IsSet() {
+		out = append(out, "bg:"+s.Background.String())
 	}
-	if e.Border.IsSet() {
-		out = append(out, "border:"+e.Border.String())
+	if s.Border.IsSet() {
+		out = append(out, "border:"+s.Border.String())
 	}
 	return strings.Join(out, " ")
 }
 
-func (e *StyleEntry) IsZero() bool {
-	return e.Colour == 0 && e.Background == 0 && e.Border == 0 && !e.Bold && !e.Italic && !e.Underline
+func (s *StyleEntry) IsZero() bool {
+	return s.Colour == 0 && s.Background == 0 && s.Border == 0 && !s.Bold && !s.Italic && !s.Underline
+}
+
+func (s *StyleEntry) Sub(e *StyleEntry) *StyleEntry {
+	out := &StyleEntry{}
+	if e.Colour != s.Colour {
+		out.Colour = s.Colour
+	}
+	if e.Background != s.Background {
+		out.Background = s.Background
+	}
+	if e.Bold != s.Bold {
+		out.Bold = s.Bold
+	}
+	if e.Italic != s.Italic {
+		out.Italic = s.Italic
+	}
+	if e.Underline != s.Underline {
+		out.Underline = s.Underline
+	}
+	if e.Border != s.Border {
+		out.Border = s.Border
+	}
+	return out
 }
 
 // StyleEntries mapping TokenType to colour definition.
@@ -50,14 +73,11 @@ type StyleEntries map[TokenType]string
 // NewStyle creates a new style definition.
 func NewStyle(name string, entries StyleEntries) *Style {
 	s := &Style{
-		Name: name,
-		Entries: map[TokenType]*StyleEntry{
-			InheritStyle: &StyleEntry{},
-		},
-	}
-	for tt, entry := range entries {
-		s.Add(tt, entry)
+		Name:    name,
+		Entries: map[TokenType]*StyleEntry{},
 	}
+	s.Add(Background, "")
+	s.AddAll(entries)
 	return s
 }
 
@@ -66,6 +86,7 @@ func NewStyle(name string, entries StyleEntries) *Style {
 // See http://pygments.org/docs/styles/ for details. Semantics are intended to be identical.
 type Style struct {
 	Name    string
+	Scheme  Scheme
 	Entries map[TokenType]*StyleEntry
 }
 
@@ -78,29 +99,66 @@ func (s *Style) Get(ttype TokenType) *StyleEntry {
 		if out == nil {
 			out = s.Entries[ttype.Category()]
 			if out == nil {
-				out = s.Entries[InheritStyle]
+				out = s.Entries[Background]
 			}
 		}
 	}
 	return out
 }
 
-// Add an StyleEntry to the Style map.
+func (s *Style) AddAll(entries StyleEntries) *Style {
+	tis := []int{}
+	for tt := range entries {
+		tis = append(tis, int(tt))
+	}
+	sort.Ints(tis)
+	for _, ti := range tis {
+		tt := TokenType(ti)
+		entry := entries[tt]
+		s.Add(tt, entry)
+	}
+	return s
+}
+
+// Add a StyleEntry to the Style map.
 //
 // See http://pygments.org/docs/styles/#style-rules for details.
 func (s *Style) Add(ttype TokenType, entry string) *Style { // nolint: gocyclo
-	out := &StyleEntry{}
 	dupl := s.Entries[ttype.SubCategory()]
 	if dupl == nil {
 		dupl = s.Entries[ttype.Category()]
 		if dupl == nil {
-			dupl = s.Entries[InheritStyle]
+			dupl = s.Entries[Background]
+			if dupl == nil {
+				dupl = &StyleEntry{}
+			}
 		}
 	}
 	parent := &StyleEntry{}
 	// Duplicate ancestor node.
 	*parent = *dupl
-	for _, part := range strings.Fields(entry) {
+	s.Entries[ttype] = ParseStyleEntry(parent, entry)
+	return s
+}
+
+// ParseStyleEntry parses a Pygments style entry.
+func ParseStyleEntry(parent *StyleEntry, entry string) *StyleEntry { // nolint: gocyclo
+	out := &StyleEntry{}
+	parts := strings.Fields(entry)
+	// Check if parent style should be inherited...
+	if parent != nil {
+		inherit := true
+		for _, part := range parts {
+			if part == "noinherit" {
+				inherit = false
+				break
+			}
+		}
+		if inherit {
+			*out = *parent
+		}
+	}
+	for _, part := range parts {
 		switch {
 		case part == "italic":
 			out.Italic = true
@@ -114,8 +172,8 @@ func (s *Style) Add(ttype TokenType, entry string) *Style { // nolint: gocyclo
 			out.Underline = true
 		case part == "nounderline":
 			out.Underline = false
-		case part == "noinherit":
-			parent = &StyleEntry{}
+		case part == "bg:":
+			out.Background = 0
 		case strings.HasPrefix(part, "bg:#"):
 			out.Background = ParseColour(part[3:])
 		case strings.HasPrefix(part, "border:#"):
@@ -126,24 +184,5 @@ func (s *Style) Add(ttype TokenType, entry string) *Style { // nolint: gocyclo
 			panic("unsupported style entry " + part)
 		}
 	}
-	if parent.Colour != 0 && out.Colour == 0 {
-		out.Colour = parent.Colour
-	}
-	if parent.Background != 0 && out.Background == 0 {
-		out.Background = parent.Background
-	}
-	if parent.Border != 0 && out.Border == 0 {
-		out.Border = parent.Border
-	}
-	if parent.Bold && !out.Bold {
-		out.Bold = true
-	}
-	if parent.Italic && !out.Italic {
-		out.Italic = true
-	}
-	if parent.Underline && !out.Underline {
-		out.Underline = true
-	}
-	s.Entries[ttype] = out
-	return s
+	return out
 }
diff --git a/styles/abap.go b/styles/abap.go
new file mode 100644
index 0000000..caf131d
--- /dev/null
+++ b/styles/abap.go
@@ -0,0 +1,20 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Abap style.
+var Abap = Register(chroma.NewStyle("abap", chroma.StyleEntries{
+    chroma.Comment: "italic #888",
+    chroma.CommentSpecial: "#888",
+    chroma.Keyword: "#00f",
+    chroma.OperatorWord: "#00f",
+    chroma.Name: "#000",
+    chroma.LiteralNumber: "#3af",
+    chroma.LiteralString: "#5a2",
+    chroma.Error: "#F00",
+    chroma.Background: " bg:#ffffff",
+}))
+
diff --git a/styles/algol.go b/styles/algol.go
new file mode 100644
index 0000000..5534c6c
--- /dev/null
+++ b/styles/algol.go
@@ -0,0 +1,27 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Algol style.
+var Algol = Register(chroma.NewStyle("algol", chroma.StyleEntries{
+    chroma.Comment: "italic #888",
+    chroma.CommentPreproc: "bold noitalic #888",
+    chroma.CommentSpecial: "bold noitalic #888",
+    chroma.Keyword: "underline bold",
+    chroma.KeywordDeclaration: "italic",
+    chroma.NameBuiltin: "bold italic",
+    chroma.NameBuiltinPseudo: "bold italic",
+    chroma.NameNamespace: "bold italic #666",
+    chroma.NameClass: "bold italic #666",
+    chroma.NameFunction: "bold italic #666",
+    chroma.NameVariable: "bold italic #666",
+    chroma.NameConstant: "bold italic #666",
+    chroma.OperatorWord: "bold",
+    chroma.LiteralString: "italic #666",
+    chroma.Error: "border:#FF0000",
+    chroma.Background: " bg:#ffffff",
+}))
+
diff --git a/styles/algol_nu.go b/styles/algol_nu.go
new file mode 100644
index 0000000..6c2b8e2
--- /dev/null
+++ b/styles/algol_nu.go
@@ -0,0 +1,27 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Algol_Nu style.
+var Algol_Nu = Register(chroma.NewStyle("algol_nu", chroma.StyleEntries{
+    chroma.Comment: "italic #888",
+    chroma.CommentPreproc: "bold noitalic #888",
+    chroma.CommentSpecial: "bold noitalic #888",
+    chroma.Keyword: "bold",
+    chroma.KeywordDeclaration: "italic",
+    chroma.NameBuiltin: "bold italic",
+    chroma.NameBuiltinPseudo: "bold italic",
+    chroma.NameNamespace: "bold italic #666",
+    chroma.NameClass: "bold italic #666",
+    chroma.NameFunction: "bold italic #666",
+    chroma.NameVariable: "bold italic #666",
+    chroma.NameConstant: "bold italic #666",
+    chroma.OperatorWord: "bold",
+    chroma.LiteralString: "italic #666",
+    chroma.Error: "border:#FF0000",
+    chroma.Background: " bg:#ffffff",
+}))
+
diff --git a/styles/api.go b/styles/api.go
index 4c410a5..d0f5a61 100644
--- a/styles/api.go
+++ b/styles/api.go
@@ -14,6 +14,15 @@ func Register(style *chroma.Style) *chroma.Style {
 	return style
 }
 
+// Names of all available styles.
+func Names() []string {
+	out := []string{}
+	for name := range Registry {
+		out = append(out, name)
+	}
+	return out
+}
+
 // Get named style, or Fallback.
 func Get(name string) *chroma.Style {
 	if style, ok := Registry[name]; ok {
diff --git a/styles/arduino.go b/styles/arduino.go
new file mode 100644
index 0000000..57da03f
--- /dev/null
+++ b/styles/arduino.go
@@ -0,0 +1,27 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Arduino style.
+var Arduino = Register(chroma.NewStyle("arduino", chroma.StyleEntries{
+    chroma.Error: "#a61717",
+    chroma.Comment: "#95a5a6",
+    chroma.CommentPreproc: "#728E00",
+    chroma.Keyword: "#728E00",
+    chroma.KeywordConstant: "#00979D",
+    chroma.KeywordPseudo: "#00979D",
+    chroma.KeywordReserved: "#00979D",
+    chroma.KeywordType: "#00979D",
+    chroma.Operator: "#728E00",
+    chroma.Name: "#434f54",
+    chroma.NameBuiltin: "#728E00",
+    chroma.NameFunction: "#D35400",
+    chroma.NameOther: "#728E00",
+    chroma.LiteralNumber: "#8A7B52",
+    chroma.LiteralString: "#7F8C8D",
+    chroma.Background: " bg:#ffffff",
+}))
+
diff --git a/styles/autumn.go b/styles/autumn.go
new file mode 100644
index 0000000..43b92bb
--- /dev/null
+++ b/styles/autumn.go
@@ -0,0 +1,44 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Autumn style.
+var Autumn = Register(chroma.NewStyle("autumn", chroma.StyleEntries{
+    chroma.TextWhitespace: "#bbbbbb",
+    chroma.Comment: "italic #aaaaaa",
+    chroma.CommentPreproc: "noitalic #4c8317",
+    chroma.CommentSpecial: "italic #0000aa",
+    chroma.Keyword: "#0000aa",
+    chroma.KeywordType: "#00aaaa",
+    chroma.OperatorWord: "#0000aa",
+    chroma.NameBuiltin: "#00aaaa",
+    chroma.NameFunction: "#00aa00",
+    chroma.NameClass: "underline #00aa00",
+    chroma.NameNamespace: "underline #00aaaa",
+    chroma.NameVariable: "#aa0000",
+    chroma.NameConstant: "#aa0000",
+    chroma.NameEntity: "bold #800",
+    chroma.NameAttribute: "#1e90ff",
+    chroma.NameTag: "bold #1e90ff",
+    chroma.NameDecorator: "#888888",
+    chroma.LiteralString: "#aa5500",
+    chroma.LiteralStringSymbol: "#0000aa",
+    chroma.LiteralStringRegex: "#009999",
+    chroma.LiteralNumber: "#009999",
+    chroma.GenericHeading: "bold #000080",
+    chroma.GenericSubheading: "bold #800080",
+    chroma.GenericDeleted: "#aa0000",
+    chroma.GenericInserted: "#00aa00",
+    chroma.GenericError: "#aa0000",
+    chroma.GenericEmph: "italic",
+    chroma.GenericStrong: "bold",
+    chroma.GenericPrompt: "#555555",
+    chroma.GenericOutput: "#888888",
+    chroma.GenericTraceback: "#aa0000",
+    chroma.Error: "#F00 bg:#FAA",
+    chroma.Background: " bg:#ffffff",
+}))
+
diff --git a/styles/borland.go b/styles/borland.go
index 43d450f..4179734 100644
--- a/styles/borland.go
+++ b/styles/borland.go
@@ -1,35 +1,34 @@
+
 package styles
 
 import (
-	"github.com/alecthomas/chroma"
+    "github.com/alecthomas/chroma"
 )
 
 // Borland style.
 var Borland = Register(chroma.NewStyle("borland", chroma.StyleEntries{
-	chroma.Whitespace: "#bbbbbb",
-
-	chroma.Comment:        "italic #008800",
-	chroma.CommentPreproc: "noitalic #008080",
-	chroma.CommentSpecial: "noitalic bold",
-
-	chroma.String:        "#0000FF",
-	chroma.StringChar:    "#800080",
-	chroma.Number:        "#0000FF",
-	chroma.Keyword:       "bold #000080",
-	chroma.OperatorWord:  "bold",
-	chroma.NameTag:       "bold #000080",
-	chroma.NameAttribute: "#FF0000",
-
-	chroma.GenericHeading:    "#999999",
-	chroma.GenericSubheading: "#aaaaaa",
-	chroma.GenericDeleted:    "bg:#ffdddd #000000",
-	chroma.GenericInserted:   "bg:#ddffdd #000000",
-	chroma.GenericError:      "#aa0000",
-	chroma.GenericEmph:       "italic",
-	chroma.GenericStrong:     "bold",
-	chroma.GenericPrompt:     "#555555",
-	chroma.GenericOutput:     "#888888",
-	chroma.GenericTraceback:  "#aa0000",
-
-	chroma.Error: "bg:#e3d2d2 #a61717",
+    chroma.TextWhitespace: "#bbbbbb",
+    chroma.Comment: "italic #008800",
+    chroma.CommentPreproc: "noitalic #008080",
+    chroma.CommentSpecial: "noitalic bold",
+    chroma.LiteralString: "#0000FF",
+    chroma.LiteralStringChar: "#800080",
+    chroma.LiteralNumber: "#0000FF",
+    chroma.Keyword: "bold #000080",
+    chroma.OperatorWord: "bold",
+    chroma.NameTag: "bold #000080",
+    chroma.NameAttribute: "#FF0000",
+    chroma.GenericHeading: "#999999",
+    chroma.GenericSubheading: "#aaaaaa",
+    chroma.GenericDeleted: "bg:#ffdddd #000000",
+    chroma.GenericInserted: "bg:#ddffdd #000000",
+    chroma.GenericError: "#aa0000",
+    chroma.GenericEmph: "italic",
+    chroma.GenericStrong: "bold",
+    chroma.GenericPrompt: "#555555",
+    chroma.GenericOutput: "#888888",
+    chroma.GenericTraceback: "#aa0000",
+    chroma.Error: "bg:#e3d2d2 #a61717",
+    chroma.Background: " bg:#ffffff",
 }))
+
diff --git a/styles/bw.go b/styles/bw.go
new file mode 100644
index 0000000..ec4b557
--- /dev/null
+++ b/styles/bw.go
@@ -0,0 +1,32 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// BlackWhite style.
+var BlackWhite = Register(chroma.NewStyle("bw", chroma.StyleEntries{
+    chroma.Comment: "italic",
+    chroma.CommentPreproc: "noitalic",
+    chroma.Keyword: "bold",
+    chroma.KeywordPseudo: "nobold",
+    chroma.KeywordType: "nobold",
+    chroma.OperatorWord: "bold",
+    chroma.NameClass: "bold",
+    chroma.NameNamespace: "bold",
+    chroma.NameException: "bold",
+    chroma.NameEntity: "bold",
+    chroma.NameTag: "bold",
+    chroma.LiteralString: "italic",
+    chroma.LiteralStringInterpol: "bold",
+    chroma.LiteralStringEscape: "bold",
+    chroma.GenericHeading: "bold",
+    chroma.GenericSubheading: "bold",
+    chroma.GenericEmph: "italic",
+    chroma.GenericStrong: "bold",
+    chroma.GenericPrompt: "bold",
+    chroma.Error: "border:#FF0000",
+    chroma.Background: " bg:#ffffff",
+}))
+
diff --git a/styles/colorful.go b/styles/colorful.go
new file mode 100644
index 0000000..2cec919
--- /dev/null
+++ b/styles/colorful.go
@@ -0,0 +1,60 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Colorful style.
+var Colorful = Register(chroma.NewStyle("colorful", chroma.StyleEntries{
+    chroma.TextWhitespace: "#bbbbbb",
+    chroma.Comment: "#888",
+    chroma.CommentPreproc: "#579",
+    chroma.CommentSpecial: "bold #cc0000",
+    chroma.Keyword: "bold #080",
+    chroma.KeywordPseudo: "#038",
+    chroma.KeywordType: "#339",
+    chroma.Operator: "#333",
+    chroma.OperatorWord: "bold #000",
+    chroma.NameBuiltin: "#007020",
+    chroma.NameFunction: "bold #06B",
+    chroma.NameClass: "bold #B06",
+    chroma.NameNamespace: "bold #0e84b5",
+    chroma.NameException: "bold #F00",
+    chroma.NameVariable: "#963",
+    chroma.NameVariableInstance: "#33B",
+    chroma.NameVariableClass: "#369",
+    chroma.NameVariableGlobal: "bold #d70",
+    chroma.NameConstant: "bold #036",
+    chroma.NameLabel: "bold #970",
+    chroma.NameEntity: "bold #800",
+    chroma.NameAttribute: "#00C",
+    chroma.NameTag: "#070",
+    chroma.NameDecorator: "bold #555",
+    chroma.LiteralString: "bg:#fff0f0",
+    chroma.LiteralStringChar: "#04D bg:",
+    chroma.LiteralStringDoc: "#D42 bg:",
+    chroma.LiteralStringInterpol: "bg:#eee",
+    chroma.LiteralStringEscape: "bold #666",
+    chroma.LiteralStringRegex: "bg:#fff0ff #000",
+    chroma.LiteralStringSymbol: "#A60 bg:",
+    chroma.LiteralStringOther: "#D20",
+    chroma.LiteralNumber: "bold #60E",
+    chroma.LiteralNumberInteger: "bold #00D",
+    chroma.LiteralNumberFloat: "bold #60E",
+    chroma.LiteralNumberHex: "bold #058",
+    chroma.LiteralNumberOct: "bold #40E",
+    chroma.GenericHeading: "bold #000080",
+    chroma.GenericSubheading: "bold #800080",
+    chroma.GenericDeleted: "#A00000",
+    chroma.GenericInserted: "#00A000",
+    chroma.GenericError: "#FF0000",
+    chroma.GenericEmph: "italic",
+    chroma.GenericStrong: "bold",
+    chroma.GenericPrompt: "bold #c65d09",
+    chroma.GenericOutput: "#888",
+    chroma.GenericTraceback: "#04D",
+    chroma.Error: "#F00 bg:#FAA",
+    chroma.Background: " bg:#ffffff",
+}))
+
diff --git a/styles/default.go b/styles/default.go
new file mode 100644
index 0000000..720d66b
--- /dev/null
+++ b/styles/default.go
@@ -0,0 +1,51 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Default style.
+var Default = Register(chroma.NewStyle("default", chroma.StyleEntries{
+    chroma.TextWhitespace: "#bbbbbb",
+    chroma.Comment: "italic #408080",
+    chroma.CommentPreproc: "noitalic #BC7A00",
+    chroma.Keyword: "bold #008000",
+    chroma.KeywordPseudo: "nobold",
+    chroma.KeywordType: "nobold #B00040",
+    chroma.Operator: "#666666",
+    chroma.OperatorWord: "bold #AA22FF",
+    chroma.NameBuiltin: "#008000",
+    chroma.NameFunction: "#0000FF",
+    chroma.NameClass: "bold #0000FF",
+    chroma.NameNamespace: "bold #0000FF",
+    chroma.NameException: "bold #D2413A",
+    chroma.NameVariable: "#19177C",
+    chroma.NameConstant: "#880000",
+    chroma.NameLabel: "#A0A000",
+    chroma.NameEntity: "bold #999999",
+    chroma.NameAttribute: "#7D9029",
+    chroma.NameTag: "bold #008000",
+    chroma.NameDecorator: "#AA22FF",
+    chroma.LiteralString: "#BA2121",
+    chroma.LiteralStringDoc: "italic",
+    chroma.LiteralStringInterpol: "bold #BB6688",
+    chroma.LiteralStringEscape: "bold #BB6622",
+    chroma.LiteralStringRegex: "#BB6688",
+    chroma.LiteralStringSymbol: "#19177C",
+    chroma.LiteralStringOther: "#008000",
+    chroma.LiteralNumber: "#666666",
+    chroma.GenericHeading: "bold #000080",
+    chroma.GenericSubheading: "bold #800080",
+    chroma.GenericDeleted: "#A00000",
+    chroma.GenericInserted: "#00A000",
+    chroma.GenericError: "#FF0000",
+    chroma.GenericEmph: "italic",
+    chroma.GenericStrong: "bold",
+    chroma.GenericPrompt: "bold #000080",
+    chroma.GenericOutput: "#888",
+    chroma.GenericTraceback: "#04D",
+    chroma.Error: "border:#FF0000",
+    chroma.Background: " bg:#f8f8f8",
+}))
+
diff --git a/styles/emacs.go b/styles/emacs.go
new file mode 100644
index 0000000..cc06440
--- /dev/null
+++ b/styles/emacs.go
@@ -0,0 +1,52 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Emacs style.
+var Emacs = Register(chroma.NewStyle("emacs", chroma.StyleEntries{
+    chroma.TextWhitespace: "#bbbbbb",
+    chroma.Comment: "italic #008800",
+    chroma.CommentPreproc: "noitalic",
+    chroma.CommentSpecial: "noitalic bold",
+    chroma.Keyword: "bold #AA22FF",
+    chroma.KeywordPseudo: "nobold",
+    chroma.KeywordType: "bold #00BB00",
+    chroma.Operator: "#666666",
+    chroma.OperatorWord: "bold #AA22FF",
+    chroma.NameBuiltin: "#AA22FF",
+    chroma.NameFunction: "#00A000",
+    chroma.NameClass: "#0000FF",
+    chroma.NameNamespace: "bold #0000FF",
+    chroma.NameException: "bold #D2413A",
+    chroma.NameVariable: "#B8860B",
+    chroma.NameConstant: "#880000",
+    chroma.NameLabel: "#A0A000",
+    chroma.NameEntity: "bold #999999",
+    chroma.NameAttribute: "#BB4444",
+    chroma.NameTag: "bold #008000",
+    chroma.NameDecorator: "#AA22FF",
+    chroma.LiteralString: "#BB4444",
+    chroma.LiteralStringDoc: "italic",
+    chroma.LiteralStringInterpol: "bold #BB6688",
+    chroma.LiteralStringEscape: "bold #BB6622",
+    chroma.LiteralStringRegex: "#BB6688",
+    chroma.LiteralStringSymbol: "#B8860B",
+    chroma.LiteralStringOther: "#008000",
+    chroma.LiteralNumber: "#666666",
+    chroma.GenericHeading: "bold #000080",
+    chroma.GenericSubheading: "bold #800080",
+    chroma.GenericDeleted: "#A00000",
+    chroma.GenericInserted: "#00A000",
+    chroma.GenericError: "#FF0000",
+    chroma.GenericEmph: "italic",
+    chroma.GenericStrong: "bold",
+    chroma.GenericPrompt: "bold #000080",
+    chroma.GenericOutput: "#888",
+    chroma.GenericTraceback: "#04D",
+    chroma.Error: "border:#FF0000",
+    chroma.Background: " bg:#f8f8f8",
+}))
+
diff --git a/styles/friendly.go b/styles/friendly.go
new file mode 100644
index 0000000..82a3b3a
--- /dev/null
+++ b/styles/friendly.go
@@ -0,0 +1,52 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Friendly style.
+var Friendly = Register(chroma.NewStyle("friendly", chroma.StyleEntries{
+    chroma.TextWhitespace: "#bbbbbb",
+    chroma.Comment: "italic #60a0b0",
+    chroma.CommentPreproc: "noitalic #007020",
+    chroma.CommentSpecial: "noitalic bg:#fff0f0",
+    chroma.Keyword: "bold #007020",
+    chroma.KeywordPseudo: "nobold",
+    chroma.KeywordType: "nobold #902000",
+    chroma.Operator: "#666666",
+    chroma.OperatorWord: "bold #007020",
+    chroma.NameBuiltin: "#007020",
+    chroma.NameFunction: "#06287e",
+    chroma.NameClass: "bold #0e84b5",
+    chroma.NameNamespace: "bold #0e84b5",
+    chroma.NameException: "#007020",
+    chroma.NameVariable: "#bb60d5",
+    chroma.NameConstant: "#60add5",
+    chroma.NameLabel: "bold #002070",
+    chroma.NameEntity: "bold #d55537",
+    chroma.NameAttribute: "#4070a0",
+    chroma.NameTag: "bold #062873",
+    chroma.NameDecorator: "bold #555555",
+    chroma.LiteralString: "#4070a0",
+    chroma.LiteralStringDoc: "italic",
+    chroma.LiteralStringInterpol: "italic #70a0d0",
+    chroma.LiteralStringEscape: "bold #4070a0",
+    chroma.LiteralStringRegex: "#235388",
+    chroma.LiteralStringSymbol: "#517918",
+    chroma.LiteralStringOther: "#c65d09",
+    chroma.LiteralNumber: "#40a070",
+    chroma.GenericHeading: "bold #000080",
+    chroma.GenericSubheading: "bold #800080",
+    chroma.GenericDeleted: "#A00000",
+    chroma.GenericInserted: "#00A000",
+    chroma.GenericError: "#FF0000",
+    chroma.GenericEmph: "italic",
+    chroma.GenericStrong: "bold",
+    chroma.GenericPrompt: "bold #c65d09",
+    chroma.GenericOutput: "#888",
+    chroma.GenericTraceback: "#04D",
+    chroma.Error: "border:#FF0000",
+    chroma.Background: " bg:#f0f0f0",
+}))
+
diff --git a/styles/fruity.go b/styles/fruity.go
new file mode 100644
index 0000000..19db2ba
--- /dev/null
+++ b/styles/fruity.go
@@ -0,0 +1,28 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Fruity style.
+var Fruity = Register(chroma.NewStyle("fruity", chroma.StyleEntries{
+    chroma.TextWhitespace: "#888888",
+    chroma.Background: "#ffffff bg:#111111",
+    chroma.GenericOutput: "#444444 bg:#222222",
+    chroma.Keyword: "#fb660a bold",
+    chroma.KeywordPseudo: "nobold",
+    chroma.LiteralNumber: "#0086f7 bold",
+    chroma.NameTag: "#fb660a bold",
+    chroma.NameVariable: "#fb660a",
+    chroma.Comment: "#008800 bg:#0f140f italic",
+    chroma.NameAttribute: "#ff0086 bold",
+    chroma.LiteralString: "#0086d2",
+    chroma.NameFunction: "#ff0086 bold",
+    chroma.GenericHeading: "#ffffff bold",
+    chroma.KeywordType: "#cdcaa9 bold",
+    chroma.GenericSubheading: "#ffffff bold",
+    chroma.NameConstant: "#0086d2",
+    chroma.CommentPreproc: "#ff0007 bold",
+}))
+
diff --git a/styles/igor.go b/styles/igor.go
new file mode 100644
index 0000000..97d3246
--- /dev/null
+++ b/styles/igor.go
@@ -0,0 +1,18 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Igor style.
+var Igor = Register(chroma.NewStyle("igor", chroma.StyleEntries{
+    chroma.Comment: "italic #FF0000",
+    chroma.Keyword: "#0000FF",
+    chroma.NameFunction: "#C34E00",
+    chroma.NameDecorator: "#CC00A3",
+    chroma.NameClass: "#007575",
+    chroma.LiteralString: "#009C00",
+    chroma.Background: " bg:#ffffff",
+}))
+
diff --git a/styles/lovelace.go b/styles/lovelace.go
new file mode 100644
index 0000000..43a2834
--- /dev/null
+++ b/styles/lovelace.go
@@ -0,0 +1,61 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Lovelace style.
+var Lovelace = Register(chroma.NewStyle("lovelace", chroma.StyleEntries{
+    chroma.TextWhitespace: "#a89028",
+    chroma.Comment: "italic #888888",
+    chroma.CommentHashbang: "#287088",
+    chroma.CommentMultiline: "#888888",
+    chroma.CommentPreproc: "noitalic #289870",
+    chroma.Keyword: "#2838b0",
+    chroma.KeywordConstant: "italic #444444",
+    chroma.KeywordDeclaration: "italic",
+    chroma.KeywordType: "italic",
+    chroma.Operator: "#666666",
+    chroma.OperatorWord: "#a848a8",
+    chroma.Punctuation: "#888888",
+    chroma.NameAttribute: "#388038",
+    chroma.NameBuiltin: "#388038",
+    chroma.NameBuiltinPseudo: "italic",
+    chroma.NameClass: "#287088",
+    chroma.NameConstant: "#b85820",
+    chroma.NameDecorator: "#287088",
+    chroma.NameEntity: "#709030",
+    chroma.NameException: "#908828",
+    chroma.NameFunction: "#785840",
+    chroma.NameFunctionMagic: "#b85820",
+    chroma.NameLabel: "#289870",
+    chroma.NameNamespace: "#289870",
+    chroma.NameTag: "#2838b0",
+    chroma.NameVariable: "#b04040",
+    chroma.NameVariableGlobal: "#908828",
+    chroma.NameVariableMagic: "#b85820",
+    chroma.LiteralString: "#b83838",
+    chroma.LiteralStringAffix: "#444444",
+    chroma.LiteralStringChar: "#a848a8",
+    chroma.LiteralStringDelimiter: "#b85820",
+    chroma.LiteralStringDoc: "italic #b85820",
+    chroma.LiteralStringEscape: "#709030",
+    chroma.LiteralStringInterpol: "underline",
+    chroma.LiteralStringOther: "#a848a8",
+    chroma.LiteralStringRegex: "#a848a8",
+    chroma.LiteralNumber: "#444444",
+    chroma.GenericDeleted: "#c02828",
+    chroma.GenericEmph: "italic",
+    chroma.GenericError: "#c02828",
+    chroma.GenericHeading: "#666666",
+    chroma.GenericSubheading: "#444444",
+    chroma.GenericInserted: "#388038",
+    chroma.GenericOutput: "#666666",
+    chroma.GenericPrompt: "#444444",
+    chroma.GenericStrong: "bold",
+    chroma.GenericTraceback: "#2838b0",
+    chroma.Error: "bg:#a848a8",
+    chroma.Background: " bg:#ffffff",
+}))
+
diff --git a/styles/manni.go b/styles/manni.go
new file mode 100644
index 0000000..c28b738
--- /dev/null
+++ b/styles/manni.go
@@ -0,0 +1,52 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Manni style.
+var Manni = Register(chroma.NewStyle("manni", chroma.StyleEntries{
+    chroma.TextWhitespace: "#bbbbbb",
+    chroma.Comment: "italic #0099FF",
+    chroma.CommentPreproc: "noitalic #009999",
+    chroma.CommentSpecial: "bold",
+    chroma.Keyword: "bold #006699",
+    chroma.KeywordPseudo: "nobold",
+    chroma.KeywordType: "#007788",
+    chroma.Operator: "#555555",
+    chroma.OperatorWord: "bold #000000",
+    chroma.NameBuiltin: "#336666",
+    chroma.NameFunction: "#CC00FF",
+    chroma.NameClass: "bold #00AA88",
+    chroma.NameNamespace: "bold #00CCFF",
+    chroma.NameException: "bold #CC0000",
+    chroma.NameVariable: "#003333",
+    chroma.NameConstant: "#336600",
+    chroma.NameLabel: "#9999FF",
+    chroma.NameEntity: "bold #999999",
+    chroma.NameAttribute: "#330099",
+    chroma.NameTag: "bold #330099",
+    chroma.NameDecorator: "#9999FF",
+    chroma.LiteralString: "#CC3300",
+    chroma.LiteralStringDoc: "italic",
+    chroma.LiteralStringInterpol: "#AA0000",
+    chroma.LiteralStringEscape: "bold #CC3300",
+    chroma.LiteralStringRegex: "#33AAAA",
+    chroma.LiteralStringSymbol: "#FFCC33",
+    chroma.LiteralStringOther: "#CC3300",
+    chroma.LiteralNumber: "#FF6600",
+    chroma.GenericHeading: "bold #003300",
+    chroma.GenericSubheading: "bold #003300",
+    chroma.GenericDeleted: "border:#CC0000 bg:#FFCCCC",
+    chroma.GenericInserted: "border:#00CC00 bg:#CCFFCC",
+    chroma.GenericError: "#FF0000",
+    chroma.GenericEmph: "italic",
+    chroma.GenericStrong: "bold",
+    chroma.GenericPrompt: "bold #000099",
+    chroma.GenericOutput: "#AAAAAA",
+    chroma.GenericTraceback: "#99CC66",
+    chroma.Error: "bg:#FFAAAA #AA0000",
+    chroma.Background: " bg:#f0f3f3",
+}))
+
diff --git a/styles/monokai.go b/styles/monokai.go
new file mode 100644
index 0000000..7da5e7a
--- /dev/null
+++ b/styles/monokai.go
@@ -0,0 +1,38 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Monokai style.
+var Monokai = Register(chroma.NewStyle("monokai", chroma.StyleEntries{
+    chroma.Text: "#f8f8f2",
+    chroma.Error: "#960050 bg:#1e0010",
+    chroma.Comment: "#75715e",
+    chroma.Keyword: "#66d9ef",
+    chroma.KeywordNamespace: "#f92672",
+    chroma.Operator: "#f92672",
+    chroma.Punctuation: "#f8f8f2",
+    chroma.Name: "#f8f8f2",
+    chroma.NameAttribute: "#a6e22e",
+    chroma.NameClass: "#a6e22e",
+    chroma.NameConstant: "#66d9ef",
+    chroma.NameDecorator: "#a6e22e",
+    chroma.NameException: "#a6e22e",
+    chroma.NameFunction: "#a6e22e",
+    chroma.NameOther: "#a6e22e",
+    chroma.NameTag: "#f92672",
+    chroma.LiteralNumber: "#ae81ff",
+    chroma.Literal: "#ae81ff",
+    chroma.LiteralDate: "#e6db74",
+    chroma.LiteralString: "#e6db74",
+    chroma.LiteralStringEscape: "#ae81ff",
+    chroma.GenericDeleted: "#f92672",
+    chroma.GenericEmph: "italic",
+    chroma.GenericInserted: "#a6e22e",
+    chroma.GenericStrong: "bold",
+    chroma.GenericSubheading: "#75715e",
+    chroma.Background: " bg:#272822",
+}))
+
diff --git a/styles/murphy.go b/styles/murphy.go
new file mode 100644
index 0000000..cde8287
--- /dev/null
+++ b/styles/murphy.go
@@ -0,0 +1,60 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Murphy style.
+var Murphy = Register(chroma.NewStyle("murphy", chroma.StyleEntries{
+    chroma.TextWhitespace: "#bbbbbb",
+    chroma.Comment: "#666 italic",
+    chroma.CommentPreproc: "#579 noitalic",
+    chroma.CommentSpecial: "#c00 bold",
+    chroma.Keyword: "bold #289",
+    chroma.KeywordPseudo: "#08f",
+    chroma.KeywordType: "#66f",
+    chroma.Operator: "#333",
+    chroma.OperatorWord: "bold #000",
+    chroma.NameBuiltin: "#072",
+    chroma.NameFunction: "bold #5ed",
+    chroma.NameClass: "bold #e9e",
+    chroma.NameNamespace: "bold #0e84b5",
+    chroma.NameException: "bold #F00",
+    chroma.NameVariable: "#036",
+    chroma.NameVariableInstance: "#aaf",
+    chroma.NameVariableClass: "#ccf",
+    chroma.NameVariableGlobal: "#f84",
+    chroma.NameConstant: "bold #5ed",
+    chroma.NameLabel: "bold #970",
+    chroma.NameEntity: "#800",
+    chroma.NameAttribute: "#007",
+    chroma.NameTag: "#070",
+    chroma.NameDecorator: "bold #555",
+    chroma.LiteralString: "bg:#e0e0ff",
+    chroma.LiteralStringChar: "#88F bg:",
+    chroma.LiteralStringDoc: "#D42 bg:",
+    chroma.LiteralStringInterpol: "bg:#eee",
+    chroma.LiteralStringEscape: "bold #666",
+    chroma.LiteralStringRegex: "bg:#e0e0ff #000",
+    chroma.LiteralStringSymbol: "#fc8 bg:",
+    chroma.LiteralStringOther: "#f88",
+    chroma.LiteralNumber: "bold #60E",
+    chroma.LiteralNumberInteger: "bold #66f",
+    chroma.LiteralNumberFloat: "bold #60E",
+    chroma.LiteralNumberHex: "bold #058",
+    chroma.LiteralNumberOct: "bold #40E",
+    chroma.GenericHeading: "bold #000080",
+    chroma.GenericSubheading: "bold #800080",
+    chroma.GenericDeleted: "#A00000",
+    chroma.GenericInserted: "#00A000",
+    chroma.GenericError: "#FF0000",
+    chroma.GenericEmph: "italic",
+    chroma.GenericStrong: "bold",
+    chroma.GenericPrompt: "bold #c65d09",
+    chroma.GenericOutput: "#888",
+    chroma.GenericTraceback: "#04D",
+    chroma.Error: "#F00 bg:#FAA",
+    chroma.Background: " bg:#ffffff",
+}))
+
diff --git a/styles/native.go b/styles/native.go
new file mode 100644
index 0000000..a2cb9ff
--- /dev/null
+++ b/styles/native.go
@@ -0,0 +1,43 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Native style.
+var Native = Register(chroma.NewStyle("native", chroma.StyleEntries{
+    chroma.Background: "#d0d0d0 bg:#202020",
+    chroma.TextWhitespace: "#666666",
+    chroma.Comment: "italic #999999",
+    chroma.CommentPreproc: "noitalic bold #cd2828",
+    chroma.CommentSpecial: "noitalic bold #e50808 bg:#520000",
+    chroma.Keyword: "bold #6ab825",
+    chroma.KeywordPseudo: "nobold",
+    chroma.OperatorWord: "bold #6ab825",
+    chroma.LiteralString: "#ed9d13",
+    chroma.LiteralStringOther: "#ffa500",
+    chroma.LiteralNumber: "#3677a9",
+    chroma.NameBuiltin: "#24909d",
+    chroma.NameVariable: "#40ffff",
+    chroma.NameConstant: "#40ffff",
+    chroma.NameClass: "underline #447fcf",
+    chroma.NameFunction: "#447fcf",
+    chroma.NameNamespace: "underline #447fcf",
+    chroma.NameException: "#bbbbbb",
+    chroma.NameTag: "bold #6ab825",
+    chroma.NameAttribute: "#bbbbbb",
+    chroma.NameDecorator: "#ffa500",
+    chroma.GenericHeading: "bold #ffffff",
+    chroma.GenericSubheading: "underline #ffffff",
+    chroma.GenericDeleted: "#d22323",
+    chroma.GenericInserted: "#589819",
+    chroma.GenericError: "#d22323",
+    chroma.GenericEmph: "italic",
+    chroma.GenericStrong: "bold",
+    chroma.GenericPrompt: "#aaaaaa",
+    chroma.GenericOutput: "#cccccc",
+    chroma.GenericTraceback: "#d22323",
+    chroma.Error: "bg:#e3d2d2 #a61717",
+}))
+
diff --git a/styles/paraiso-dark.go b/styles/paraiso-dark.go
new file mode 100644
index 0000000..8c4150b
--- /dev/null
+++ b/styles/paraiso-dark.go
@@ -0,0 +1,46 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// ParaisoDark style.
+var ParaisoDark = Register(chroma.NewStyle("paraiso-dark", chroma.StyleEntries{
+    chroma.Text: "#e7e9db",
+    chroma.Error: "#ef6155",
+    chroma.Comment: "#776e71",
+    chroma.Keyword: "#815ba4",
+    chroma.KeywordNamespace: "#5bc4bf",
+    chroma.KeywordType: "#fec418",
+    chroma.Operator: "#5bc4bf",
+    chroma.Punctuation: "#e7e9db",
+    chroma.Name: "#e7e9db",
+    chroma.NameAttribute: "#06b6ef",
+    chroma.NameClass: "#fec418",
+    chroma.NameConstant: "#ef6155",
+    chroma.NameDecorator: "#5bc4bf",
+    chroma.NameException: "#ef6155",
+    chroma.NameFunction: "#06b6ef",
+    chroma.NameNamespace: "#fec418",
+    chroma.NameOther: "#06b6ef",
+    chroma.NameTag: "#5bc4bf",
+    chroma.NameVariable: "#ef6155",
+    chroma.LiteralNumber: "#f99b15",
+    chroma.Literal: "#f99b15",
+    chroma.LiteralDate: "#48b685",
+    chroma.LiteralString: "#48b685",
+    chroma.LiteralStringChar: "#e7e9db",
+    chroma.LiteralStringDoc: "#776e71",
+    chroma.LiteralStringEscape: "#f99b15",
+    chroma.LiteralStringInterpol: "#f99b15",
+    chroma.GenericDeleted: "#ef6155",
+    chroma.GenericEmph: "italic",
+    chroma.GenericHeading: "bold #e7e9db",
+    chroma.GenericInserted: "#48b685",
+    chroma.GenericPrompt: "bold #776e71",
+    chroma.GenericStrong: "bold",
+    chroma.GenericSubheading: "bold #5bc4bf",
+    chroma.Background: " bg:#2f1e2e",
+}))
+
diff --git a/styles/paraiso-light.go b/styles/paraiso-light.go
new file mode 100644
index 0000000..ba46de7
--- /dev/null
+++ b/styles/paraiso-light.go
@@ -0,0 +1,46 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// ParaisoLight style.
+var ParaisoLight = Register(chroma.NewStyle("paraiso-light", chroma.StyleEntries{
+    chroma.Text: "#2f1e2e",
+    chroma.Error: "#ef6155",
+    chroma.Comment: "#8d8687",
+    chroma.Keyword: "#815ba4",
+    chroma.KeywordNamespace: "#5bc4bf",
+    chroma.KeywordType: "#fec418",
+    chroma.Operator: "#5bc4bf",
+    chroma.Punctuation: "#2f1e2e",
+    chroma.Name: "#2f1e2e",
+    chroma.NameAttribute: "#06b6ef",
+    chroma.NameClass: "#fec418",
+    chroma.NameConstant: "#ef6155",
+    chroma.NameDecorator: "#5bc4bf",
+    chroma.NameException: "#ef6155",
+    chroma.NameFunction: "#06b6ef",
+    chroma.NameNamespace: "#fec418",
+    chroma.NameOther: "#06b6ef",
+    chroma.NameTag: "#5bc4bf",
+    chroma.NameVariable: "#ef6155",
+    chroma.LiteralNumber: "#f99b15",
+    chroma.Literal: "#f99b15",
+    chroma.LiteralDate: "#48b685",
+    chroma.LiteralString: "#48b685",
+    chroma.LiteralStringChar: "#2f1e2e",
+    chroma.LiteralStringDoc: "#8d8687",
+    chroma.LiteralStringEscape: "#f99b15",
+    chroma.LiteralStringInterpol: "#f99b15",
+    chroma.GenericDeleted: "#ef6155",
+    chroma.GenericEmph: "italic",
+    chroma.GenericHeading: "bold #2f1e2e",
+    chroma.GenericInserted: "#48b685",
+    chroma.GenericPrompt: "bold #8d8687",
+    chroma.GenericStrong: "bold",
+    chroma.GenericSubheading: "bold #5bc4bf",
+    chroma.Background: " bg:#e7e9db",
+}))
+
diff --git a/styles/pastie.go b/styles/pastie.go
new file mode 100644
index 0000000..1853612
--- /dev/null
+++ b/styles/pastie.go
@@ -0,0 +1,53 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Pastie style.
+var Pastie = Register(chroma.NewStyle("pastie", chroma.StyleEntries{
+    chroma.TextWhitespace: "#bbbbbb",
+    chroma.Comment: "#888888",
+    chroma.CommentPreproc: "bold #cc0000",
+    chroma.CommentSpecial: "bg:#fff0f0 bold #cc0000",
+    chroma.LiteralString: "bg:#fff0f0 #dd2200",
+    chroma.LiteralStringRegex: "bg:#fff0ff #008800",
+    chroma.LiteralStringOther: "bg:#f0fff0 #22bb22",
+    chroma.LiteralStringSymbol: "#aa6600",
+    chroma.LiteralStringInterpol: "#3333bb",
+    chroma.LiteralStringEscape: "#0044dd",
+    chroma.OperatorWord: "#008800",
+    chroma.Keyword: "bold #008800",
+    chroma.KeywordPseudo: "nobold",
+    chroma.KeywordType: "#888888",
+    chroma.NameClass: "bold #bb0066",
+    chroma.NameException: "bold #bb0066",
+    chroma.NameFunction: "bold #0066bb",
+    chroma.NameProperty: "bold #336699",
+    chroma.NameNamespace: "bold #bb0066",
+    chroma.NameBuiltin: "#003388",
+    chroma.NameVariable: "#336699",
+    chroma.NameVariableClass: "#336699",
+    chroma.NameVariableInstance: "#3333bb",
+    chroma.NameVariableGlobal: "#dd7700",
+    chroma.NameConstant: "bold #003366",
+    chroma.NameTag: "bold #bb0066",
+    chroma.NameAttribute: "#336699",
+    chroma.NameDecorator: "#555555",
+    chroma.NameLabel: "italic #336699",
+    chroma.LiteralNumber: "bold #0000DD",
+    chroma.GenericHeading: "#333",
+    chroma.GenericSubheading: "#666",
+    chroma.GenericDeleted: "bg:#ffdddd #000000",
+    chroma.GenericInserted: "bg:#ddffdd #000000",
+    chroma.GenericError: "#aa0000",
+    chroma.GenericEmph: "italic",
+    chroma.GenericStrong: "bold",
+    chroma.GenericPrompt: "#555555",
+    chroma.GenericOutput: "#888888",
+    chroma.GenericTraceback: "#aa0000",
+    chroma.Error: "bg:#e3d2d2 #a61717",
+    chroma.Background: " bg:#ffffff",
+}))
+
diff --git a/styles/perldoc.go b/styles/perldoc.go
new file mode 100644
index 0000000..e3a2023
--- /dev/null
+++ b/styles/perldoc.go
@@ -0,0 +1,45 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Perldoc style.
+var Perldoc = Register(chroma.NewStyle("perldoc", chroma.StyleEntries{
+    chroma.TextWhitespace: "#bbbbbb",
+    chroma.Comment: "#228B22",
+    chroma.CommentPreproc: "#1e889b",
+    chroma.CommentSpecial: "#8B008B bold",
+    chroma.LiteralString: "#CD5555",
+    chroma.LiteralStringHeredoc: "#1c7e71 italic",
+    chroma.LiteralStringRegex: "#1c7e71",
+    chroma.LiteralStringOther: "#cb6c20",
+    chroma.LiteralNumber: "#B452CD",
+    chroma.OperatorWord: "#8B008B",
+    chroma.Keyword: "#8B008B bold",
+    chroma.KeywordType: "#00688B",
+    chroma.NameClass: "#008b45 bold",
+    chroma.NameException: "#008b45 bold",
+    chroma.NameFunction: "#008b45",
+    chroma.NameNamespace: "#008b45 underline",
+    chroma.NameVariable: "#00688B",
+    chroma.NameConstant: "#00688B",
+    chroma.NameDecorator: "#707a7c",
+    chroma.NameTag: "#8B008B bold",
+    chroma.NameAttribute: "#658b00",
+    chroma.NameBuiltin: "#658b00",
+    chroma.GenericHeading: "bold #000080",
+    chroma.GenericSubheading: "bold #800080",
+    chroma.GenericDeleted: "#aa0000",
+    chroma.GenericInserted: "#00aa00",
+    chroma.GenericError: "#aa0000",
+    chroma.GenericEmph: "italic",
+    chroma.GenericStrong: "bold",
+    chroma.GenericPrompt: "#555555",
+    chroma.GenericOutput: "#888888",
+    chroma.GenericTraceback: "#aa0000",
+    chroma.Error: "bg:#e3d2d2 #a61717",
+    chroma.Background: " bg:#eeeedd",
+}))
+
diff --git a/styles/rainbow_dash.go b/styles/rainbow_dash.go
new file mode 100644
index 0000000..d9d74f3
--- /dev/null
+++ b/styles/rainbow_dash.go
@@ -0,0 +1,48 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// RainbowDash style.
+var RainbowDash = Register(chroma.NewStyle("rainbow_dash", chroma.StyleEntries{
+    chroma.Comment: "italic #0080ff",
+    chroma.CommentPreproc: "noitalic",
+    chroma.CommentSpecial: "bold",
+    chroma.Error: "bg:#cc0000 #ffffff",
+    chroma.GenericDeleted: "border:#c5060b bg:#ffcccc",
+    chroma.GenericEmph: "italic",
+    chroma.GenericError: "#ff0000",
+    chroma.GenericHeading: "bold #2c5dcd",
+    chroma.GenericInserted: "border:#00cc00 bg:#ccffcc",
+    chroma.GenericOutput: "#aaaaaa",
+    chroma.GenericPrompt: "bold #2c5dcd",
+    chroma.GenericStrong: "bold",
+    chroma.GenericSubheading: "bold #2c5dcd",
+    chroma.GenericTraceback: "#c5060b",
+    chroma.Keyword: "bold #2c5dcd",
+    chroma.KeywordPseudo: "nobold",
+    chroma.KeywordType: "#5918bb",
+    chroma.NameAttribute: "italic #2c5dcd",
+    chroma.NameBuiltin: "bold #5918bb",
+    chroma.NameClass: "underline",
+    chroma.NameConstant: "#318495",
+    chroma.NameDecorator: "bold #ff8000",
+    chroma.NameEntity: "bold #5918bb",
+    chroma.NameException: "bold #5918bb",
+    chroma.NameFunction: "bold #ff8000",
+    chroma.NameTag: "bold #2c5dcd",
+    chroma.LiteralNumber: "bold #5918bb",
+    chroma.Operator: "#2c5dcd",
+    chroma.OperatorWord: "bold",
+    chroma.LiteralString: "#00cc66",
+    chroma.LiteralStringDoc: "italic",
+    chroma.LiteralStringEscape: "bold #c5060b",
+    chroma.LiteralStringOther: "#318495",
+    chroma.LiteralStringSymbol: "bold #c5060b",
+    chroma.Text: "#4d4d4d",
+    chroma.TextWhitespace: "#cbcbcb",
+    chroma.Background: " bg:#ffffff",
+}))
+
diff --git a/styles/rrt.go b/styles/rrt.go
new file mode 100644
index 0000000..e1e6978
--- /dev/null
+++ b/styles/rrt.go
@@ -0,0 +1,20 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Rrt style.
+var Rrt = Register(chroma.NewStyle("rrt", chroma.StyleEntries{
+    chroma.Comment: "#00ff00",
+    chroma.NameFunction: "#ffff00",
+    chroma.NameVariable: "#eedd82",
+    chroma.NameConstant: "#7fffd4",
+    chroma.Keyword: "#ff0000",
+    chroma.CommentPreproc: "#e5e5e5",
+    chroma.LiteralString: "#87ceeb",
+    chroma.KeywordType: "#ee82ee",
+    chroma.Background: " bg:#000000",
+}))
+
diff --git a/styles/swapoff.go b/styles/swapoff.go
index 177edec..6680ea9 100644
--- a/styles/swapoff.go
+++ b/styles/swapoff.go
@@ -6,10 +6,11 @@ import (
 
 // SwapOff theme.
 var SwapOff = Register(chroma.NewStyle("swapoff", map[chroma.TokenType]string{
+	chroma.Background:        "#lightgray bg:#black",
 	chroma.Number:            "bold #ansiyellow",
 	chroma.Comment:           "#ansiteal",
 	chroma.CommentPreproc:    "bold #ansigreen",
-	chroma.String:            "bold #ansiteal",
+	chroma.String:            "bold #ansiturquoise",
 	chroma.Keyword:           "bold #ansiwhite",
 	chroma.GenericHeading:    "bold",
 	chroma.GenericSubheading: "bold",
diff --git a/styles/tango.go b/styles/tango.go
new file mode 100644
index 0000000..d526712
--- /dev/null
+++ b/styles/tango.go
@@ -0,0 +1,80 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Tango style.
+var Tango = Register(chroma.NewStyle("tango", chroma.StyleEntries{
+    chroma.TextWhitespace: "underline #f8f8f8",
+    chroma.Error: "#a40000 border:#ef2929",
+    chroma.Other: "#000000",
+    chroma.Comment: "italic #8f5902",
+    chroma.CommentMultiline: "italic #8f5902",
+    chroma.CommentPreproc: "italic #8f5902",
+    chroma.CommentSingle: "italic #8f5902",
+    chroma.CommentSpecial: "italic #8f5902",
+    chroma.Keyword: "bold #204a87",
+    chroma.KeywordConstant: "bold #204a87",
+    chroma.KeywordDeclaration: "bold #204a87",
+    chroma.KeywordNamespace: "bold #204a87",
+    chroma.KeywordPseudo: "bold #204a87",
+    chroma.KeywordReserved: "bold #204a87",
+    chroma.KeywordType: "bold #204a87",
+    chroma.Operator: "bold #ce5c00",
+    chroma.OperatorWord: "bold #204a87",
+    chroma.Punctuation: "bold #000000",
+    chroma.Name: "#000000",
+    chroma.NameAttribute: "#c4a000",
+    chroma.NameBuiltin: "#204a87",
+    chroma.NameBuiltinPseudo: "#3465a4",
+    chroma.NameClass: "#000000",
+    chroma.NameConstant: "#000000",
+    chroma.NameDecorator: "bold #5c35cc",
+    chroma.NameEntity: "#ce5c00",
+    chroma.NameException: "bold #cc0000",
+    chroma.NameFunction: "#000000",
+    chroma.NameProperty: "#000000",
+    chroma.NameLabel: "#f57900",
+    chroma.NameNamespace: "#000000",
+    chroma.NameOther: "#000000",
+    chroma.NameTag: "bold #204a87",
+    chroma.NameVariable: "#000000",
+    chroma.NameVariableClass: "#000000",
+    chroma.NameVariableGlobal: "#000000",
+    chroma.NameVariableInstance: "#000000",
+    chroma.LiteralNumber: "bold #0000cf",
+    chroma.LiteralNumberFloat: "bold #0000cf",
+    chroma.LiteralNumberHex: "bold #0000cf",
+    chroma.LiteralNumberInteger: "bold #0000cf",
+    chroma.LiteralNumberIntegerLong: "bold #0000cf",
+    chroma.LiteralNumberOct: "bold #0000cf",
+    chroma.Literal: "#000000",
+    chroma.LiteralDate: "#000000",
+    chroma.LiteralString: "#4e9a06",
+    chroma.LiteralStringBacktick: "#4e9a06",
+    chroma.LiteralStringChar: "#4e9a06",
+    chroma.LiteralStringDoc: "italic #8f5902",
+    chroma.LiteralStringDouble: "#4e9a06",
+    chroma.LiteralStringEscape: "#4e9a06",
+    chroma.LiteralStringHeredoc: "#4e9a06",
+    chroma.LiteralStringInterpol: "#4e9a06",
+    chroma.LiteralStringOther: "#4e9a06",
+    chroma.LiteralStringRegex: "#4e9a06",
+    chroma.LiteralStringSingle: "#4e9a06",
+    chroma.LiteralStringSymbol: "#4e9a06",
+    chroma.Generic: "#000000",
+    chroma.GenericDeleted: "#a40000",
+    chroma.GenericEmph: "italic #000000",
+    chroma.GenericError: "#ef2929",
+    chroma.GenericHeading: "bold #000080",
+    chroma.GenericInserted: "#00A000",
+    chroma.GenericOutput: "italic #000000",
+    chroma.GenericPrompt: "#8f5902",
+    chroma.GenericStrong: "bold #000000",
+    chroma.GenericSubheading: "bold #800080",
+    chroma.GenericTraceback: "bold #a40000",
+    chroma.Background: " bg:#f8f8f8",
+}))
+
diff --git a/styles/trac.go b/styles/trac.go
index 1498c19..bea7985 100644
--- a/styles/trac.go
+++ b/styles/trac.go
@@ -1,40 +1,43 @@
+
 package styles
 
 import (
-	"github.com/alecthomas/chroma"
+    "github.com/alecthomas/chroma"
 )
 
-// Trac colour scheme.
-var Trac = Register(chroma.NewStyle("trac", map[chroma.TokenType]string{
-	chroma.Whitespace:        "#bbbbbb",
-	chroma.Comment:           "italic #999988",
-	chroma.CommentPreproc:    "bold noitalic #999999",
-	chroma.CommentSpecial:    "bold #999999",
-	chroma.Operator:          "bold",
-	chroma.String:            "#bb8844",
-	chroma.StringRegex:       "#808000",
-	chroma.Number:            "#009999",
-	chroma.Keyword:           "bold",
-	chroma.KeywordType:       "#445588",
-	chroma.NameBuiltin:       "#999999",
-	chroma.NameFunction:      "bold #990000",
-	chroma.NameClass:         "bold #445588",
-	chroma.NameException:     "bold #990000",
-	chroma.NameNamespace:     "#555555",
-	chroma.NameVariable:      "#008080",
-	chroma.NameConstant:      "#008080",
-	chroma.NameTag:           "#000080",
-	chroma.NameAttribute:     "#008080",
-	chroma.NameEntity:        "#800080",
-	chroma.GenericHeading:    "#999999",
-	chroma.GenericSubheading: "#aaaaaa",
-	chroma.GenericDeleted:    "bg:#ffdddd #000000",
-	chroma.GenericInserted:   "bg:#ddffdd #000000",
-	chroma.GenericError:      "#aa0000",
-	chroma.GenericEmph:       "italic",
-	chroma.GenericStrong:     "bold",
-	chroma.GenericPrompt:     "#555555",
-	chroma.GenericOutput:     "#888888",
-	chroma.GenericTraceback:  "#aa0000",
-	chroma.Error:             "bg:#e3d2d2 #a61717",
+// Trac style.
+var Trac = Register(chroma.NewStyle("trac", chroma.StyleEntries{
+    chroma.TextWhitespace: "#bbbbbb",
+    chroma.Comment: "italic #999988",
+    chroma.CommentPreproc: "bold noitalic #999999",
+    chroma.CommentSpecial: "bold #999999",
+    chroma.Operator: "bold",
+    chroma.LiteralString: "#bb8844",
+    chroma.LiteralStringRegex: "#808000",
+    chroma.LiteralNumber: "#009999",
+    chroma.Keyword: "bold",
+    chroma.KeywordType: "#445588",
+    chroma.NameBuiltin: "#999999",
+    chroma.NameFunction: "bold #990000",
+    chroma.NameClass: "bold #445588",
+    chroma.NameException: "bold #990000",
+    chroma.NameNamespace: "#555555",
+    chroma.NameVariable: "#008080",
+    chroma.NameConstant: "#008080",
+    chroma.NameTag: "#000080",
+    chroma.NameAttribute: "#008080",
+    chroma.NameEntity: "#800080",
+    chroma.GenericHeading: "#999999",
+    chroma.GenericSubheading: "#aaaaaa",
+    chroma.GenericDeleted: "bg:#ffdddd #000000",
+    chroma.GenericInserted: "bg:#ddffdd #000000",
+    chroma.GenericError: "#aa0000",
+    chroma.GenericEmph: "italic",
+    chroma.GenericStrong: "bold",
+    chroma.GenericPrompt: "#555555",
+    chroma.GenericOutput: "#888888",
+    chroma.GenericTraceback: "#aa0000",
+    chroma.Error: "bg:#e3d2d2 #a61717",
+    chroma.Background: " bg:#ffffff",
 }))
+
diff --git a/styles/vim.go b/styles/vim.go
new file mode 100644
index 0000000..cad7095
--- /dev/null
+++ b/styles/vim.go
@@ -0,0 +1,37 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Vim style.
+var Vim = Register(chroma.NewStyle("vim", chroma.StyleEntries{
+    chroma.Background: "#cccccc bg:#000000",
+    chroma.Comment: "#000080",
+    chroma.CommentSpecial: "bold #cd0000",
+    chroma.Keyword: "#cdcd00",
+    chroma.KeywordDeclaration: "#00cd00",
+    chroma.KeywordNamespace: "#cd00cd",
+    chroma.KeywordType: "#00cd00",
+    chroma.Operator: "#3399cc",
+    chroma.OperatorWord: "#cdcd00",
+    chroma.NameClass: "#00cdcd",
+    chroma.NameBuiltin: "#cd00cd",
+    chroma.NameException: "bold #666699",
+    chroma.NameVariable: "#00cdcd",
+    chroma.LiteralString: "#cd0000",
+    chroma.LiteralNumber: "#cd00cd",
+    chroma.GenericHeading: "bold #000080",
+    chroma.GenericSubheading: "bold #800080",
+    chroma.GenericDeleted: "#cd0000",
+    chroma.GenericInserted: "#00cd00",
+    chroma.GenericError: "#FF0000",
+    chroma.GenericEmph: "italic",
+    chroma.GenericStrong: "bold",
+    chroma.GenericPrompt: "bold #000080",
+    chroma.GenericOutput: "#888",
+    chroma.GenericTraceback: "#04D",
+    chroma.Error: "border:#FF0000",
+}))
+
diff --git a/styles/vs.go b/styles/vs.go
new file mode 100644
index 0000000..8af4ac0
--- /dev/null
+++ b/styles/vs.go
@@ -0,0 +1,25 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// VisualStudio style.
+var VisualStudio = Register(chroma.NewStyle("vs", chroma.StyleEntries{
+    chroma.Comment: "#008000",
+    chroma.CommentPreproc: "#0000ff",
+    chroma.Keyword: "#0000ff",
+    chroma.OperatorWord: "#0000ff",
+    chroma.KeywordType: "#2b91af",
+    chroma.NameClass: "#2b91af",
+    chroma.LiteralString: "#a31515",
+    chroma.GenericHeading: "bold",
+    chroma.GenericSubheading: "bold",
+    chroma.GenericEmph: "italic",
+    chroma.GenericStrong: "bold",
+    chroma.GenericPrompt: "bold",
+    chroma.Error: "border:#FF0000",
+    chroma.Background: " bg:#ffffff",
+}))
+
diff --git a/styles/xcode.go b/styles/xcode.go
new file mode 100644
index 0000000..6ea3a15
--- /dev/null
+++ b/styles/xcode.go
@@ -0,0 +1,31 @@
+
+package styles
+
+import (
+    "github.com/alecthomas/chroma"
+)
+
+// Xcode style.
+var Xcode = Register(chroma.NewStyle("xcode", chroma.StyleEntries{
+    chroma.Comment: "#177500",
+    chroma.CommentPreproc: "#633820",
+    chroma.LiteralString: "#C41A16",
+    chroma.LiteralStringChar: "#2300CE",
+    chroma.Operator: "#000000",
+    chroma.Keyword: "#A90D91",
+    chroma.Name: "#000000",
+    chroma.NameAttribute: "#836C28",
+    chroma.NameClass: "#3F6E75",
+    chroma.NameFunction: "#000000",
+    chroma.NameBuiltin: "#A90D91",
+    chroma.NameBuiltinPseudo: "#5B269A",
+    chroma.NameVariable: "#000000",
+    chroma.NameTag: "#000000",
+    chroma.NameDecorator: "#000000",
+    chroma.NameLabel: "#000000",
+    chroma.Literal: "#1C01CE",
+    chroma.LiteralNumber: "#1C01CE",
+    chroma.Error: "#000000",
+    chroma.Background: " bg:#ffffff",
+}))
+
diff --git a/tokentype_string.go b/tokentype_string.go
index 236e561..0aaff0c 100644
--- a/tokentype_string.go
+++ b/tokentype_string.go
@@ -1,91 +1,94 @@
-// Code generated by "stringer -type TokenType"; DO NOT EDIT
+// Code generated by "stringer -type TokenType"; DO NOT EDIT.
 
 package chroma
 
 import "fmt"
 
-const _TokenType_name = "EscapeErrorOtherKeywordKeywordConstantKeywordDeclarationKeywordNamespaceKeywordPseudoKeywordReservedKeywordTypeNameNameAttributeNameBuiltinNameBuiltinPseudoNameClassNameConstantNameDecoratorNameEntityNameExceptionNameFunctionNameFunctionMagicNamePropertyNameLabelNameNamespaceNameOtherNameTagNameVariableNameVariableClassNameVariableGlobalNameVariableInstanceNameVariableMagicLiteralLiteralDateLiteralStringLiteralStringAffixLiteralStringBacktickLiteralStringCharLiteralStringDelimiterLiteralStringDocLiteralStringDoubleLiteralStringEscapeLiteralStringHeredocLiteralStringInterpolLiteralStringOtherLiteralStringRegexLiteralStringSingleLiteralStringSymbolLiteralStringNameLiteralNumberLiteralNumberBinLiteralNumberFloatLiteralNumberHexLiteralNumberIntegerLiteralNumberIntegerLongLiteralNumberOctOperatorOperatorWordPunctuationCommentCommentHashbangCommentMultilineCommentSingleCommentSpecialCommentPreprocCommentPreprocFileGenericGenericDeletedGenericEmphGenericErrorGenericHeadingGenericInsertedGenericOutputGenericPromptGenericStrongGenericSubheadingGenericTracebackGenericUnderlineTextTextWhitespace"
+const _TokenType_name = "BackgroundEscapeErrorOtherEOFKeywordKeywordConstantKeywordDeclarationKeywordNamespaceKeywordPseudoKeywordReservedKeywordTypeNameNameAttributeNameBuiltinNameBuiltinPseudoNameClassNameConstantNameDecoratorNameEntityNameExceptionNameFunctionNameFunctionMagicNamePropertyNameLabelNameNamespaceNameOtherNameOperatorNameTagNameVariableNameVariableClassNameVariableGlobalNameVariableInstanceNameVariableMagicLiteralLiteralDateLiteralStringLiteralStringAffixLiteralStringBacktickLiteralStringCharLiteralStringDelimiterLiteralStringDocLiteralStringDoubleLiteralStringEscapeLiteralStringHeredocLiteralStringInterpolLiteralStringOtherLiteralStringRegexLiteralStringSingleLiteralStringSymbolLiteralStringNameLiteralNumberLiteralNumberBinLiteralNumberFloatLiteralNumberHexLiteralNumberIntegerLiteralNumberIntegerLongLiteralNumberOctOperatorOperatorWordPunctuationCommentCommentHashbangCommentMultilineCommentSingleCommentSpecialCommentPreprocCommentPreprocFileGenericGenericDeletedGenericEmphGenericErrorGenericHeadingGenericInsertedGenericOutputGenericPromptGenericStrongGenericSubheadingGenericTracebackGenericUnderlineTextTextWhitespace"
 
 var _TokenType_map = map[TokenType]string{
-	0:    _TokenType_name[0:6],
-	1:    _TokenType_name[6:11],
-	2:    _TokenType_name[11:16],
-	1000: _TokenType_name[16:23],
-	1001: _TokenType_name[23:38],
-	1002: _TokenType_name[38:56],
-	1003: _TokenType_name[56:72],
-	1004: _TokenType_name[72:85],
-	1005: _TokenType_name[85:100],
-	1006: _TokenType_name[100:111],
-	2000: _TokenType_name[111:115],
-	2001: _TokenType_name[115:128],
-	2002: _TokenType_name[128:139],
-	2003: _TokenType_name[139:156],
-	2004: _TokenType_name[156:165],
-	2005: _TokenType_name[165:177],
-	2006: _TokenType_name[177:190],
-	2007: _TokenType_name[190:200],
-	2008: _TokenType_name[200:213],
-	2009: _TokenType_name[213:225],
-	2010: _TokenType_name[225:242],
-	2011: _TokenType_name[242:254],
-	2012: _TokenType_name[254:263],
-	2013: _TokenType_name[263:276],
-	2014: _TokenType_name[276:285],
-	2015: _TokenType_name[285:292],
-	2016: _TokenType_name[292:304],
-	2017: _TokenType_name[304:321],
-	2018: _TokenType_name[321:339],
-	2019: _TokenType_name[339:359],
-	2020: _TokenType_name[359:376],
-	3000: _TokenType_name[376:383],
-	3001: _TokenType_name[383:394],
-	3100: _TokenType_name[394:407],
-	3101: _TokenType_name[407:425],
-	3102: _TokenType_name[425:446],
-	3103: _TokenType_name[446:463],
-	3104: _TokenType_name[463:485],
-	3105: _TokenType_name[485:501],
-	3106: _TokenType_name[501:520],
-	3107: _TokenType_name[520:539],
-	3108: _TokenType_name[539:559],
-	3109: _TokenType_name[559:580],
-	3110: _TokenType_name[580:598],
-	3111: _TokenType_name[598:616],
-	3112: _TokenType_name[616:635],
-	3113: _TokenType_name[635:654],
-	3114: _TokenType_name[654:671],
-	3200: _TokenType_name[671:684],
-	3201: _TokenType_name[684:700],
-	3202: _TokenType_name[700:718],
-	3203: _TokenType_name[718:734],
-	3204: _TokenType_name[734:754],
-	3205: _TokenType_name[754:778],
-	3206: _TokenType_name[778:794],
-	4000: _TokenType_name[794:802],
-	4001: _TokenType_name[802:814],
-	5000: _TokenType_name[814:825],
-	6000: _TokenType_name[825:832],
-	6001: _TokenType_name[832:847],
-	6002: _TokenType_name[847:863],
-	6003: _TokenType_name[863:876],
-	6004: _TokenType_name[876:890],
-	6100: _TokenType_name[890:904],
-	6101: _TokenType_name[904:922],
-	7000: _TokenType_name[922:929],
-	7001: _TokenType_name[929:943],
-	7002: _TokenType_name[943:954],
-	7003: _TokenType_name[954:966],
-	7004: _TokenType_name[966:980],
-	7005: _TokenType_name[980:995],
-	7006: _TokenType_name[995:1008],
-	7007: _TokenType_name[1008:1021],
-	7008: _TokenType_name[1021:1034],
-	7009: _TokenType_name[1034:1051],
-	7010: _TokenType_name[1051:1067],
-	7011: _TokenType_name[1067:1083],
-	8000: _TokenType_name[1083:1087],
-	8001: _TokenType_name[1087:1101],
+	-1:   _TokenType_name[0:10],
+	0:    _TokenType_name[10:16],
+	1:    _TokenType_name[16:21],
+	2:    _TokenType_name[21:26],
+	3:    _TokenType_name[26:29],
+	1000: _TokenType_name[29:36],
+	1001: _TokenType_name[36:51],
+	1002: _TokenType_name[51:69],
+	1003: _TokenType_name[69:85],
+	1004: _TokenType_name[85:98],
+	1005: _TokenType_name[98:113],
+	1006: _TokenType_name[113:124],
+	2000: _TokenType_name[124:128],
+	2001: _TokenType_name[128:141],
+	2002: _TokenType_name[141:152],
+	2003: _TokenType_name[152:169],
+	2004: _TokenType_name[169:178],
+	2005: _TokenType_name[178:190],
+	2006: _TokenType_name[190:203],
+	2007: _TokenType_name[203:213],
+	2008: _TokenType_name[213:226],
+	2009: _TokenType_name[226:238],
+	2010: _TokenType_name[238:255],
+	2011: _TokenType_name[255:267],
+	2012: _TokenType_name[267:276],
+	2013: _TokenType_name[276:289],
+	2014: _TokenType_name[289:298],
+	2015: _TokenType_name[298:310],
+	2016: _TokenType_name[310:317],
+	2017: _TokenType_name[317:329],
+	2018: _TokenType_name[329:346],
+	2019: _TokenType_name[346:364],
+	2020: _TokenType_name[364:384],
+	2021: _TokenType_name[384:401],
+	3000: _TokenType_name[401:408],
+	3001: _TokenType_name[408:419],
+	3100: _TokenType_name[419:432],
+	3101: _TokenType_name[432:450],
+	3102: _TokenType_name[450:471],
+	3103: _TokenType_name[471:488],
+	3104: _TokenType_name[488:510],
+	3105: _TokenType_name[510:526],
+	3106: _TokenType_name[526:545],
+	3107: _TokenType_name[545:564],
+	3108: _TokenType_name[564:584],
+	3109: _TokenType_name[584:605],
+	3110: _TokenType_name[605:623],
+	3111: _TokenType_name[623:641],
+	3112: _TokenType_name[641:660],
+	3113: _TokenType_name[660:679],
+	3114: _TokenType_name[679:696],
+	3200: _TokenType_name[696:709],
+	3201: _TokenType_name[709:725],
+	3202: _TokenType_name[725:743],
+	3203: _TokenType_name[743:759],
+	3204: _TokenType_name[759:779],
+	3205: _TokenType_name[779:803],
+	3206: _TokenType_name[803:819],
+	4000: _TokenType_name[819:827],
+	4001: _TokenType_name[827:839],
+	5000: _TokenType_name[839:850],
+	6000: _TokenType_name[850:857],
+	6001: _TokenType_name[857:872],
+	6002: _TokenType_name[872:888],
+	6003: _TokenType_name[888:901],
+	6004: _TokenType_name[901:915],
+	6100: _TokenType_name[915:929],
+	6101: _TokenType_name[929:947],
+	7000: _TokenType_name[947:954],
+	7001: _TokenType_name[954:968],
+	7002: _TokenType_name[968:979],
+	7003: _TokenType_name[979:991],
+	7004: _TokenType_name[991:1005],
+	7005: _TokenType_name[1005:1020],
+	7006: _TokenType_name[1020:1033],
+	7007: _TokenType_name[1033:1046],
+	7008: _TokenType_name[1046:1059],
+	7009: _TokenType_name[1059:1076],
+	7010: _TokenType_name[1076:1092],
+	7011: _TokenType_name[1092:1108],
+	8000: _TokenType_name[1108:1112],
+	8001: _TokenType_name[1112:1126],
 }
 
 func (i TokenType) String() string {
diff --git a/types.go b/types.go
index 1204302..85230e6 100644
--- a/types.go
+++ b/types.go
@@ -1,5 +1,16 @@
 package chroma
 
+// Scheme is either dark or light.
+type Scheme int
+
+// Theme types.
+const (
+	DarkScheme Scheme = iota
+	LightScheme
+)
+
+//go:generate stringer -type TokenType
+
 // TokenType is the type of token to highlight.
 //
 // It is also an Emitter, emitting a single token of itself
@@ -10,10 +21,14 @@ type TokenType int
 // Categories of types are grouped in ranges of 1000, while sub-categories are in ranges of 100. For
 // example, the literal category is in the range 3000-3999. The sub-category for literal strings is
 // in the range 3100-3199.
+
+// Meta token types.
 const (
-	Escape TokenType = iota
+	Background TokenType = -1 - iota
+	Escape
 	Error
 	Other
+	EOF
 )
 
 // Keywords.
@@ -44,6 +59,7 @@ const (
 	NameLabel
 	NameNamespace
 	NameOther
+	NameOperator
 	NameTag
 	NameVariable
 	NameVariableClass