From 382b2ce94bc57b3bc7c94a6a1c03954e24f2666a Mon Sep 17 00:00:00 2001
From: Toastie <toastie@toastiet0ast.com>
Date: Sat, 22 Mar 2025 20:32:42 +1300
Subject: [PATCH] Added base files as well as base16 and styles

---
 .gitignore                               |  25 +
 base16/base16.go                         | 138 ++++++
 coalesce.go                              |  35 ++
 coalesce_test.go                         |  19 +
 colour.go                                | 192 ++++++++
 colour_test.go                           |  91 ++++
 delegate.go                              | 152 ++++++
 delegate_test.go                         | 111 +++++
 doc.go                                   |   7 +
 emitters.go                              | 218 +++++++++
 formatter.go                             |  43 ++
 go.mod                                   |  11 +
 go.sum                                   |   5 +
 iterator.go                              |  76 +++
 lexer.go                                 | 162 +++++++
 lexer_test.go                            |  48 ++
 mutator_test.go                          |  57 +++
 mutators.go                              | 201 ++++++++
 regexp.go                                | 483 +++++++++++++++++++
 regexp_test.go                           | 194 ++++++++
 registry.go                              | 210 +++++++++
 remap.go                                 |  94 ++++
 remap_test.go                            |  29 ++
 serialise.go                             | 479 +++++++++++++++++++
 serialise_test.go                        | 166 +++++++
 style.go                                 | 493 +++++++++++++++++++
 style_test.go                            | 122 +++++
 styles/api.go                            |  93 ++++
 styles/embedded/abap.xml                 |  11 +
 styles/embedded/algol.xml                |  18 +
 styles/embedded/algol_nu.xml             |  18 +
 styles/embedded/arduino.xml              |  18 +
 styles/embedded/autumn.xml               |  36 ++
 styles/embedded/average.xml              |  74 +++
 styles/embedded/base16-snazzy.xml        |  74 +++
 styles/embedded/borland.xml              |  26 +
 styles/embedded/bw.xml                   |  23 +
 styles/embedded/catppuccin-frappe.xml    |  83 ++++
 styles/embedded/catppuccin-latte.xml     |  83 ++++
 styles/embedded/catppuccin-macchiato.xml |  83 ++++
 styles/embedded/catppuccin-mocha.xml     |  83 ++++
 styles/embedded/colorful.xml             |  52 ++
 styles/embedded/doom-one.xml             |  51 ++
 styles/embedded/doom-one2.xml            |  64 +++
 styles/embedded/dracula.xml              |  74 +++
 styles/embedded/emacs.xml                |  44 ++
 styles/embedded/evergarden.xml           |  33 ++
 styles/embedded/friendly.xml             |  44 ++
 styles/embedded/fruity.xml               |  19 +
 styles/embedded/github-dark.xml          |  45 ++
 styles/embedded/github.xml               |  44 ++
 styles/embedded/gruvbox-light.xml        |  33 ++
 styles/embedded/gruvbox.xml              |  33 ++
 styles/embedded/hr_high_contrast.xml     |  12 +
 styles/embedded/hrdark.xml               |  10 +
 styles/embedded/igor.xml                 |   9 +
 styles/embedded/lovelace.xml             |  53 +++
 styles/embedded/manni.xml                |  44 ++
 styles/embedded/modus-operandi.xml       |  13 +
 styles/embedded/modus-vivendi.xml        |  13 +
 styles/embedded/monokai.xml              |  29 ++
 styles/embedded/monokailight.xml         |  26 +
 styles/embedded/murphy.xml               |  52 ++
 styles/embedded/native.xml               |  35 ++
 styles/embedded/nord.xml                 |  46 ++
 styles/embedded/onedark.xml              |  25 +
 styles/embedded/onesenterprise.xml       |  10 +
 styles/embedded/paraiso-dark.xml         |  37 ++
 styles/embedded/paraiso-light.xml        |  37 ++
 styles/embedded/pastie.xml               |  45 ++
 styles/embedded/perldoc.xml              |  37 ++
 styles/embedded/pygments.xml             |  42 ++
 styles/embedded/rainbow_dash.xml         |  40 ++
 styles/embedded/rose-pine-dawn.xml       |  29 ++
 styles/embedded/rose-pine-moon.xml       |  29 ++
 styles/embedded/rose-pine.xml            |  29 ++
 styles/embedded/rrt.xml                  |  13 +
 styles/embedded/solarized-dark.xml       |  39 ++
 styles/embedded/solarized-dark256.xml    |  41 ++
 styles/embedded/solarized-light.xml      |  17 +
 styles/embedded/swapoff.xml              |  18 +
 styles/embedded/tango.xml                |  72 +++
 styles/embedded/tokyonight-day.xml       |  83 ++++
 styles/embedded/tokyonight-moon.xml      |  83 ++++
 styles/embedded/tokyonight-night.xml     |  83 ++++
 styles/embedded/tokyonight-storm.xml     |  83 ++++
 styles/embedded/trac.xml                 |  35 ++
 styles/embedded/vim.xml                  |  29 ++
 styles/embedded/vs.xml                   |  16 +
 styles/embedded/vulcan.xml               |  74 +++
 styles/embedded/witchhazel.xml           |  31 ++
 styles/embedded/xcode-dark.xml           |  31 ++
 styles/embedded/xcode.xml                |  22 +
 tokentype_enumer.go                      | 573 +++++++++++++++++++++++
 types.go                                 | 340 ++++++++++++++
 95 files changed, 7505 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 base16/base16.go
 create mode 100644 coalesce.go
 create mode 100644 coalesce_test.go
 create mode 100644 colour.go
 create mode 100644 colour_test.go
 create mode 100644 delegate.go
 create mode 100644 delegate_test.go
 create mode 100644 doc.go
 create mode 100644 emitters.go
 create mode 100644 formatter.go
 create mode 100644 go.mod
 create mode 100644 go.sum
 create mode 100644 iterator.go
 create mode 100644 lexer.go
 create mode 100644 lexer_test.go
 create mode 100644 mutator_test.go
 create mode 100644 mutators.go
 create mode 100644 regexp.go
 create mode 100644 regexp_test.go
 create mode 100644 registry.go
 create mode 100644 remap.go
 create mode 100644 remap_test.go
 create mode 100644 serialise.go
 create mode 100644 serialise_test.go
 create mode 100644 style.go
 create mode 100644 style_test.go
 create mode 100644 styles/api.go
 create mode 100644 styles/embedded/abap.xml
 create mode 100644 styles/embedded/algol.xml
 create mode 100644 styles/embedded/algol_nu.xml
 create mode 100644 styles/embedded/arduino.xml
 create mode 100644 styles/embedded/autumn.xml
 create mode 100644 styles/embedded/average.xml
 create mode 100644 styles/embedded/base16-snazzy.xml
 create mode 100644 styles/embedded/borland.xml
 create mode 100644 styles/embedded/bw.xml
 create mode 100644 styles/embedded/catppuccin-frappe.xml
 create mode 100644 styles/embedded/catppuccin-latte.xml
 create mode 100644 styles/embedded/catppuccin-macchiato.xml
 create mode 100644 styles/embedded/catppuccin-mocha.xml
 create mode 100644 styles/embedded/colorful.xml
 create mode 100644 styles/embedded/doom-one.xml
 create mode 100644 styles/embedded/doom-one2.xml
 create mode 100644 styles/embedded/dracula.xml
 create mode 100644 styles/embedded/emacs.xml
 create mode 100644 styles/embedded/evergarden.xml
 create mode 100644 styles/embedded/friendly.xml
 create mode 100644 styles/embedded/fruity.xml
 create mode 100644 styles/embedded/github-dark.xml
 create mode 100644 styles/embedded/github.xml
 create mode 100644 styles/embedded/gruvbox-light.xml
 create mode 100644 styles/embedded/gruvbox.xml
 create mode 100644 styles/embedded/hr_high_contrast.xml
 create mode 100644 styles/embedded/hrdark.xml
 create mode 100644 styles/embedded/igor.xml
 create mode 100644 styles/embedded/lovelace.xml
 create mode 100644 styles/embedded/manni.xml
 create mode 100644 styles/embedded/modus-operandi.xml
 create mode 100644 styles/embedded/modus-vivendi.xml
 create mode 100644 styles/embedded/monokai.xml
 create mode 100644 styles/embedded/monokailight.xml
 create mode 100644 styles/embedded/murphy.xml
 create mode 100644 styles/embedded/native.xml
 create mode 100644 styles/embedded/nord.xml
 create mode 100644 styles/embedded/onedark.xml
 create mode 100644 styles/embedded/onesenterprise.xml
 create mode 100644 styles/embedded/paraiso-dark.xml
 create mode 100644 styles/embedded/paraiso-light.xml
 create mode 100644 styles/embedded/pastie.xml
 create mode 100644 styles/embedded/perldoc.xml
 create mode 100644 styles/embedded/pygments.xml
 create mode 100644 styles/embedded/rainbow_dash.xml
 create mode 100644 styles/embedded/rose-pine-dawn.xml
 create mode 100644 styles/embedded/rose-pine-moon.xml
 create mode 100644 styles/embedded/rose-pine.xml
 create mode 100644 styles/embedded/rrt.xml
 create mode 100644 styles/embedded/solarized-dark.xml
 create mode 100644 styles/embedded/solarized-dark256.xml
 create mode 100644 styles/embedded/solarized-light.xml
 create mode 100644 styles/embedded/swapoff.xml
 create mode 100644 styles/embedded/tango.xml
 create mode 100644 styles/embedded/tokyonight-day.xml
 create mode 100644 styles/embedded/tokyonight-moon.xml
 create mode 100644 styles/embedded/tokyonight-night.xml
 create mode 100644 styles/embedded/tokyonight-storm.xml
 create mode 100644 styles/embedded/trac.xml
 create mode 100644 styles/embedded/vim.xml
 create mode 100644 styles/embedded/vs.xml
 create mode 100644 styles/embedded/vulcan.xml
 create mode 100644 styles/embedded/witchhazel.xml
 create mode 100644 styles/embedded/xcode-dark.xml
 create mode 100644 styles/embedded/xcode.xml
 create mode 100644 tokentype_enumer.go
 create mode 100644 types.go

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ca99310
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,25 @@
+# Binaries for programs and plugins
+.git
+.idea
+.vscode
+.hermit
+*.exe
+*.dll
+*.so
+*.dylib
+/cmd/chroma/chroma
+
+# Test binary, build with `go test -c`
+*.test
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out
+
+# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
+.glide/
+
+_models/
+
+_examples/
+*.min.*
+build/
\ No newline at end of file
diff --git a/base16/base16.go b/base16/base16.go
new file mode 100644
index 0000000..98f9336
--- /dev/null
+++ b/base16/base16.go
@@ -0,0 +1,138 @@
+package base16
+
+import (
+	"io"
+
+	"gopkg.in/yaml.v3"
+	"toastielab.dev/toastie-stuff/chroma/v2"
+)
+
+type Base16 struct {
+	// Scheme is the name of the scheme.
+	Scheme string `yaml:"scheme"`
+	// Author is the name of the author.
+	Author string `yaml:"author"`
+	// Theme is either "light" or "dark".
+	Theme string `yaml:"theme"`
+	// Base00 Default Background
+	Base00 string `yaml:"base00"`
+	// Base01 Lighter Background (Used for status bars, line number and folding marks)
+	Base01 string `yaml:"base01"`
+	// Base02 Selection Background
+	Base02 string `yaml:"base02"`
+	// Base03 Comments, Invisibles, Line Highlighting
+	Base03 string `yaml:"base03"`
+	// Base04 Dark Foreground (Used for status bars)
+	Base04 string `yaml:"base04"`
+	// Base05 Default Foreground, Caret, Delimiters, Operators
+	Base05 string `yaml:"base05"`
+	// Base06 Light Foreground (Not often used)
+	Base06 string `yaml:"base06"`
+	// Base07 Light Background (Not often used)
+	Base07 string `yaml:"base07"`
+	// Base08 Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted
+	Base08 string `yaml:"base08"`
+	// Base09 Integers, Boolean, Constants, XML Attributes, Markup Link Url
+	Base09 string `yaml:"base09"`
+	// Base0A Classes, Markup Bold, Search Text Background
+	Base0A string `yaml:"base0A"`
+	// Base0B Strings, Inherited Class, Markup Code, Diff Inserted
+	Base0B string `yaml:"base0B"`
+	// Base0C Support, Regular Expressions, Escape Characters, Markup Quotes
+	Base0C string `yaml:"base0C"`
+	// Base0D Functions, Methods, Attribute IDs, Headings
+	Base0D string `yaml:"base0D"`
+	// Base0E Keywords, Storage, Selector, Markup Italic, Diff Changed
+	Base0E string `yaml:"base0E"`
+	// Base0F Deprecated, Opening/Closing Embedded Language Tags, e.g. `<?php ?>`
+	Base0F string `yaml:"base0F"`
+}
+
+func (b *Base16) toStyle() (*chroma.Style, error) {
+	entries := chroma.StyleEntries{
+		chroma.Other:                    "#" + b.Base05,
+		chroma.Error:                    "#" + b.Base08,
+		chroma.Background:               "bg:" + "#" + b.Base00,
+		chroma.Keyword:                  "#" + b.Base0E,
+		chroma.KeywordConstant:          "#" + b.Base0E,
+		chroma.KeywordDeclaration:       "#" + b.Base08,
+		chroma.KeywordNamespace:         "#" + b.Base0E,
+		chroma.KeywordPseudo:            "#" + b.Base0E,
+		chroma.KeywordReserved:          "#" + b.Base0E,
+		chroma.KeywordType:              "#" + b.Base0C,
+		chroma.Name:                     "#" + b.Base05,
+		chroma.NameAttribute:            "#" + b.Base0D,
+		chroma.NameBuiltin:              "#" + b.Base08,
+		chroma.NameBuiltinPseudo:        "#" + b.Base05,
+		chroma.NameClass:                "#" + b.Base0A,
+		chroma.NameConstant:             "#" + b.Base09,
+		chroma.NameDecorator:            "#" + b.Base09,
+		chroma.NameEntity:               "#" + b.Base05,
+		chroma.NameException:            "#" + b.Base05,
+		chroma.NameFunction:             "#" + b.Base0D,
+		chroma.NameLabel:                "#" + b.Base08,
+		chroma.NameNamespace:            "#" + b.Base05,
+		chroma.NameOther:                "#" + b.Base05,
+		chroma.NameTag:                  "#" + b.Base0E,
+		chroma.NameVariable:             "#" + b.Base08,
+		chroma.NameVariableClass:        "#" + b.Base08,
+		chroma.NameVariableGlobal:       "#" + b.Base08,
+		chroma.NameVariableInstance:     "#" + b.Base08,
+		chroma.Literal:                  "#" + b.Base05,
+		chroma.LiteralDate:              "#" + b.Base05,
+		chroma.LiteralString:            "#" + b.Base0B,
+		chroma.LiteralStringBacktick:    "#" + b.Base0B,
+		chroma.LiteralStringChar:        "#" + b.Base0B,
+		chroma.LiteralStringDoc:         "#" + b.Base0B,
+		chroma.LiteralStringDouble:      "#" + b.Base0B,
+		chroma.LiteralStringEscape:      "#" + b.Base0B,
+		chroma.LiteralStringHeredoc:     "#" + b.Base0B,
+		chroma.LiteralStringInterpol:    "#" + b.Base0B,
+		chroma.LiteralStringOther:       "#" + b.Base0B,
+		chroma.LiteralStringRegex:       "#" + b.Base0B,
+		chroma.LiteralStringSingle:      "#" + b.Base0B,
+		chroma.LiteralStringSymbol:      "#" + b.Base0B,
+		chroma.LiteralNumber:            "#" + b.Base09,
+		chroma.LiteralNumberBin:         "#" + b.Base09,
+		chroma.LiteralNumberFloat:       "#" + b.Base09,
+		chroma.LiteralNumberHex:         "#" + b.Base09,
+		chroma.LiteralNumberInteger:     "#" + b.Base09,
+		chroma.LiteralNumberIntegerLong: "#" + b.Base09,
+		chroma.LiteralNumberOct:         "#" + b.Base09,
+		chroma.Operator:                 "#" + b.Base0E,
+		chroma.OperatorWord:             "#" + b.Base0E,
+		chroma.Punctuation:              "#" + b.Base05,
+		chroma.Comment:                  "#" + b.Base03,
+		chroma.CommentHashbang:          "#" + b.Base03,
+		chroma.CommentMultiline:         "#" + b.Base03,
+		chroma.CommentSingle:            "#" + b.Base03,
+		chroma.CommentSpecial:           "#" + b.Base03,
+		chroma.CommentPreproc:           "#" + b.Base03,
+		chroma.Generic:                  "#" + b.Base05,
+		chroma.GenericDeleted:           "#" + b.Base08,
+		chroma.GenericEmph:              "underline #" + b.Base05,
+		chroma.GenericError:             "#" + b.Base08,
+		chroma.GenericHeading:           "bold #" + b.Base05,
+		chroma.GenericInserted:          "bold #" + b.Base05,
+		chroma.GenericOutput:            "#" + b.Base02,
+		chroma.GenericPrompt:            "#" + b.Base05,
+		chroma.GenericStrong:            "italic #" + b.Base05,
+		chroma.GenericSubheading:        "bold #" + b.Base05,
+		chroma.GenericTraceback:         "#" + b.Base05,
+		chroma.GenericUnderline:         "underline",
+		chroma.Text:                     "#" + b.Base05,
+		chroma.TextWhitespace:           "#" + b.Base05,
+	}
+
+	return chroma.NewStyle(b.Scheme, b.Theme, entries)
+}
+
+func NewStyle(r io.Reader) (*chroma.Style, error) {
+	dec := yaml.NewDecoder(r)
+	b16 := &Base16{}
+	if err := dec.Decode(b16); err != nil {
+		return nil, err
+	}
+
+	return b16.toStyle()
+}
diff --git a/coalesce.go b/coalesce.go
new file mode 100644
index 0000000..f504895
--- /dev/null
+++ b/coalesce.go
@@ -0,0 +1,35 @@
+package chroma
+
+// Coalesce is a Lexer interceptor that collapses runs of common types into a single token.
+func Coalesce(lexer Lexer) Lexer { return &coalescer{lexer} }
+
+type coalescer struct{ Lexer }
+
+func (d *coalescer) Tokenise(options *TokeniseOptions, text string) (Iterator, error) {
+	var prev Token
+	it, err := d.Lexer.Tokenise(options, text)
+	if err != nil {
+		return nil, err
+	}
+	return func() Token {
+		for token := it(); token != (EOF); token = it() {
+			if len(token.Value) == 0 {
+				continue
+			}
+			if prev == EOF {
+				prev = token
+			} else {
+				if prev.Type == token.Type && len(prev.Value) < 8192 {
+					prev.Value += token.Value
+				} else {
+					out := prev
+					prev = token
+					return out
+				}
+			}
+		}
+		out := prev
+		prev = EOF
+		return out
+	}, nil
+}
diff --git a/coalesce_test.go b/coalesce_test.go
new file mode 100644
index 0000000..fc39cb8
--- /dev/null
+++ b/coalesce_test.go
@@ -0,0 +1,19 @@
+package chroma
+
+import (
+	"testing"
+
+	"github.com/alecthomas/assert/v2"
+)
+
+func TestCoalesce(t *testing.T) {
+	lexer := Coalesce(mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+		"root": []Rule{
+			{`[!@#$%^&*()]`, Punctuation, nil},
+		},
+	}))
+	actual, err := Tokenise(lexer, nil, "!@#$")
+	assert.NoError(t, err)
+	expected := []Token{{Punctuation, "!@#$"}}
+	assert.Equal(t, expected, actual)
+}
diff --git a/colour.go b/colour.go
new file mode 100644
index 0000000..b7fd6e0
--- /dev/null
+++ b/colour.go
@@ -0,0 +1,192 @@
+package chroma
+
+import (
+	"fmt"
+	"math"
+	"strconv"
+	"strings"
+)
+
+// ANSI2RGB maps ANSI colour names, as supported by Chroma, to hex RGB values.
+var ANSI2RGB = map[string]string{
+	"#ansiblack":     "000000",
+	"#ansidarkred":   "7f0000",
+	"#ansidarkgreen": "007f00",
+	"#ansibrown":     "7f7fe0",
+	"#ansidarkblue":  "00007f",
+	"#ansipurple":    "7f007f",
+	"#ansiteal":      "007f7f",
+	"#ansilightgray": "e5e5e5",
+	// Normal
+	"#ansidarkgray":  "555555",
+	"#ansired":       "ff0000",
+	"#ansigreen":     "00ff00",
+	"#ansiyellow":    "ffff00",
+	"#ansiblue":      "0000ff",
+	"#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
+
+// NewColour creates a Colour directly from RGB values.
+func NewColour(r, g, b uint8) Colour {
+	return ParseColour(fmt.Sprintf("%02x%02x%02x", r, g, b))
+}
+
+// Distance between this colour and another.
+//
+// This uses the approach described here (https://www.compuphase.com/cmetric.htm).
+// This is not as accurate as LAB, et. al. but is *vastly* simpler and sufficient for our needs.
+func (c Colour) Distance(e2 Colour) float64 {
+	ar, ag, ab := int64(c.Red()), int64(c.Green()), int64(c.Blue())
+	br, bg, bb := int64(e2.Red()), int64(e2.Green()), int64(e2.Blue())
+	rmean := (ar + br) / 2
+	r := ar - br
+	g := ag - bg
+	b := ab - bb
+	return math.Sqrt(float64((((512 + rmean) * r * r) >> 8) + 4*g*g + (((767 - rmean) * b * b) >> 8)))
+}
+
+// Brighten returns a copy of this colour with its brightness adjusted.
+//
+// If factor is negative, the colour is darkened.
+//
+// Uses approach described here (http://www.pvladov.com/2012/09/make-color-lighter-or-darker.html).
+func (c Colour) Brighten(factor float64) Colour {
+	r := float64(c.Red())
+	g := float64(c.Green())
+	b := float64(c.Blue())
+
+	if factor < 0 {
+		factor++
+		r *= factor
+		g *= factor
+		b *= factor
+	} else {
+		r = (255-r)*factor + r
+		g = (255-g)*factor + g
+		b = (255-b)*factor + b
+	}
+	return NewColour(uint8(r), uint8(g), uint8(b))
+}
+
+// BrightenOrDarken brightens a colour if it is < 0.5 brightness or darkens if > 0.5 brightness.
+func (c Colour) BrightenOrDarken(factor float64) Colour {
+	if c.Brightness() < 0.5 {
+		return c.Brighten(factor)
+	}
+	return c.Brighten(-factor)
+}
+
+// ClampBrightness returns a copy of this colour with its brightness adjusted such that
+// it falls within the range [min, max] (or very close to it due to rounding errors).
+// The supplied values use the same [0.0, 1.0] range as Brightness.
+func (c Colour) ClampBrightness(min, max float64) Colour {
+	if !c.IsSet() {
+		return c
+	}
+
+	min = math.Max(min, 0)
+	max = math.Min(max, 1)
+	current := c.Brightness()
+	target := math.Min(math.Max(current, min), max)
+	if current == target {
+		return c
+	}
+
+	r := float64(c.Red())
+	g := float64(c.Green())
+	b := float64(c.Blue())
+	rgb := r + g + b
+	if target > current {
+		// Solve for x: target == ((255-r)*x + r + (255-g)*x + g + (255-b)*x + b) / 255 / 3
+		return c.Brighten((target*255*3 - rgb) / (255*3 - rgb))
+	}
+	// Solve for x: target == (r*(x+1) + g*(x+1) + b*(x+1)) / 255 / 3
+	return c.Brighten((target*255*3)/rgb - 1)
+}
+
+// Brightness of the colour (roughly) in the range 0.0 to 1.0.
+func (c Colour) Brightness() float64 {
+	return (float64(c.Red()) + float64(c.Green()) + float64(c.Blue())) / 255.0 / 3.0
+}
+
+// ParseColour in the forms #rgb, #rrggbb, #ansi<colour>, or #<colour>.
+// Will return an "unset" colour if invalid.
+func ParseColour(colour string) Colour {
+	colour = normaliseColour(colour)
+	n, err := strconv.ParseUint(colour, 16, 32)
+	if err != nil {
+		return 0
+	}
+	return Colour(n + 1)
+}
+
+// MustParseColour is like ParseColour except it panics if the colour is invalid.
+//
+// Will panic if colour is in an invalid format.
+func MustParseColour(colour string) Colour {
+	parsed := ParseColour(colour)
+	if !parsed.IsSet() {
+		panic(fmt.Errorf("invalid colour %q", colour))
+	}
+	return parsed
+}
+
+// IsSet returns true if the colour is set.
+func (c Colour) IsSet() bool { return c != 0 }
+
+func (c Colour) String() string   { return fmt.Sprintf("#%06x", int(c-1)) }
+func (c Colour) GoString() string { return fmt.Sprintf("Colour(0x%06x)", int(c-1)) }
+
+// Red component of colour.
+func (c Colour) Red() uint8 { return uint8(((c - 1) >> 16) & 0xff) }
+
+// Green component of colour.
+func (c Colour) Green() uint8 { return uint8(((c - 1) >> 8) & 0xff) }
+
+// Blue component of colour.
+func (c Colour) Blue() uint8 { return uint8((c - 1) & 0xff) }
+
+// Colours is an orderable set of colours.
+type Colours []Colour
+
+func (c Colours) Len() int           { return len(c) }
+func (c Colours) Swap(i, j int)      { c[i], c[j] = c[j], c[i] }
+func (c Colours) Less(i, j int) bool { return c[i] < c[j] }
+
+// Convert colours to #rrggbb.
+func normaliseColour(colour string) string {
+	if ansi, ok := ANSI2RGB[colour]; ok {
+		return ansi
+	}
+	if strings.HasPrefix(colour, "#") {
+		colour = colour[1:]
+		if len(colour) == 3 {
+			return colour[0:1] + colour[0:1] + colour[1:2] + colour[1:2] + colour[2:3] + colour[2:3]
+		}
+	}
+	return colour
+}
diff --git a/colour_test.go b/colour_test.go
new file mode 100644
index 0000000..8d75f64
--- /dev/null
+++ b/colour_test.go
@@ -0,0 +1,91 @@
+package chroma
+
+import (
+	"math"
+	"testing"
+
+	"github.com/alecthomas/assert/v2"
+)
+
+func TestColourRGB(t *testing.T) {
+	colour := ParseColour("#8913af")
+	assert.Equal(t, uint8(0x89), colour.Red())
+	assert.Equal(t, uint8(0x13), colour.Green())
+	assert.Equal(t, uint8(0xaf), colour.Blue())
+}
+
+func TestColourString(t *testing.T) {
+	assert.Equal(t, "#8913af", ParseColour("#8913af").String())
+}
+
+func distance(a, b uint8) uint8 {
+	if a < b {
+		return b - a
+	}
+	return a - b
+}
+
+func TestColourBrighten(t *testing.T) {
+	actual := NewColour(128, 128, 128).Brighten(0.5)
+	// Closeish to what we expect is fine.
+	assert.True(t, distance(192, actual.Red()) <= 2)
+	assert.True(t, distance(192, actual.Blue()) <= 2)
+	assert.True(t, distance(192, actual.Green()) <= 2)
+	actual = NewColour(128, 128, 128).Brighten(-0.5)
+	assert.True(t, distance(65, actual.Red()) <= 2)
+	assert.True(t, distance(65, actual.Blue()) <= 2)
+	assert.True(t, distance(65, actual.Green()) <= 2)
+}
+
+func TestColourBrightess(t *testing.T) {
+	actual := NewColour(128, 128, 128).Brightness()
+	assert.True(t, distance(128, uint8(actual*255.0)) <= 2)
+}
+
+// hue returns c's hue. See https://stackoverflow.com/a/23094494.
+func hue(c Colour) float64 {
+	r := float64(c.Red()) / 255
+	g := float64(c.Green()) / 255
+	b := float64(c.Blue()) / 255
+
+	min := math.Min(math.Min(r, g), b)
+	max := math.Max(math.Max(r, g), b)
+
+	switch {
+	case r == min:
+		return (g - b) / (max - min)
+	case g == min:
+		return 2 + (b-r)/(max-min)
+	default:
+		return 4 + (r-g)/(max-min)
+	}
+}
+
+func TestColourClampBrightness(t *testing.T) {
+	// Start with a colour with a brightness close to 0.5.
+	initial := NewColour(0, 128, 255)
+	br := initial.Brightness()
+	assertInDelta(t, 0.5, br)
+
+	// Passing a range that includes the colour's brightness should be a no-op.
+	assert.Equal(t, initial.String(), initial.ClampBrightness(br-0.01, br+0.01).String())
+
+	// Clamping to [0, 0] or [1, 1] should produce black or white, respectively.
+	assert.Equal(t, "#000000", initial.ClampBrightness(0, 0).String())
+	assert.Equal(t, "#ffffff", initial.ClampBrightness(1, 1).String())
+
+	// Clamping to a brighter or darker range should produce the requested
+	// brightness while preserving the colour's hue.
+	brighter := initial.ClampBrightness(0.75, 1)
+	assertInDelta(t, 0.75, brighter.Brightness())
+	assertInDelta(t, hue(initial), hue(brighter))
+
+	darker := initial.ClampBrightness(0, 0.25)
+	assertInDelta(t, 0.25, darker.Brightness())
+	assertInDelta(t, hue(initial), hue(darker))
+}
+
+func assertInDelta(t *testing.T, expected, actual float64) {
+	const delta = 0.01 // used for brightness and hue comparisons
+	assert.True(t, actual > (expected-delta) && actual < (expected+delta))
+}
diff --git a/delegate.go b/delegate.go
new file mode 100644
index 0000000..f848194
--- /dev/null
+++ b/delegate.go
@@ -0,0 +1,152 @@
+package chroma
+
+import (
+	"bytes"
+)
+
+type delegatingLexer struct {
+	root     Lexer
+	language Lexer
+}
+
+// DelegatingLexer combines two lexers to handle the common case of a language embedded inside another, such as PHP
+// inside HTML or PHP inside plain text.
+//
+// It takes two lexer as arguments: a root lexer and a language lexer.  First everything is scanned using the language
+// lexer, which must return "Other" for unrecognised tokens. Then all "Other" tokens are lexed using the root lexer.
+// Finally, these two sets of tokens are merged.
+//
+// The lexers from the template lexer package use this base lexer.
+func DelegatingLexer(root Lexer, language Lexer) Lexer {
+	return &delegatingLexer{
+		root:     root,
+		language: language,
+	}
+}
+
+func (d *delegatingLexer) AnalyseText(text string) float32 {
+	return d.root.AnalyseText(text)
+}
+
+func (d *delegatingLexer) SetAnalyser(analyser func(text string) float32) Lexer {
+	d.root.SetAnalyser(analyser)
+	return d
+}
+
+func (d *delegatingLexer) SetRegistry(r *LexerRegistry) Lexer {
+	d.root.SetRegistry(r)
+	d.language.SetRegistry(r)
+	return d
+}
+
+func (d *delegatingLexer) Config() *Config {
+	return d.language.Config()
+}
+
+// An insertion is the character range where language tokens should be inserted.
+type insertion struct {
+	start, end int
+	tokens     []Token
+}
+
+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
+	}
+	// Compute insertions and gather "Other" tokens.
+	others := &bytes.Buffer{}
+	insertions := []*insertion{}
+	var insert *insertion
+	offset := 0
+	var last Token
+	for _, t := range tokens {
+		if t.Type == Other {
+			if last != EOF && insert != nil && last.Type != Other {
+				insert.end = offset
+			}
+			others.WriteString(t.Value)
+		} else {
+			if last == EOF || last.Type == Other {
+				insert = &insertion{start: offset}
+				insertions = append(insertions, insert)
+			}
+			insert.tokens = append(insert.tokens, t)
+		}
+		last = t
+		offset += len(t.Value)
+	}
+
+	if len(insertions) == 0 {
+		return d.root.Tokenise(options, text)
+	}
+
+	// Lex the other tokens.
+	rootTokens, err := Tokenise(Coalesce(d.root), options, others.String())
+	if err != nil {
+		return nil, err
+	}
+
+	// Interleave the two sets of tokens.
+	var out []Token
+	offset = 0 // Offset into text.
+	tokenIndex := 0
+	nextToken := func() Token {
+		if tokenIndex >= len(rootTokens) {
+			return EOF
+		}
+		t := rootTokens[tokenIndex]
+		tokenIndex++
+		return t
+	}
+	insertionIndex := 0
+	nextInsertion := func() *insertion {
+		if insertionIndex >= len(insertions) {
+			return nil
+		}
+		i := insertions[insertionIndex]
+		insertionIndex++
+		return i
+	}
+	t := nextToken()
+	i := nextInsertion()
+	for t != EOF || i != nil {
+		// fmt.Printf("%d->%d:%q   %d->%d:%q\n", offset, offset+len(t.Value), t.Value, i.start, i.end, Stringify(i.tokens...))
+		if t == EOF || (i != nil && i.start < offset+len(t.Value)) {
+			var l Token
+			l, t = splitToken(t, i.start-offset)
+			if l != EOF {
+				out = append(out, l)
+				offset += len(l.Value)
+			}
+			out = append(out, i.tokens...)
+			offset += i.end - i.start
+			if t == EOF {
+				t = nextToken()
+			}
+			i = nextInsertion()
+		} else {
+			out = append(out, t)
+			offset += len(t.Value)
+			t = nextToken()
+		}
+	}
+	return Literator(out...), nil
+}
+
+func splitToken(t Token, offset int) (l Token, r Token) {
+	if t == EOF {
+		return EOF, EOF
+	}
+	if offset == 0 {
+		return EOF, t
+	}
+	if offset == len(t.Value) {
+		return t, EOF
+	}
+	l = t.Clone()
+	r = t.Clone()
+	l.Value = l.Value[:offset]
+	r.Value = r.Value[offset:]
+	return
+}
diff --git a/delegate_test.go b/delegate_test.go
new file mode 100644
index 0000000..9c4a09b
--- /dev/null
+++ b/delegate_test.go
@@ -0,0 +1,111 @@
+package chroma
+
+import (
+	"testing"
+
+	"github.com/alecthomas/assert/v2"
+)
+
+func makeDelegationTestLexers(t *testing.T) (lang Lexer, root Lexer) {
+	return mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+			"root": {
+				{`\<\?`, CommentPreproc, Push("inside")},
+				{`.`, Other, nil},
+			},
+			"inside": {
+				{`\?\>`, CommentPreproc, Pop(1)},
+				{`\bwhat\b`, Keyword, nil},
+				{`\s+`, Whitespace, nil},
+			},
+		}),
+		mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+			"root": {
+				{`\bhello\b`, Keyword, nil},
+				{`\b(world|there)\b`, Name, nil},
+				{`\s+`, Whitespace, nil},
+			},
+		})
+}
+
+func TestDelegate(t *testing.T) {
+	testdata := []struct {
+		name     string
+		source   string
+		expected []Token
+	}{
+		{"SourceInMiddle", `hello world <? what ?> there`, []Token{
+			{Keyword, "hello"},
+			{TextWhitespace, " "},
+			{Name, "world"},
+			{TextWhitespace, " "},
+			// lang
+			{CommentPreproc, "<?"},
+			{Whitespace, " "},
+			{Keyword, "what"},
+			{Whitespace, " "},
+			{CommentPreproc, "?>"},
+			// /lang
+			{TextWhitespace, " "},
+			{Name, "there"},
+		}},
+		{"SourceBeginning", `<? what ?> hello world there`, []Token{
+			{CommentPreproc, "<?"},
+			{TextWhitespace, " "},
+			{Keyword, "what"},
+			{TextWhitespace, " "},
+			{CommentPreproc, "?>"},
+			{TextWhitespace, " "},
+			{Keyword, "hello"},
+			{TextWhitespace, " "},
+			{Name, "world"},
+			{TextWhitespace, " "},
+			{Name, "there"},
+		}},
+		{"SourceEnd", `hello world <? what there`, []Token{
+			{Keyword, "hello"},
+			{TextWhitespace, " "},
+			{Name, "world"},
+			{TextWhitespace, " "},
+			// lang
+			{CommentPreproc, "<?"},
+			{Whitespace, " "},
+			{Keyword, "what"},
+			{TextWhitespace, " "},
+			{Error, "there"},
+		}},
+		{"SourceMultiple", "hello world <? what ?> hello there <? what ?> hello", []Token{
+			{Keyword, "hello"},
+			{TextWhitespace, " "},
+			{Name, "world"},
+			{TextWhitespace, " "},
+			{CommentPreproc, "<?"},
+			{TextWhitespace, " "},
+			{Keyword, "what"},
+			{TextWhitespace, " "},
+			{CommentPreproc, "?>"},
+			{TextWhitespace, " "},
+			{Keyword, "hello"},
+			{TextWhitespace, " "},
+			{Name, "there"},
+			{TextWhitespace, " "},
+			{CommentPreproc, "<?"},
+			{TextWhitespace, " "},
+			{Keyword, "what"},
+			{TextWhitespace, " "},
+			{CommentPreproc, "?>"},
+			{TextWhitespace, " "},
+			{Keyword, "hello"},
+		}},
+	}
+	lang, root := makeDelegationTestLexers(t)
+	delegate := DelegatingLexer(root, lang)
+	for _, test := range testdata {
+		// nolint: scopelint
+		t.Run(test.name, func(t *testing.T) {
+			it, err := delegate.Tokenise(nil, test.source)
+			assert.NoError(t, err)
+			actual := it.Tokens()
+			assert.Equal(t, test.expected, actual)
+		})
+	}
+}
diff --git a/doc.go b/doc.go
new file mode 100644
index 0000000..4dde77c
--- /dev/null
+++ b/doc.go
@@ -0,0 +1,7 @@
+// Package chroma takes source code and other structured text and converts it into syntax highlighted HTML, ANSI-
+// coloured text, etc.
+//
+// Chroma is based heavily on Pygments, and includes translators for Pygments lexers and styles.
+//
+// For more information, go here: https://github.com/alecthomas/chroma
+package chroma
diff --git a/emitters.go b/emitters.go
new file mode 100644
index 0000000..0788b5b
--- /dev/null
+++ b/emitters.go
@@ -0,0 +1,218 @@
+package chroma
+
+import (
+	"fmt"
+)
+
+// An Emitter takes group matches and returns tokens.
+type Emitter interface {
+	// Emit tokens for the given regex groups.
+	Emit(groups []string, state *LexerState) Iterator
+}
+
+// SerialisableEmitter is an Emitter that can be serialised and deserialised to/from JSON.
+type SerialisableEmitter interface {
+	Emitter
+	EmitterKind() string
+}
+
+// EmitterFunc is a function that is an Emitter.
+type EmitterFunc func(groups []string, state *LexerState) Iterator
+
+// Emit tokens for groups.
+func (e EmitterFunc) Emit(groups []string, state *LexerState) Iterator {
+	return e(groups, state)
+}
+
+type Emitters []Emitter
+
+type byGroupsEmitter struct {
+	Emitters
+}
+
+// ByGroups emits a token for each matching group in the rule's regex.
+func ByGroups(emitters ...Emitter) Emitter {
+	return &byGroupsEmitter{Emitters: emitters}
+}
+
+func (b *byGroupsEmitter) EmitterKind() string { return "bygroups" }
+
+func (b *byGroupsEmitter) Emit(groups []string, state *LexerState) Iterator {
+	iterators := make([]Iterator, 0, len(groups)-1)
+	if len(b.Emitters) != len(groups)-1 {
+		iterators = append(iterators, Error.Emit(groups, state))
+		// panic(errors.Errorf("number of groups %q does not match number of emitters %v", groups, emitters))
+	} else {
+		for i, group := range groups[1:] {
+			if b.Emitters[i] != nil {
+				iterators = append(iterators, b.Emitters[i].Emit([]string{group}, state))
+			}
+		}
+	}
+	return Concaterator(iterators...)
+}
+
+// ByGroupNames emits a token for each named matching group in the rule's regex.
+func ByGroupNames(emitters map[string]Emitter) Emitter {
+	return EmitterFunc(func(groups []string, state *LexerState) Iterator {
+		iterators := make([]Iterator, 0, len(state.NamedGroups)-1)
+		if len(state.NamedGroups)-1 == 0 {
+			if emitter, ok := emitters[`0`]; ok {
+				iterators = append(iterators, emitter.Emit(groups, state))
+			} else {
+				iterators = append(iterators, Error.Emit(groups, state))
+			}
+		} else {
+			ruleRegex := state.Rules[state.State][state.Rule].Regexp
+			for i := 1; i < len(state.NamedGroups); i++ {
+				groupName := ruleRegex.GroupNameFromNumber(i)
+				group := state.NamedGroups[groupName]
+				if emitter, ok := emitters[groupName]; ok {
+					if emitter != nil {
+						iterators = append(iterators, emitter.Emit([]string{group}, state))
+					}
+				} else {
+					iterators = append(iterators, Error.Emit([]string{group}, state))
+				}
+			}
+		}
+		return Concaterator(iterators...)
+	})
+}
+
+// UsingByGroup emits tokens for the matched groups in the regex using a
+// sublexer. Used when lexing code blocks where the name of a sublexer is
+// contained within the block, for example on a Markdown text block or SQL
+// language block.
+//
+// An attempt to load the sublexer will be made using the captured value from
+// the text of the matched sublexerNameGroup. If a sublexer matching the
+// sublexerNameGroup is available, then tokens for the matched codeGroup will
+// be emitted using the sublexer. Otherwise, if no sublexer is available, then
+// tokens will be emitted from the passed emitter.
+//
+// Example:
+//
+//	var Markdown = internal.Register(MustNewLexer(
+//		&Config{
+//			Name:      "markdown",
+//			Aliases:   []string{"md", "mkd"},
+//			Filenames: []string{"*.md", "*.mkd", "*.markdown"},
+//			MimeTypes: []string{"text/x-markdown"},
+//		},
+//		Rules{
+//			"root": {
+//				{"^(```)(\\w+)(\\n)([\\w\\W]*?)(^```$)",
+//					UsingByGroup(
+//						2, 4,
+//						String, String, String, Text, String,
+//					),
+//					nil,
+//				},
+//			},
+//		},
+//	))
+//
+// See the lexers/markdown.go for the complete example.
+//
+// Note: panic's if the number of emitters does not equal the number of matched
+// groups in the regex.
+func UsingByGroup(sublexerNameGroup, codeGroup int, emitters ...Emitter) Emitter {
+	return &usingByGroup{
+		SublexerNameGroup: sublexerNameGroup,
+		CodeGroup:         codeGroup,
+		Emitters:          emitters,
+	}
+}
+
+type usingByGroup struct {
+	SublexerNameGroup int      `xml:"sublexer_name_group"`
+	CodeGroup         int      `xml:"code_group"`
+	Emitters          Emitters `xml:"emitters"`
+}
+
+func (u *usingByGroup) EmitterKind() string { return "usingbygroup" }
+func (u *usingByGroup) Emit(groups []string, state *LexerState) Iterator {
+	// bounds check
+	if len(u.Emitters) != len(groups)-1 {
+		panic("UsingByGroup expects number of emitters to be the same as len(groups)-1")
+	}
+
+	// grab sublexer
+	sublexer := state.Registry.Get(groups[u.SublexerNameGroup])
+
+	// build iterators
+	iterators := make([]Iterator, len(groups)-1)
+	for i, group := range groups[1:] {
+		if i == u.CodeGroup-1 && sublexer != nil {
+			var err error
+			iterators[i], err = sublexer.Tokenise(nil, groups[u.CodeGroup])
+			if err != nil {
+				panic(err)
+			}
+		} else if u.Emitters[i] != nil {
+			iterators[i] = u.Emitters[i].Emit([]string{group}, state)
+		}
+	}
+	return Concaterator(iterators...)
+}
+
+// UsingLexer returns an Emitter that uses a given Lexer for parsing and emitting.
+//
+// This Emitter is not serialisable.
+func UsingLexer(lexer Lexer) Emitter {
+	return EmitterFunc(func(groups []string, _ *LexerState) Iterator {
+		it, err := lexer.Tokenise(&TokeniseOptions{State: "root", Nested: true}, groups[0])
+		if err != nil {
+			panic(err)
+		}
+		return it
+	})
+}
+
+type usingEmitter struct {
+	Lexer string `xml:"lexer,attr"`
+}
+
+func (u *usingEmitter) EmitterKind() string { return "using" }
+
+func (u *usingEmitter) Emit(groups []string, state *LexerState) Iterator {
+	if state.Registry == nil {
+		panic(fmt.Sprintf("no LexerRegistry available for Using(%q)", u.Lexer))
+	}
+	lexer := state.Registry.Get(u.Lexer)
+	if lexer == nil {
+		panic(fmt.Sprintf("no such lexer %q", u.Lexer))
+	}
+	it, err := lexer.Tokenise(&TokeniseOptions{State: "root", Nested: true}, groups[0])
+	if err != nil {
+		panic(err)
+	}
+	return it
+}
+
+// Using returns an Emitter that uses a given Lexer reference for parsing and emitting.
+//
+// The referenced lexer must be stored in the same LexerRegistry.
+func Using(lexer string) Emitter {
+	return &usingEmitter{Lexer: lexer}
+}
+
+type usingSelfEmitter struct {
+	State string `xml:"state,attr"`
+}
+
+func (u *usingSelfEmitter) EmitterKind() string { return "usingself" }
+
+func (u *usingSelfEmitter) Emit(groups []string, state *LexerState) Iterator {
+	it, err := state.Lexer.Tokenise(&TokeniseOptions{State: u.State, Nested: true}, groups[0])
+	if err != nil {
+		panic(err)
+	}
+	return it
+}
+
+// UsingSelf is like Using, but uses the current Lexer.
+func UsingSelf(stateName string) Emitter {
+	return &usingSelfEmitter{stateName}
+}
diff --git a/formatter.go b/formatter.go
new file mode 100644
index 0000000..00dd5d8
--- /dev/null
+++ b/formatter.go
@@ -0,0 +1,43 @@
+package chroma
+
+import (
+	"io"
+)
+
+// A Formatter for Chroma lexers.
+type Formatter interface {
+	// Format returns a formatting function for tokens.
+	//
+	// If the iterator panics, the Formatter should recover.
+	Format(w io.Writer, style *Style, iterator Iterator) error
+}
+
+// A FormatterFunc is a Formatter implemented as a function.
+//
+// Guards against iterator panics.
+type FormatterFunc func(w io.Writer, style *Style, iterator Iterator) error
+
+func (f FormatterFunc) Format(w io.Writer, s *Style, it Iterator) (err error) { // nolint
+	defer func() {
+		if perr := recover(); perr != nil {
+			err = perr.(error)
+		}
+	}()
+	return f(w, s, it)
+}
+
+type recoveringFormatter struct {
+	Formatter
+}
+
+func (r recoveringFormatter) Format(w io.Writer, s *Style, it Iterator) (err error) {
+	defer func() {
+		if perr := recover(); perr != nil {
+			err = perr.(error)
+		}
+	}()
+	return r.Formatter.Format(w, s, it)
+}
+
+// RecoveringFormatter wraps a formatter with panic recovery.
+func RecoveringFormatter(formatter Formatter) Formatter { return recoveringFormatter{formatter} }
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..06e3656
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,11 @@
+module toastielab.dev/toastie-stuff/chroma/v2
+
+go 1.24.1
+
+require (
+	github.com/alecthomas/assert/v2 v2.10.0
+	github.com/alecthomas/repr v0.4.0
+	github.com/dlclark/regexp2 v1.11.0
+)
+
+require github.com/hexops/gotextdiff v1.0.3 // indirect
\ No newline at end of file
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..4bd5c9d
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,5 @@
+github.com/alecthomas/assert/v2 v2.10.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
+github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
+github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
+github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
+github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
diff --git a/iterator.go b/iterator.go
new file mode 100644
index 0000000..d5175de
--- /dev/null
+++ b/iterator.go
@@ -0,0 +1,76 @@
+package chroma
+
+import "strings"
+
+// An Iterator across tokens.
+//
+// EOF will be returned at the end of the Token stream.
+//
+// If an error occurs within an Iterator, it may propagate this in a panic. Formatters should recover.
+type Iterator func() Token
+
+// Tokens consumes all tokens from the iterator and returns them as a slice.
+func (i Iterator) Tokens() []Token {
+	var out []Token
+	for t := i(); t != EOF; t = i() {
+		out = append(out, t)
+	}
+	return out
+}
+
+// Concaterator concatenates tokens from a series of iterators.
+func Concaterator(iterators ...Iterator) Iterator {
+	return func() Token {
+		for len(iterators) > 0 {
+			t := iterators[0]()
+			if t != EOF {
+				return t
+			}
+			iterators = iterators[1:]
+		}
+		return EOF
+	}
+}
+
+// Literator converts a sequence of literal Tokens into an Iterator.
+func Literator(tokens ...Token) Iterator {
+	return func() Token {
+		if len(tokens) == 0 {
+			return EOF
+		}
+		token := tokens[0]
+		tokens = tokens[1:]
+		return token
+	}
+}
+
+// SplitTokensIntoLines splits tokens containing newlines in two.
+func SplitTokensIntoLines(tokens []Token) (out [][]Token) {
+	var line []Token // nolint: prealloc
+	for _, token := range tokens {
+		for strings.Contains(token.Value, "\n") {
+			parts := strings.SplitAfterN(token.Value, "\n", 2)
+			// Token becomes the tail.
+			token.Value = parts[1]
+
+			// Append the head to the line and flush the line.
+			clone := token.Clone()
+			clone.Value = parts[0]
+			line = append(line, clone)
+			out = append(out, line)
+			line = nil
+		}
+		line = append(line, token)
+	}
+	if len(line) > 0 {
+		out = append(out, line)
+	}
+	// Strip empty trailing token line.
+	if len(out) > 0 {
+		last := out[len(out)-1]
+		if len(last) == 1 && last[0].Value == "" {
+			out = out[:len(out)-1]
+		}
+	}
+	return
+}
diff --git a/lexer.go b/lexer.go
new file mode 100644
index 0000000..eb027bf
--- /dev/null
+++ b/lexer.go
@@ -0,0 +1,162 @@
+package chroma
+
+import (
+	"fmt"
+	"strings"
+)
+
+var (
+	defaultOptions = &TokeniseOptions{
+		State:    "root",
+		EnsureLF: true,
+	}
+)
+
+// Config for a lexer.
+type Config struct {
+	// Name of the lexer.
+	Name string `xml:"name,omitempty"`
+
+	// Shortcuts for the lexer
+	Aliases []string `xml:"alias,omitempty"`
+
+	// File name globs
+	Filenames []string `xml:"filename,omitempty"`
+
+	// Secondary file name globs
+	AliasFilenames []string `xml:"alias_filename,omitempty"`
+
+	// MIME types
+	MimeTypes []string `xml:"mime_type,omitempty"`
+
+	// Regex matching is case-insensitive.
+	CaseInsensitive bool `xml:"case_insensitive,omitempty"`
+
+	// Regex matches all characters.
+	DotAll bool `xml:"dot_all,omitempty"`
+
+	// Regex does not match across lines ($ matches EOL).
+	//
+	// Defaults to multiline.
+	NotMultiline bool `xml:"not_multiline,omitempty"`
+
+	// Don't strip leading and trailing newlines from the input.
+	// DontStripNL bool
+
+	// Strip all leading and trailing whitespace from the input
+	// StripAll bool
+
+	// Make sure that the input ends with a newline. This
+	// is required for some lexers that consume input linewise.
+	EnsureNL bool `xml:"ensure_nl,omitempty"`
+
+	// If given and greater than 0, expand tabs in the input.
+	// TabSize int
+
+	// Priority of lexer.
+	//
+	// If this is 0 it will be treated as a default of 1.
+	Priority float32 `xml:"priority,omitempty"`
+
+	// Analyse is a list of regexes to match against the input.
+	//
+	// If a match is found, the score is returned if single attribute is set to true,
+	// otherwise the sum of all the score of matching patterns will be
+	// used as the final score.
+	Analyse *AnalyseConfig `xml:"analyse,omitempty"`
+}
+
+// AnalyseConfig defines the list of regexes analysers.
+type AnalyseConfig struct {
+	Regexes []RegexConfig `xml:"regex,omitempty"`
+	// If true, the first matching score is returned.
+	First bool `xml:"first,attr"`
+}
+
+// RegexConfig defines a single regex pattern and its score in case of match.
+type RegexConfig struct {
+	Pattern string  `xml:"pattern,attr"`
+	Score   float32 `xml:"score,attr"`
+}
+
+// Token output to formatter.
+type Token struct {
+	Type  TokenType `json:"type"`
+	Value string    `json:"value"`
+}
+
+func (t *Token) String() string   { return t.Value }
+func (t *Token) GoString() string { return fmt.Sprintf("&Token{%s, %q}", t.Type, t.Value) }
+
+// Clone returns a clone of the Token.
+func (t *Token) Clone() Token {
+	return *t
+}
+
+// EOF is returned by lexers at the end of input.
+var EOF Token
+
+// TokeniseOptions contains options for tokenisers.
+type TokeniseOptions struct {
+	// State to start tokenisation in. Defaults to "root".
+	State string
+	// Nested tokenisation.
+	Nested bool
+
+	// If true, all EOLs are converted into LF
+	// by replacing CRLF and CR
+	EnsureLF bool
+}
+
+// A Lexer for tokenising source code.
+type Lexer interface {
+	// Config describing the features of the Lexer.
+	Config() *Config
+	// Tokenise returns an Iterator over tokens in text.
+	Tokenise(options *TokeniseOptions, text string) (Iterator, error)
+	// SetRegistry sets the registry this Lexer is associated with.
+	//
+	// The registry should be used by the Lexer if it needs to look up other
+	// lexers.
+	SetRegistry(registry *LexerRegistry) Lexer
+	// SetAnalyser sets a function the Lexer should use for scoring how
+	// likely a fragment of text is to match this lexer, between 0.0 and 1.0.
+	// A value of 1 indicates high confidence.
+	//
+	// Lexers may ignore this if they implement their own analysers.
+	SetAnalyser(analyser func(text string) float32) Lexer
+	// AnalyseText scores how likely a fragment of text is to match
+	// this lexer, between 0.0 and 1.0. A value of 1 indicates high confidence.
+	AnalyseText(text string) float32
+}
+
+// Lexers is a slice of lexers sortable by name.
+type Lexers []Lexer
+
+func (l Lexers) Len() int      { return len(l) }
+func (l Lexers) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
+func (l Lexers) Less(i, j int) bool {
+	return strings.ToLower(l[i].Config().Name) < strings.ToLower(l[j].Config().Name)
+}
+
+// PrioritisedLexers is a slice of lexers sortable by priority.
+type PrioritisedLexers []Lexer
+
+func (l PrioritisedLexers) Len() int      { return len(l) }
+func (l PrioritisedLexers) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
+func (l PrioritisedLexers) Less(i, j int) bool {
+	ip := l[i].Config().Priority
+	if ip == 0 {
+		ip = 1
+	}
+	jp := l[j].Config().Priority
+	if jp == 0 {
+		jp = 1
+	}
+	return ip > jp
+}
+
+// Analyser determines how appropriate this lexer is for the given text.
+type Analyser interface {
+	AnalyseText(text string) float32
+}
diff --git a/lexer_test.go b/lexer_test.go
new file mode 100644
index 0000000..0f0ab5f
--- /dev/null
+++ b/lexer_test.go
@@ -0,0 +1,48 @@
+package chroma
+
+import (
+	"testing"
+
+	"github.com/alecthomas/assert/v2"
+)
+
+func TestTokenTypeClassifiers(t *testing.T) {
+	assert.True(t, GenericDeleted.InCategory(Generic))
+	assert.True(t, LiteralStringBacktick.InSubCategory(String))
+	assert.Equal(t, LiteralStringBacktick.String(), "LiteralStringBacktick")
+}
+
+func TestSimpleLexer(t *testing.T) {
+	lexer := mustNewLexer(t, &Config{
+		Name:      "INI",
+		Aliases:   []string{"ini", "cfg"},
+		Filenames: []string{"*.ini", "*.cfg"},
+	}, map[string][]Rule{
+		"root": {
+			{`\s+`, Whitespace, nil},
+			{`;.*?$`, Comment, nil},
+			{`\[.*?\]$`, Keyword, nil},
+			{`(.*?)(\s*)(=)(\s*)(.*?)$`, ByGroups(Name, Whitespace, Operator, Whitespace, String), nil},
+		},
+	})
+	actual, err := Tokenise(lexer, nil, `
+	; this is a comment
+	[section]
+	a = 10
+`)
+	assert.NoError(t, err)
+	expected := []Token{
+		{Whitespace, "\n\t"},
+		{Comment, "; this is a comment"},
+		{Whitespace, "\n\t"},
+		{Keyword, "[section]"},
+		{Whitespace, "\n\t"},
+		{Name, "a"},
+		{Whitespace, " "},
+		{Operator, "="},
+		{Whitespace, " "},
+		{LiteralString, "10"},
+		{Whitespace, "\n"},
+	}
+	assert.Equal(t, expected, actual)
+}
diff --git a/mutator_test.go b/mutator_test.go
new file mode 100644
index 0000000..6561fc4
--- /dev/null
+++ b/mutator_test.go
@@ -0,0 +1,57 @@
+package chroma
+
+import (
+	"testing"
+
+	"github.com/alecthomas/assert/v2"
+)
+
+func TestInclude(t *testing.T) {
+	include := Include("other")
+	actual := CompiledRules{
+		"root": {{Rule: include}},
+		"other": {
+			{Rule: Rule{Pattern: "//.+", Type: Comment}},
+			{Rule: Rule{Pattern: `"[^"]*"`, Type: String}},
+		},
+	}
+	lexer := &RegexLexer{rules: actual}
+	err := include.Mutator.(LexerMutator).MutateLexer(lexer.rules, "root", 0)
+	assert.NoError(t, err)
+	expected := CompiledRules{
+		"root": {
+			{Rule: Rule{
+				Pattern: "//.+",
+				Type:    Comment,
+			}},
+			{Rule: Rule{
+				Pattern: `"[^"]*"`,
+				Type:    String,
+			}},
+		},
+		"other": {
+			{Rule: Rule{
+				Pattern: "//.+",
+				Type:    Comment,
+			}},
+			{Rule: Rule{
+				Pattern: `"[^"]*"`,
+				Type:    String,
+			}},
+		},
+	}
+	assert.Equal(t, expected, actual)
+}
+
+func TestCombine(t *testing.T) {
+	l := mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+		"root":  {{`hello`, String, Combined("world", "bye", "space")}},
+		"world": {{`world`, Name, nil}},
+		"bye":   {{`bye`, Name, nil}},
+		"space": {{`\s+`, Whitespace, nil}},
+	})
+	it, err := l.Tokenise(nil, "hello world")
+	assert.NoError(t, err)
+	expected := []Token{{String, `hello`}, {Whitespace, ` `}, {Name, `world`}}
+	assert.Equal(t, expected, it.Tokens())
+}
diff --git a/mutators.go b/mutators.go
new file mode 100644
index 0000000..e80ad97
--- /dev/null
+++ b/mutators.go
@@ -0,0 +1,201 @@
+package chroma
+
+import (
+	"encoding/xml"
+	"fmt"
+	"strings"
+)
+
+// A Mutator modifies the behaviour of the lexer.
+type Mutator interface {
+	// Mutate the lexer state machine as it is processing.
+	Mutate(state *LexerState) error
+}
+
+// SerialisableMutator is a Mutator that can be serialised and deserialised.
+type SerialisableMutator interface {
+	Mutator
+	MutatorKind() string
+}
+
+// A LexerMutator is an additional interface that a Mutator can implement
+// to modify the lexer when it is compiled.
+type LexerMutator interface {
+	// MutateLexer can be implemented to mutate the lexer itself.
+	//
+	// Rules are the lexer rules, state is the state key for the rule the mutator is associated with.
+	MutateLexer(rules CompiledRules, state string, rule int) error
+}
+
+// A MutatorFunc is a Mutator that mutates the lexer state machine as it is processing.
+type MutatorFunc func(state *LexerState) error
+
+func (m MutatorFunc) Mutate(state *LexerState) error { return m(state) } // nolint
+
+type multiMutator struct {
+	Mutators []Mutator `xml:"mutator"`
+}
+
+func (m *multiMutator) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+	for {
+		token, err := d.Token()
+		if err != nil {
+			return err
+		}
+		switch token := token.(type) {
+		case xml.StartElement:
+			mutator, err := unmarshalMutator(d, token)
+			if err != nil {
+				return err
+			}
+			m.Mutators = append(m.Mutators, mutator)
+
+		case xml.EndElement:
+			return nil
+		}
+	}
+}
+
+func (m *multiMutator) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+	name := xml.Name{Local: "mutators"}
+	if err := e.EncodeToken(xml.StartElement{Name: name}); err != nil {
+		return err
+	}
+	for _, m := range m.Mutators {
+		if err := marshalMutator(e, m); err != nil {
+			return err
+		}
+	}
+	return e.EncodeToken(xml.EndElement{Name: name})
+}
+
+func (m *multiMutator) MutatorKind() string { return "mutators" }
+
+func (m *multiMutator) Mutate(state *LexerState) error {
+	for _, modifier := range m.Mutators {
+		if err := modifier.Mutate(state); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// Mutators applies a set of Mutators in order.
+func Mutators(modifiers ...Mutator) Mutator {
+	return &multiMutator{modifiers}
+}
+
+type includeMutator struct {
+	State string `xml:"state,attr"`
+}
+
+// Include the given state.
+func Include(state string) Rule {
+	return Rule{Mutator: &includeMutator{state}}
+}
+
+func (i *includeMutator) MutatorKind() string { return "include" }
+
+func (i *includeMutator) Mutate(s *LexerState) error {
+	return fmt.Errorf("should never reach here Include(%q)", i.State)
+}
+
+func (i *includeMutator) MutateLexer(rules CompiledRules, state string, rule int) error {
+	includedRules, ok := rules[i.State]
+	if !ok {
+		return fmt.Errorf("invalid include state %q", i.State)
+	}
+	rules[state] = append(rules[state][:rule], append(includedRules, rules[state][rule+1:]...)...)
+	return nil
+}
+
+type combinedMutator struct {
+	States []string `xml:"state,attr"`
+}
+
+func (c *combinedMutator) MutatorKind() string { return "combined" }
+
+// Combined creates a new anonymous state from the given states, and pushes that state.
+func Combined(states ...string) Mutator {
+	return &combinedMutator{states}
+}
+
+func (c *combinedMutator) Mutate(s *LexerState) error {
+	return fmt.Errorf("should never reach here Combined(%v)", c.States)
+}
+
+func (c *combinedMutator) MutateLexer(rules CompiledRules, state string, rule int) error {
+	name := "__combined_" + strings.Join(c.States, "__")
+	if _, ok := rules[name]; !ok {
+		combined := []*CompiledRule{}
+		for _, state := range c.States {
+			rules, ok := rules[state]
+			if !ok {
+				return fmt.Errorf("invalid combine state %q", state)
+			}
+			combined = append(combined, rules...)
+		}
+		rules[name] = combined
+	}
+	rules[state][rule].Mutator = Push(name)
+	return nil
+}
+
+type pushMutator struct {
+	States []string `xml:"state,attr"`
+}
+
+func (p *pushMutator) MutatorKind() string { return "push" }
+
+func (p *pushMutator) Mutate(s *LexerState) error {
+	if len(p.States) == 0 {
+		s.Stack = append(s.Stack, s.State)
+	} else {
+		for _, state := range p.States {
+			if state == "#pop" {
+				s.Stack = s.Stack[:len(s.Stack)-1]
+			} else {
+				s.Stack = append(s.Stack, state)
+			}
+		}
+	}
+	return nil
+}
+
+// Push states onto the stack.
+func Push(states ...string) Mutator {
+	return &pushMutator{states}
+}
+
+type popMutator struct {
+	Depth int `xml:"depth,attr"`
+}
+
+func (p *popMutator) MutatorKind() string { return "pop" }
+
+func (p *popMutator) Mutate(state *LexerState) error {
+	if len(state.Stack) == 0 {
+		return fmt.Errorf("nothing to pop")
+	}
+	state.Stack = state.Stack[:len(state.Stack)-p.Depth]
+	return nil
+}
+
+// Pop state from the stack when rule matches.
+func Pop(n int) Mutator {
+	return &popMutator{n}
+}
+
+// Default returns a Rule that applies a set of Mutators.
+func Default(mutators ...Mutator) Rule {
+	return Rule{Mutator: Mutators(mutators...)}
+}
+
+// Stringify returns the raw string for a set of tokens.
+func Stringify(tokens ...Token) string {
+	out := []string{}
+	for _, t := range tokens {
+		out = append(out, t.Value)
+	}
+	return strings.Join(out, "")
+}
diff --git a/regexp.go b/regexp.go
new file mode 100644
index 0000000..0dcb077
--- /dev/null
+++ b/regexp.go
@@ -0,0 +1,483 @@
+package chroma
+
+import (
+	"fmt"
+	"os"
+	"path/filepath"
+	"regexp"
+	"sort"
+	"strings"
+	"sync"
+	"time"
+	"unicode/utf8"
+
+	"github.com/dlclark/regexp2"
+)
+
+// A Rule is the fundamental matching unit of the Regex lexer state machine.
+type Rule struct {
+	Pattern string
+	Type    Emitter
+	Mutator Mutator
+}
+
+// Words creates a regex that matches any of the given literal words.
+func Words(prefix, suffix string, words ...string) string {
+	sort.Slice(words, func(i, j int) bool {
+		return len(words[j]) < len(words[i])
+	})
+	for i, word := range words {
+		words[i] = regexp.QuoteMeta(word)
+	}
+	return prefix + `(` + strings.Join(words, `|`) + `)` + suffix
+}
+
+// Tokenise text using lexer, returning tokens as a slice.
+func Tokenise(lexer Lexer, options *TokeniseOptions, text string) ([]Token, error) {
+	var out []Token
+	it, err := lexer.Tokenise(options, text)
+	if err != nil {
+		return nil, err
+	}
+	for t := it(); t != EOF; t = it() {
+		out = append(out, t)
+	}
+	return out, nil
+}
+
+// Rules maps from state to a sequence of Rules.
+type Rules map[string][]Rule
+
+// Rename clones rules then a rule.
+func (r Rules) Rename(oldRule, newRule string) Rules {
+	r = r.Clone()
+	r[newRule] = r[oldRule]
+	delete(r, oldRule)
+	return r
+}
+
+// Clone returns a clone of the Rules.
+func (r Rules) Clone() Rules {
+	out := map[string][]Rule{}
+	for key, rules := range r {
+		out[key] = make([]Rule, len(rules))
+		copy(out[key], rules)
+	}
+	return out
+}
+
+// Merge creates a clone of "r" then merges "rules" into the clone.
+func (r Rules) Merge(rules Rules) Rules {
+	out := r.Clone()
+	for k, v := range rules.Clone() {
+		out[k] = v
+	}
+	return out
+}
+
+// MustNewLexer creates a new Lexer with deferred rules generation or panics.
+func MustNewLexer(config *Config, rules func() Rules) *RegexLexer {
+	lexer, err := NewLexer(config, rules)
+	if err != nil {
+		panic(err)
+	}
+	return lexer
+}
+
+// NewLexer creates a new regex-based Lexer.
+//
+// "rules" is a state machine transition map. Each key is a state. Values are sets of rules
+// that match input, optionally modify lexer state, and output tokens.
+func NewLexer(config *Config, rulesFunc func() Rules) (*RegexLexer, error) {
+	if config == nil {
+		config = &Config{}
+	}
+	for _, glob := range append(config.Filenames, config.AliasFilenames...) {
+		_, err := filepath.Match(glob, "")
+		if err != nil {
+			return nil, fmt.Errorf("%s: %q is not a valid glob: %w", config.Name, glob, err)
+		}
+	}
+	r := &RegexLexer{
+		config:         config,
+		fetchRulesFunc: func() (Rules, error) { return rulesFunc(), nil },
+	}
+	// One-off code to generate XML lexers in the Chroma source tree.
+	// var nameCleanRe = regexp.MustCompile(`[^-+A-Za-z0-9_]`)
+	// name := strings.ToLower(nameCleanRe.ReplaceAllString(config.Name, "_"))
+	// data, err := Marshal(r)
+	// if err != nil {
+	// 	if errors.Is(err, ErrNotSerialisable) {
+	// 		fmt.Fprintf(os.Stderr, "warning: %q: %s\n", name, err)
+	// 		return r, nil
+	// 	}
+	// 	return nil, err
+	// }
+	// _, file, _, ok := runtime.Caller(2)
+	// if !ok {
+	// 	panic("??")
+	// }
+	// fmt.Println(file)
+	// if strings.Contains(file, "/lexers/") {
+	// 	dir := filepath.Join(filepath.Dir(file), "embedded")
+	// 	err = os.MkdirAll(dir, 0700)
+	// 	if err != nil {
+	// 		return nil, err
+	// 	}
+	// 	filename := filepath.Join(dir, name) + ".xml"
+	// 	fmt.Println(filename)
+	// 	err = ioutil.WriteFile(filename, data, 0600)
+	// 	if err != nil {
+	// 		return nil, err
+	// 	}
+	// }
+	return r, nil
+}
+
+// Trace enables debug tracing.
+func (r *RegexLexer) Trace(trace bool) *RegexLexer {
+	r.trace = trace
+	return r
+}
+
+// A CompiledRule is a Rule with a pre-compiled regex.
+//
+// Note that regular expressions are lazily compiled on first use of the lexer.
+type CompiledRule struct {
+	Rule
+	Regexp *regexp2.Regexp
+	flags  string
+}
+
+// CompiledRules is a map of rule name to sequence of compiled rules in that rule.
+type CompiledRules map[string][]*CompiledRule
+
+// LexerState contains the state for a single lex.
+type LexerState struct {
+	Lexer    *RegexLexer
+	Registry *LexerRegistry
+	Text     []rune
+	Pos      int
+	Rules    CompiledRules
+	Stack    []string
+	State    string
+	Rule     int
+	// Group matches.
+	Groups []string
+	// Named Group matches.
+	NamedGroups map[string]string
+	// Custum context for mutators.
+	MutatorContext map[interface{}]interface{}
+	iteratorStack  []Iterator
+	options        *TokeniseOptions
+	newlineAdded   bool
+}
+
+// Set mutator context.
+func (l *LexerState) Set(key interface{}, value interface{}) {
+	l.MutatorContext[key] = value
+}
+
+// Get mutator context.
+func (l *LexerState) Get(key interface{}) interface{} {
+	return l.MutatorContext[key]
+}
+
+// Iterator returns the next Token from the lexer.
+func (l *LexerState) Iterator() Token { // nolint: gocognit
+	end := len(l.Text)
+	if l.newlineAdded {
+		end--
+	}
+	for l.Pos < end && len(l.Stack) > 0 {
+		// Exhaust the iterator stack, if any.
+		for len(l.iteratorStack) > 0 {
+			n := len(l.iteratorStack) - 1
+			t := l.iteratorStack[n]()
+			if t == EOF {
+				l.iteratorStack = l.iteratorStack[:n]
+				continue
+			}
+			return t
+		}
+
+		l.State = l.Stack[len(l.Stack)-1]
+		if l.Lexer.trace {
+			fmt.Fprintf(os.Stderr, "%s: pos=%d, text=%q\n", l.State, l.Pos, string(l.Text[l.Pos:]))
+		}
+		selectedRule, ok := l.Rules[l.State]
+		if !ok {
+			panic("unknown state " + l.State)
+		}
+		ruleIndex, rule, groups, namedGroups := matchRules(l.Text, l.Pos, selectedRule)
+		// No match.
+		if groups == nil {
+			// From Pygments :\
+			//
+			// If the RegexLexer encounters a newline that is flagged as an error token, the stack is
+			// emptied and the lexer continues scanning in the 'root' state. This can help producing
+			// error-tolerant highlighting for erroneous input, e.g. when a single-line string is not
+			// closed.
+			if l.Text[l.Pos] == '\n' && l.State != l.options.State {
+				l.Stack = []string{l.options.State}
+				continue
+			}
+			l.Pos++
+			return Token{Error, string(l.Text[l.Pos-1 : l.Pos])}
+		}
+		l.Rule = ruleIndex
+		l.Groups = groups
+		l.NamedGroups = namedGroups
+		l.Pos += utf8.RuneCountInString(groups[0])
+		if rule.Mutator != nil {
+			if err := rule.Mutator.Mutate(l); err != nil {
+				panic(err)
+			}
+		}
+		if rule.Type != nil {
+			l.iteratorStack = append(l.iteratorStack, rule.Type.Emit(l.Groups, l))
+		}
+	}
+	// Exhaust the IteratorStack, if any.
+	// Duplicate code, but eh.
+	for len(l.iteratorStack) > 0 {
+		n := len(l.iteratorStack) - 1
+		t := l.iteratorStack[n]()
+		if t == EOF {
+			l.iteratorStack = l.iteratorStack[:n]
+			continue
+		}
+		return t
+	}
+
+	// If we get to here and we still have text, return it as an error.
+	if l.Pos != len(l.Text) && len(l.Stack) == 0 {
+		value := string(l.Text[l.Pos:])
+		l.Pos = len(l.Text)
+		return Token{Type: Error, Value: value}
+	}
+	return EOF
+}
+
+// RegexLexer is the default lexer implementation used in Chroma.
+type RegexLexer struct {
+	registry *LexerRegistry // The LexerRegistry this Lexer is associated with, if any.
+	config   *Config
+	analyser func(text string) float32
+	trace    bool
+
+	mu             sync.Mutex
+	compiled       bool
+	rawRules       Rules
+	rules          map[string][]*CompiledRule
+	fetchRulesFunc func() (Rules, error)
+	compileOnce    sync.Once
+}
+
+func (r *RegexLexer) String() string {
+	return r.config.Name
+}
+
+// Rules in the Lexer.
+func (r *RegexLexer) Rules() (Rules, error) {
+	if err := r.needRules(); err != nil {
+		return nil, err
+	}
+	return r.rawRules, nil
+}
+
+// SetRegistry the lexer will use to lookup other lexers if necessary.
+func (r *RegexLexer) SetRegistry(registry *LexerRegistry) Lexer {
+	r.registry = registry
+	return r
+}
+
+// SetAnalyser sets the analyser function used to perform content inspection.
+func (r *RegexLexer) SetAnalyser(analyser func(text string) float32) Lexer {
+	r.analyser = analyser
+	return r
+}
+
+// AnalyseText scores how likely a fragment of text is to match this lexer, between 0.0 and 1.0.
+func (r *RegexLexer) AnalyseText(text string) float32 {
+	if r.analyser != nil {
+		return r.analyser(text)
+	}
+	return 0
+}
+
+// SetConfig replaces the Config for this Lexer.
+func (r *RegexLexer) SetConfig(config *Config) *RegexLexer {
+	r.config = config
+	return r
+}
+
+// Config returns the Config for this Lexer.
+func (r *RegexLexer) Config() *Config {
+	return r.config
+}
+
+// Regex compilation is deferred until the lexer is used. This is to avoid significant init() time costs.
+func (r *RegexLexer) maybeCompile() (err error) {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+	if r.compiled {
+		return nil
+	}
+	for state, rules := range r.rules {
+		for i, rule := range rules {
+			if rule.Regexp == nil {
+				pattern := "(?:" + rule.Pattern + ")"
+				if rule.flags != "" {
+					pattern = "(?" + rule.flags + ")" + pattern
+				}
+				pattern = `\G` + pattern
+				rule.Regexp, err = regexp2.Compile(pattern, 0)
+				if err != nil {
+					return fmt.Errorf("failed to compile rule %s.%d: %s", state, i, err)
+				}
+				rule.Regexp.MatchTimeout = time.Millisecond * 250
+			}
+		}
+	}
+restart:
+	seen := map[LexerMutator]bool{}
+	for state := range r.rules {
+		for i := 0; i < len(r.rules[state]); i++ {
+			rule := r.rules[state][i]
+			if compile, ok := rule.Mutator.(LexerMutator); ok {
+				if seen[compile] {
+					return fmt.Errorf("saw mutator %T twice; this should not happen", compile)
+				}
+				seen[compile] = true
+				if err := compile.MutateLexer(r.rules, state, i); err != nil {
+					return err
+				}
+				// Process the rules again in case the mutator added/removed rules.
+				//
+				// This sounds bad, but shouldn't be significant in practice.
+				goto restart
+			}
+		}
+	}
+	r.compiled = true
+	return nil
+}
+
+func (r *RegexLexer) fetchRules() error {
+	rules, err := r.fetchRulesFunc()
+	if err != nil {
+		return fmt.Errorf("%s: failed to compile rules: %w", r.config.Name, err)
+	}
+	if _, ok := rules["root"]; !ok {
+		return fmt.Errorf("no \"root\" state")
+	}
+	compiledRules := map[string][]*CompiledRule{}
+	for state, rules := range rules {
+		compiledRules[state] = nil
+		for _, rule := range rules {
+			flags := ""
+			if !r.config.NotMultiline {
+				flags += "m"
+			}
+			if r.config.CaseInsensitive {
+				flags += "i"
+			}
+			if r.config.DotAll {
+				flags += "s"
+			}
+			compiledRules[state] = append(compiledRules[state], &CompiledRule{Rule: rule, flags: flags})
+		}
+	}
+
+	r.rawRules = rules
+	r.rules = compiledRules
+	return nil
+}
+
+func (r *RegexLexer) needRules() error {
+	var err error
+	if r.fetchRulesFunc != nil {
+		r.compileOnce.Do(func() {
+			err = r.fetchRules()
+		})
+	}
+	if err := r.maybeCompile(); err != nil {
+		return err
+	}
+	return err
+}
+
+// Tokenise text using lexer, returning an iterator.
+func (r *RegexLexer) Tokenise(options *TokeniseOptions, text string) (Iterator, error) {
+	err := r.needRules()
+	if err != nil {
+		return nil, err
+	}
+	if options == nil {
+		options = defaultOptions
+	}
+	if options.EnsureLF {
+		text = ensureLF(text)
+	}
+	newlineAdded := false
+	if !options.Nested && r.config.EnsureNL && !strings.HasSuffix(text, "\n") {
+		text += "\n"
+		newlineAdded = true
+	}
+	state := &LexerState{
+		Registry:       r.registry,
+		newlineAdded:   newlineAdded,
+		options:        options,
+		Lexer:          r,
+		Text:           []rune(text),
+		Stack:          []string{options.State},
+		Rules:          r.rules,
+		MutatorContext: map[interface{}]interface{}{},
+	}
+	return state.Iterator, nil
+}
+
+// MustRules is like Rules() but will panic on error.
+func (r *RegexLexer) MustRules() Rules {
+	rules, err := r.Rules()
+	if err != nil {
+		panic(err)
+	}
+	return rules
+}
+
+func matchRules(text []rune, pos int, rules []*CompiledRule) (int, *CompiledRule, []string, map[string]string) {
+	for i, rule := range rules {
+		match, err := rule.Regexp.FindRunesMatchStartingAt(text, pos)
+		if match != nil && err == nil && match.Index == pos {
+			groups := []string{}
+			namedGroups := make(map[string]string)
+			for _, g := range match.Groups() {
+				namedGroups[g.Name] = g.String()
+				groups = append(groups, g.String())
+			}
+			return i, rule, groups, namedGroups
+		}
+	}
+	return 0, &CompiledRule{}, nil, nil
+}
+
+// replace \r and \r\n with \n
+// same as strings.ReplaceAll but more efficient
+func ensureLF(text string) string {
+	buf := make([]byte, len(text))
+	var j int
+	for i := 0; i < len(text); i++ {
+		c := text[i]
+		if c == '\r' {
+			if i < len(text)-1 && text[i+1] == '\n' {
+				continue
+			}
+			c = '\n'
+		}
+		buf[j] = c
+		j++
+	}
+	return string(buf[:j])
+}
diff --git a/regexp_test.go b/regexp_test.go
new file mode 100644
index 0000000..6a22c20
--- /dev/null
+++ b/regexp_test.go
@@ -0,0 +1,194 @@
+package chroma
+
+import (
+	"testing"
+
+	"github.com/alecthomas/assert/v2"
+)
+
+func mustNewLexer(t *testing.T, config *Config, rules Rules) *RegexLexer { // nolint: forbidigo
+	lexer, err := NewLexer(config, func() Rules {
+		return rules
+	})
+	assert.NoError(t, err)
+	return lexer
+}
+
+func TestNewlineAtEndOfFile(t *testing.T) {
+	l := Coalesce(mustNewLexer(t, &Config{EnsureNL: true}, Rules{ // nolint: forbidigo
+		"root": {
+			{`(\w+)(\n)`, ByGroups(Keyword, Whitespace), nil},
+		},
+	}))
+	it, err := l.Tokenise(nil, `hello`)
+	assert.NoError(t, err)
+	assert.Equal(t, []Token{{Keyword, "hello"}, {Whitespace, "\n"}}, it.Tokens())
+
+	l = Coalesce(mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+		"root": {
+			{`(\w+)(\n)`, ByGroups(Keyword, Whitespace), nil},
+		},
+	}))
+	it, err = l.Tokenise(nil, `hello`)
+	assert.NoError(t, err)
+	assert.Equal(t, []Token{{Error, "hello"}}, it.Tokens())
+}
+
+func TestMatchingAtStart(t *testing.T) {
+	l := Coalesce(mustNewLexer(t, &Config{}, Rules{ // nolint: forbidigo
+		"root": {
+			{`\s+`, Whitespace, nil},
+			{`^-`, Punctuation, Push("directive")},
+			{`->`, Operator, nil},
+		},
+		"directive": {
+			{"module", NameEntity, Pop(1)},
+		},
+	}))
+	it, err := l.Tokenise(nil, `-module ->`)
+	assert.NoError(t, err)
+	assert.Equal(t,
+		[]Token{{Punctuation, "-"}, {NameEntity, "module"}, {Whitespace, " "}, {Operator, "->"}},
+		it.Tokens())
+}
+
+func TestEnsureLFOption(t *testing.T) {
+	l := Coalesce(mustNewLexer(t, &Config{}, Rules{ // nolint: forbidigo
+		"root": {
+			{`(\w+)(\r?\n|\r)`, ByGroups(Keyword, Whitespace), nil},
+		},
+	}))
+	it, err := l.Tokenise(&TokeniseOptions{
+		State:    "root",
+		EnsureLF: true,
+	}, "hello\r\nworld\r")
+	assert.NoError(t, err)
+	assert.Equal(t, []Token{
+		{Keyword, "hello"},
+		{Whitespace, "\n"},
+		{Keyword, "world"},
+		{Whitespace, "\n"},
+	}, it.Tokens())
+
+	l = Coalesce(mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+		"root": {
+			{`(\w+)(\r?\n|\r)`, ByGroups(Keyword, Whitespace), nil},
+		},
+	}))
+	it, err = l.Tokenise(&TokeniseOptions{
+		State:    "root",
+		EnsureLF: false,
+	}, "hello\r\nworld\r")
+	assert.NoError(t, err)
+	assert.Equal(t, []Token{
+		{Keyword, "hello"},
+		{Whitespace, "\r\n"},
+		{Keyword, "world"},
+		{Whitespace, "\r"},
+	}, it.Tokens())
+}
+
+func TestEnsureLFFunc(t *testing.T) {
+	tests := []struct{ in, out string }{
+		{in: "", out: ""},
+		{in: "abc", out: "abc"},
+		{in: "\r", out: "\n"},
+		{in: "a\r", out: "a\n"},
+		{in: "\rb", out: "\nb"},
+		{in: "a\rb", out: "a\nb"},
+		{in: "\r\n", out: "\n"},
+		{in: "a\r\n", out: "a\n"},
+		{in: "\r\nb", out: "\nb"},
+		{in: "a\r\nb", out: "a\nb"},
+		{in: "\r\r\r\n\r", out: "\n\n\n\n"},
+	}
+	for _, test := range tests {
+		out := ensureLF(test.in)
+		assert.Equal(t, out, test.out)
+	}
+}
+
+func TestByGroupNames(t *testing.T) {
+	l := Coalesce(mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+		"root": {
+			{
+				`(?<key>\w+)(?<operator>=)(?<value>\w+)`,
+				ByGroupNames(map[string]Emitter{
+					`key`:      String,
+					`operator`: Operator,
+					`value`:    String,
+				}),
+				nil,
+			},
+		},
+	}))
+	it, err := l.Tokenise(nil, `abc=123`)
+	assert.NoError(t, err)
+	assert.Equal(t, []Token{{String, `abc`}, {Operator, `=`}, {String, `123`}}, it.Tokens())
+
+	l = Coalesce(mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+		"root": {
+			{
+				`(?<key>\w+)(?<operator>=)(?<value>\w+)`,
+				ByGroupNames(map[string]Emitter{
+					`key`:   String,
+					`value`: String,
+				}),
+				nil,
+			},
+		},
+	}))
+	it, err = l.Tokenise(nil, `abc=123`)
+	assert.NoError(t, err)
+	assert.Equal(t, []Token{{String, `abc`}, {Error, `=`}, {String, `123`}}, it.Tokens())
+
+	l = Coalesce(mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+		"root": {
+			{
+				`(?<key>\w+)=(?<value>\w+)`,
+				ByGroupNames(map[string]Emitter{
+					`key`:   String,
+					`value`: String,
+				}),
+				nil,
+			},
+		},
+	}))
+	it, err = l.Tokenise(nil, `abc=123`)
+	assert.NoError(t, err)
+	assert.Equal(t, []Token{{String, `abc123`}}, it.Tokens())
+
+	l = Coalesce(mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+		"root": {
+			{
+				`(?<key>\w+)(?<op>=)(?<value>\w+)`,
+				ByGroupNames(map[string]Emitter{
+					`key`:      String,
+					`operator`: Operator,
+					`value`:    String,
+				}),
+				nil,
+			},
+		},
+	}))
+	it, err = l.Tokenise(nil, `abc=123`)
+	assert.NoError(t, err)
+	assert.Equal(t, []Token{{String, `abc`}, {Error, `=`}, {String, `123`}}, it.Tokens())
+
+	l = Coalesce(mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+		"root": {
+			{
+				`\w+=\w+`,
+				ByGroupNames(map[string]Emitter{
+					`key`:      String,
+					`operator`: Operator,
+					`value`:    String,
+				}),
+				nil,
+			},
+		},
+	}))
+	it, err = l.Tokenise(nil, `abc=123`)
+	assert.NoError(t, err)
+	assert.Equal(t, []Token{{Error, `abc=123`}}, it.Tokens())
+}
diff --git a/registry.go b/registry.go
new file mode 100644
index 0000000..4742e8c
--- /dev/null
+++ b/registry.go
@@ -0,0 +1,210 @@
+package chroma
+
+import (
+	"path/filepath"
+	"sort"
+	"strings"
+)
+
+var (
+	ignoredSuffixes = [...]string{
+		// Editor backups
+		"~", ".bak", ".old", ".orig",
+		// Debian and derivatives apt/dpkg/ucf backups
+		".dpkg-dist", ".dpkg-old", ".ucf-dist", ".ucf-new", ".ucf-old",
+		// Red Hat and derivatives rpm backups
+		".rpmnew", ".rpmorig", ".rpmsave",
+		// Build system input/template files
+		".in",
+	}
+)
+
+// LexerRegistry is a registry of Lexers.
+type LexerRegistry struct {
+	Lexers  Lexers
+	byName  map[string]Lexer
+	byAlias map[string]Lexer
+}
+
+// NewLexerRegistry creates a new LexerRegistry of Lexers.
+func NewLexerRegistry() *LexerRegistry {
+	return &LexerRegistry{
+		byName:  map[string]Lexer{},
+		byAlias: map[string]Lexer{},
+	}
+}
+
+// Names of all lexers, optionally including aliases.
+func (l *LexerRegistry) Names(withAliases bool) []string {
+	out := []string{}
+	for _, lexer := range l.Lexers {
+		config := lexer.Config()
+		out = append(out, config.Name)
+		if withAliases {
+			out = append(out, config.Aliases...)
+		}
+	}
+	sort.Strings(out)
+	return out
+}
+
+// Get a Lexer by name, alias or file extension.
+func (l *LexerRegistry) Get(name string) Lexer {
+	if lexer := l.byName[name]; lexer != nil {
+		return lexer
+	}
+	if lexer := l.byAlias[name]; lexer != nil {
+		return lexer
+	}
+	if lexer := l.byName[strings.ToLower(name)]; lexer != nil {
+		return lexer
+	}
+	if lexer := l.byAlias[strings.ToLower(name)]; lexer != nil {
+		return lexer
+	}
+
+	candidates := PrioritisedLexers{}
+	// Try file extension.
+	if lexer := l.Match("filename." + name); lexer != nil {
+		candidates = append(candidates, lexer)
+	}
+	// Try exact filename.
+	if lexer := l.Match(name); lexer != nil {
+		candidates = append(candidates, lexer)
+	}
+	if len(candidates) == 0 {
+		return nil
+	}
+	sort.Sort(candidates)
+	return candidates[0]
+}
+
+// MatchMimeType attempts to find a lexer for the given MIME type.
+func (l *LexerRegistry) MatchMimeType(mimeType string) Lexer {
+	matched := PrioritisedLexers{}
+	for _, l := range l.Lexers {
+		for _, lmt := range l.Config().MimeTypes {
+			if mimeType == lmt {
+				matched = append(matched, l)
+			}
+		}
+	}
+	if len(matched) != 0 {
+		sort.Sort(matched)
+		return matched[0]
+	}
+	return nil
+}
+
+// Match returns the first lexer matching filename.
+//
+// Note that this iterates over all file patterns in all lexers, so is not fast.
+func (l *LexerRegistry) Match(filename string) Lexer {
+	filename = filepath.Base(filename)
+	matched := PrioritisedLexers{}
+	// First, try primary filename matches.
+	for _, lexer := range l.Lexers {
+		config := lexer.Config()
+		for _, glob := range config.Filenames {
+			ok, err := filepath.Match(glob, filename)
+			if err != nil { // nolint
+				panic(err)
+			} else if ok {
+				matched = append(matched, lexer)
+			} else {
+				for _, suf := range &ignoredSuffixes {
+					ok, err := filepath.Match(glob+suf, filename)
+					if err != nil {
+						panic(err)
+					} else if ok {
+						matched = append(matched, lexer)
+						break
+					}
+				}
+			}
+		}
+	}
+	if len(matched) > 0 {
+		sort.Sort(matched)
+		return matched[0]
+	}
+	matched = nil
+	// Next, try filename aliases.
+	for _, lexer := range l.Lexers {
+		config := lexer.Config()
+		for _, glob := range config.AliasFilenames {
+			ok, err := filepath.Match(glob, filename)
+			if err != nil { // nolint
+				panic(err)
+			} else if ok {
+				matched = append(matched, lexer)
+			} else {
+				for _, suf := range &ignoredSuffixes {
+					ok, err := filepath.Match(glob+suf, filename)
+					if err != nil {
+						panic(err)
+					} else if ok {
+						matched = append(matched, lexer)
+						break
+					}
+				}
+			}
+		}
+	}
+	if len(matched) > 0 {
+		sort.Sort(matched)
+		return matched[0]
+	}
+	return nil
+}
+
+// Analyse text content and return the "best" lexer..
+func (l *LexerRegistry) Analyse(text string) Lexer {
+	var picked Lexer
+	highest := float32(0.0)
+	for _, lexer := range l.Lexers {
+		if analyser, ok := lexer.(Analyser); ok {
+			weight := analyser.AnalyseText(text)
+			if weight > highest {
+				picked = lexer
+				highest = weight
+			}
+		}
+	}
+	return picked
+}
+
+// Register a Lexer with the LexerRegistry. If the lexer is already registered
+// it will be replaced.
+func (l *LexerRegistry) Register(lexer Lexer) Lexer {
+	lexer.SetRegistry(l)
+	config := lexer.Config()
+
+	l.byName[config.Name] = lexer
+	l.byName[strings.ToLower(config.Name)] = lexer
+
+	for _, alias := range config.Aliases {
+		l.byAlias[alias] = lexer
+		l.byAlias[strings.ToLower(alias)] = lexer
+	}
+
+	l.Lexers = add(l.Lexers, lexer)
+
+	return lexer
+}
+
+// add adds a lexer to a slice of lexers if it doesn't already exist, or if found will replace it.
+func add(lexers Lexers, lexer Lexer) Lexers {
+	for i, val := range lexers {
+		if val == nil {
+			continue
+		}
+
+		if val.Config().Name == lexer.Config().Name {
+			lexers[i] = lexer
+			return lexers
+		}
+	}
+
+	return append(lexers, lexer)
+}
diff --git a/remap.go b/remap.go
new file mode 100644
index 0000000..bcf5e66
--- /dev/null
+++ b/remap.go
@@ -0,0 +1,94 @@
+package chroma
+
+type remappingLexer struct {
+	lexer  Lexer
+	mapper func(Token) []Token
+}
+
+// RemappingLexer remaps a token to a set of, potentially empty, tokens.
+func RemappingLexer(lexer Lexer, mapper func(Token) []Token) Lexer {
+	return &remappingLexer{lexer, mapper}
+}
+
+func (r *remappingLexer) AnalyseText(text string) float32 {
+	return r.lexer.AnalyseText(text)
+}
+
+func (r *remappingLexer) SetAnalyser(analyser func(text string) float32) Lexer {
+	r.lexer.SetAnalyser(analyser)
+	return r
+}
+
+func (r *remappingLexer) SetRegistry(registry *LexerRegistry) Lexer {
+	r.lexer.SetRegistry(registry)
+	return r
+}
+
+func (r *remappingLexer) Config() *Config {
+	return r.lexer.Config()
+}
+
+func (r *remappingLexer) Tokenise(options *TokeniseOptions, text string) (Iterator, error) {
+	it, err := r.lexer.Tokenise(options, text)
+	if err != nil {
+		return nil, err
+	}
+	var buffer []Token
+	return func() Token {
+		for {
+			if len(buffer) > 0 {
+				t := buffer[0]
+				buffer = buffer[1:]
+				return t
+			}
+			t := it()
+			if t == EOF {
+				return t
+			}
+			buffer = r.mapper(t)
+		}
+	}, nil
+}
+
+// TypeMapping defines type maps for the TypeRemappingLexer.
+type TypeMapping []struct {
+	From, To TokenType
+	Words    []string
+}
+
+// TypeRemappingLexer remaps types of tokens coming from a parent Lexer.
+//
+// eg. Map "defvaralias" tokens of type NameVariable to NameFunction:
+//
+//	mapping := TypeMapping{
+//		{NameVariable, NameFunction, []string{"defvaralias"},
+//	}
+//	lexer = TypeRemappingLexer(lexer, mapping)
+func TypeRemappingLexer(lexer Lexer, mapping TypeMapping) Lexer {
+	// Lookup table for fast remapping.
+	lut := map[TokenType]map[string]TokenType{}
+	for _, rt := range mapping {
+		km, ok := lut[rt.From]
+		if !ok {
+			km = map[string]TokenType{}
+			lut[rt.From] = km
+		}
+		if len(rt.Words) == 0 {
+			km[""] = rt.To
+		} else {
+			for _, k := range rt.Words {
+				km[k] = rt.To
+			}
+		}
+	}
+	return RemappingLexer(lexer, func(t Token) []Token {
+		if k, ok := lut[t.Type]; ok {
+			if tt, ok := k[t.Value]; ok {
+				t.Type = tt
+			} else if tt, ok := k[""]; ok {
+				t.Type = tt
+			}
+		}
+		return []Token{t}
+	})
+}
diff --git a/remap_test.go b/remap_test.go
new file mode 100644
index 0000000..80d74ef
--- /dev/null
+++ b/remap_test.go
@@ -0,0 +1,29 @@
+package chroma
+
+import (
+	"testing"
+
+	"github.com/alecthomas/assert/v2"
+)
+
+func TestRemappingLexer(t *testing.T) {
+	var lexer Lexer = mustNewLexer(t, nil, Rules{ // nolint: forbidigo
+		"root": {
+			{`\s+`, Whitespace, nil},
+			{`\w+`, Name, nil},
+		},
+	})
+	lexer = TypeRemappingLexer(lexer, TypeMapping{
+		{Name, Keyword, []string{"if", "else"}},
+	})
+
+	it, err := lexer.Tokenise(nil, `if true then print else end`)
+	assert.NoError(t, err)
+	expected := []Token{
+		{Keyword, "if"}, {TextWhitespace, " "}, {Name, "true"}, {TextWhitespace, " "}, {Name, "then"},
+		{TextWhitespace, " "}, {Name, "print"}, {TextWhitespace, " "}, {Keyword, "else"},
+		{TextWhitespace, " "}, {Name, "end"},
+	}
+	actual := it.Tokens()
+	assert.Equal(t, expected, actual)
+}
diff --git a/serialise.go b/serialise.go
new file mode 100644
index 0000000..645a5fa
--- /dev/null
+++ b/serialise.go
@@ -0,0 +1,479 @@
+package chroma
+
+import (
+	"compress/gzip"
+	"encoding/xml"
+	"errors"
+	"fmt"
+	"io"
+	"io/fs"
+	"math"
+	"path/filepath"
+	"reflect"
+	"regexp"
+	"strings"
+
+	"github.com/dlclark/regexp2"
+)
+
+// Serialisation of Chroma rules to XML. The format is:
+//
+//	<rules>
+//	  <state name="$STATE">
+//	    <rule [pattern="$PATTERN"]>
+//	      [<$EMITTER ...>]
+//	      [<$MUTATOR ...>]
+//	    </rule>
+//	  </state>
+//	</rules>
+//
+// eg. Include("String") would become:
+//
+//	<rule>
+//	  <include state="String" />
+//	</rule>
+//
+//	[null, null, {"kind": "include", "state": "String"}]
+//
+// eg. Rule{`\d+`, Text, nil} would become:
+//
+//	<rule pattern="\\d+">
+//	  <token type="Text"/>
+//	</rule>
+//
+// eg. Rule{`"`, String, Push("String")}
+//
+//	<rule pattern="\"">
+//	  <token type="String" />
+//	  <push state="String" />
+//	</rule>
+//
+// eg. Rule{`(\w+)(\n)`, ByGroups(Keyword, Whitespace), nil},
+//
+//	<rule pattern="(\\w+)(\\n)">
+//	  <bygroups token="Keyword" token="Whitespace" />
+//	  <push state="String" />
+//	</rule>
+var (
+	// ErrNotSerialisable is returned if a lexer contains Rules that cannot be serialised.
+	ErrNotSerialisable = fmt.Errorf("not serialisable")
+	emitterTemplates   = func() map[string]SerialisableEmitter {
+		out := map[string]SerialisableEmitter{}
+		for _, emitter := range []SerialisableEmitter{
+			&byGroupsEmitter{},
+			&usingSelfEmitter{},
+			TokenType(0),
+			&usingEmitter{},
+			&usingByGroup{},
+		} {
+			out[emitter.EmitterKind()] = emitter
+		}
+		return out
+	}()
+	mutatorTemplates = func() map[string]SerialisableMutator {
+		out := map[string]SerialisableMutator{}
+		for _, mutator := range []SerialisableMutator{
+			&includeMutator{},
+			&combinedMutator{},
+			&multiMutator{},
+			&pushMutator{},
+			&popMutator{},
+		} {
+			out[mutator.MutatorKind()] = mutator
+		}
+		return out
+	}()
+)
+
+// fastUnmarshalConfig unmarshals only the Config from a serialised lexer.
+func fastUnmarshalConfig(from fs.FS, path string) (*Config, error) {
+	r, err := from.Open(path)
+	if err != nil {
+		return nil, err
+	}
+	defer r.Close()
+	dec := xml.NewDecoder(r)
+	for {
+		token, err := dec.Token()
+		if err != nil {
+			if errors.Is(err, io.EOF) {
+				return nil, fmt.Errorf("could not find <config> element")
+			}
+			return nil, err
+		}
+		switch se := token.(type) {
+		case xml.StartElement:
+			if se.Name.Local != "config" {
+				break
+			}
+
+			var config Config
+			err = dec.DecodeElement(&config, &se)
+			if err != nil {
+				return nil, fmt.Errorf("%s: %w", path, err)
+			}
+			return &config, nil
+		}
+	}
+}
+
+// MustNewXMLLexer constructs a new RegexLexer from an XML file or panics.
+func MustNewXMLLexer(from fs.FS, path string) *RegexLexer {
+	lex, err := NewXMLLexer(from, path)
+	if err != nil {
+		panic(err)
+	}
+	return lex
+}
+
+// NewXMLLexer creates a new RegexLexer from a serialised RegexLexer.
+func NewXMLLexer(from fs.FS, path string) (*RegexLexer, error) {
+	config, err := fastUnmarshalConfig(from, path)
+	if err != nil {
+		return nil, err
+	}
+
+	for _, glob := range append(config.Filenames, config.AliasFilenames...) {
+		_, err := filepath.Match(glob, "")
+		if err != nil {
+			return nil, fmt.Errorf("%s: %q is not a valid glob: %w", config.Name, glob, err)
+		}
+	}
+
+	var analyserFn func(string) float32
+
+	if config.Analyse != nil {
+		type regexAnalyse struct {
+			re    *regexp2.Regexp
+			score float32
+		}
+
+		regexAnalysers := make([]regexAnalyse, 0, len(config.Analyse.Regexes))
+
+		for _, ra := range config.Analyse.Regexes {
+			re, err := regexp2.Compile(ra.Pattern, regexp2.None)
+			if err != nil {
+				return nil, fmt.Errorf("%s: %q is not a valid analyser regex: %w", config.Name, ra.Pattern, err)
+			}
+
+			regexAnalysers = append(regexAnalysers, regexAnalyse{re, ra.Score})
+		}
+
+		analyserFn = func(text string) float32 {
+			var score float32
+
+			for _, ra := range regexAnalysers {
+				ok, err := ra.re.MatchString(text)
+				if err != nil {
+					return 0
+				}
+
+				if ok && config.Analyse.First {
+					return float32(math.Min(float64(ra.score), 1.0))
+				}
+
+				if ok {
+					score += ra.score
+				}
+			}
+
+			return float32(math.Min(float64(score), 1.0))
+		}
+	}
+
+	return &RegexLexer{
+		config:   config,
+		analyser: analyserFn,
+		fetchRulesFunc: func() (Rules, error) {
+			var lexer struct {
+				Config
+				Rules Rules `xml:"rules"`
+			}
+			// Try to open .xml fallback to .xml.gz
+			fr, err := from.Open(path)
+			if err != nil {
+				if errors.Is(err, fs.ErrNotExist) {
+					path += ".gz"
+					fr, err = from.Open(path)
+					if err != nil {
+						return nil, err
+					}
+				} else {
+					return nil, err
+				}
+			}
+			defer fr.Close()
+			var r io.Reader = fr
+			if strings.HasSuffix(path, ".gz") {
+				r, err = gzip.NewReader(r)
+				if err != nil {
+					return nil, fmt.Errorf("%s: %w", path, err)
+				}
+			}
+			err = xml.NewDecoder(r).Decode(&lexer)
+			if err != nil {
+				return nil, fmt.Errorf("%s: %w", path, err)
+			}
+			return lexer.Rules, nil
+		},
+	}, nil
+}
+
+// Marshal a RegexLexer to XML.
+func Marshal(l *RegexLexer) ([]byte, error) {
+	type lexer struct {
+		Config Config `xml:"config"`
+		Rules  Rules  `xml:"rules"`
+	}
+
+	rules, err := l.Rules()
+	if err != nil {
+		return nil, err
+	}
+	root := &lexer{
+		Config: *l.Config(),
+		Rules:  rules,
+	}
+	data, err := xml.MarshalIndent(root, "", "  ")
+	if err != nil {
+		return nil, err
+	}
+	re := regexp.MustCompile(`></[a-zA-Z]+>`)
+	data = re.ReplaceAll(data, []byte(`/>`))
+	return data, nil
+}
+
+// Unmarshal a RegexLexer from XML.
+func Unmarshal(data []byte) (*RegexLexer, error) {
+	type lexer struct {
+		Config Config `xml:"config"`
+		Rules  Rules  `xml:"rules"`
+	}
+	root := &lexer{}
+	err := xml.Unmarshal(data, root)
+	if err != nil {
+		return nil, fmt.Errorf("invalid Lexer XML: %w", err)
+	}
+	lex, err := NewLexer(&root.Config, func() Rules { return root.Rules })
+	if err != nil {
+		return nil, err
+	}
+	return lex, nil
+}
+
+func marshalMutator(e *xml.Encoder, mutator Mutator) error {
+	if mutator == nil {
+		return nil
+	}
+	smutator, ok := mutator.(SerialisableMutator)
+	if !ok {
+		return fmt.Errorf("unsupported mutator: %w", ErrNotSerialisable)
+	}
+	return e.EncodeElement(mutator, xml.StartElement{Name: xml.Name{Local: smutator.MutatorKind()}})
+}
+
+func unmarshalMutator(d *xml.Decoder, start xml.StartElement) (Mutator, error) {
+	kind := start.Name.Local
+	mutator, ok := mutatorTemplates[kind]
+	if !ok {
+		return nil, fmt.Errorf("unknown mutator %q: %w", kind, ErrNotSerialisable)
+	}
+	value, target := newFromTemplate(mutator)
+	if err := d.DecodeElement(target, &start); err != nil {
+		return nil, err
+	}
+	return value().(SerialisableMutator), nil
+}
+
+func marshalEmitter(e *xml.Encoder, emitter Emitter) error {
+	if emitter == nil {
+		return nil
+	}
+	semitter, ok := emitter.(SerialisableEmitter)
+	if !ok {
+		return fmt.Errorf("unsupported emitter %T: %w", emitter, ErrNotSerialisable)
+	}
+	return e.EncodeElement(emitter, xml.StartElement{
+		Name: xml.Name{Local: semitter.EmitterKind()},
+	})
+}
+
+func unmarshalEmitter(d *xml.Decoder, start xml.StartElement) (Emitter, error) {
+	kind := start.Name.Local
+	mutator, ok := emitterTemplates[kind]
+	if !ok {
+		return nil, fmt.Errorf("unknown emitter %q: %w", kind, ErrNotSerialisable)
+	}
+	value, target := newFromTemplate(mutator)
+	if err := d.DecodeElement(target, &start); err != nil {
+		return nil, err
+	}
+	return value().(SerialisableEmitter), nil
+}
+
+func (r Rule) MarshalXML(e *xml.Encoder, _ xml.StartElement) error {
+	start := xml.StartElement{
+		Name: xml.Name{Local: "rule"},
+	}
+	if r.Pattern != "" {
+		start.Attr = append(start.Attr, xml.Attr{
+			Name:  xml.Name{Local: "pattern"},
+			Value: r.Pattern,
+		})
+	}
+	if err := e.EncodeToken(start); err != nil {
+		return err
+	}
+	if err := marshalEmitter(e, r.Type); err != nil {
+		return err
+	}
+	if err := marshalMutator(e, r.Mutator); err != nil {
+		return err
+	}
+	return e.EncodeToken(xml.EndElement{Name: start.Name})
+}
+
+func (r *Rule) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+	for _, attr := range start.Attr {
+		if attr.Name.Local == "pattern" {
+			r.Pattern = attr.Value
+			break
+		}
+	}
+	for {
+		token, err := d.Token()
+		if err != nil {
+			return err
+		}
+		switch token := token.(type) {
+		case xml.StartElement:
+			mutator, err := unmarshalMutator(d, token)
+			if err != nil && !errors.Is(err, ErrNotSerialisable) {
+				return err
+			} else if err == nil {
+				if r.Mutator != nil {
+					return fmt.Errorf("duplicate mutator")
+				}
+				r.Mutator = mutator
+				continue
+			}
+			emitter, err := unmarshalEmitter(d, token)
+			if err != nil && !errors.Is(err, ErrNotSerialisable) { // nolint: gocritic
+				return err
+			} else if err == nil {
+				if r.Type != nil {
+					return fmt.Errorf("duplicate emitter")
+				}
+				r.Type = emitter
+				continue
+			} else {
+				return err
+			}
+
+		case xml.EndElement:
+			return nil
+		}
+	}
+}
+
+type xmlRuleState struct {
+	Name  string `xml:"name,attr"`
+	Rules []Rule `xml:"rule"`
+}
+
+type xmlRules struct {
+	States []xmlRuleState `xml:"state"`
+}
+
+func (r Rules) MarshalXML(e *xml.Encoder, _ xml.StartElement) error {
+	xr := xmlRules{}
+	for state, rules := range r {
+		xr.States = append(xr.States, xmlRuleState{
+			Name:  state,
+			Rules: rules,
+		})
+	}
+	return e.EncodeElement(xr, xml.StartElement{Name: xml.Name{Local: "rules"}})
+}
+
+func (r *Rules) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+	xr := xmlRules{}
+	if err := d.DecodeElement(&xr, &start); err != nil {
+		return err
+	}
+	if *r == nil {
+		*r = Rules{}
+	}
+	for _, state := range xr.States {
+		(*r)[state.Name] = state.Rules
+	}
+	return nil
+}
+
+type xmlTokenType struct {
+	Type string `xml:"type,attr"`
+}
+
+func (t *TokenType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+	el := xmlTokenType{}
+	if err := d.DecodeElement(&el, &start); err != nil {
+		return err
+	}
+	tt, err := TokenTypeString(el.Type)
+	if err != nil {
+		return err
+	}
+	*t = tt
+	return nil
+}
+
+func (t TokenType) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+	start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{Local: "type"}, Value: t.String()})
+	if err := e.EncodeToken(start); err != nil {
+		return err
+	}
+	return e.EncodeToken(xml.EndElement{Name: start.Name})
+}
+
+// This hijinks is a bit unfortunate but without it we can't deserialise into TokenType.
+func newFromTemplate(template interface{}) (value func() interface{}, target interface{}) {
+	t := reflect.TypeOf(template)
+	if t.Kind() == reflect.Ptr {
+		v := reflect.New(t.Elem())
+		return v.Interface, v.Interface()
+	}
+	v := reflect.New(t)
+	return func() interface{} { return v.Elem().Interface() }, v.Interface()
+}
+
+func (b *Emitters) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+	for {
+		token, err := d.Token()
+		if err != nil {
+			return err
+		}
+		switch token := token.(type) {
+		case xml.StartElement:
+			emitter, err := unmarshalEmitter(d, token)
+			if err != nil {
+				return err
+			}
+			*b = append(*b, emitter)
+
+		case xml.EndElement:
+			return nil
+		}
+	}
+}
+
+func (b Emitters) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+	if err := e.EncodeToken(start); err != nil {
+		return err
+	}
+	for _, m := range b {
+		if err := marshalEmitter(e, m); err != nil {
+			return err
+		}
+	}
+	return e.EncodeToken(xml.EndElement{Name: start.Name})
+}
diff --git a/serialise_test.go b/serialise_test.go
new file mode 100644
index 0000000..9177b54
--- /dev/null
+++ b/serialise_test.go
@@ -0,0 +1,166 @@
+package chroma
+
+import (
+	"bytes"
+	"compress/gzip"
+	"encoding/xml"
+	"fmt"
+	"regexp"
+	"testing"
+
+	"github.com/alecthomas/assert/v2"
+)
+
+func TestEmitterSerialisationRoundTrip(t *testing.T) {
+	tests := []struct {
+		name    string
+		emitter Emitter
+	}{
+		{"ByGroups", ByGroups(Name, Using("Go"))},
+		{"UsingSelf", UsingSelf("root")},
+		{"Using", Using("Go")},
+		{"UsingByGroup", UsingByGroup(1, 2, Name)},
+		{"TokenType", Name},
+	}
+	for _, test := range tests {
+		// nolint: scopelint
+		t.Run(test.name, func(t *testing.T) {
+			data, err := xml.Marshal(test.emitter)
+			assert.NoError(t, err)
+			t.Logf("%s", data)
+			value, target := newFromTemplate(test.emitter)
+			err = xml.Unmarshal(data, target)
+			assert.NoError(t, err)
+			assert.Equal(t, test.emitter, value().(Emitter))
+		})
+	}
+}
+
+func TestMutatorSerialisationRoundTrip(t *testing.T) {
+	tests := []struct {
+		name    string
+		mutator Mutator
+	}{
+		{"Include", Include("string").Mutator},
+		{"Combined", Combined("a", "b", "c")},
+		{"Multi", Mutators(Include("string").Mutator, Push("quote"))},
+		{"Push", Push("include")},
+		{"Pop", Pop(1)},
+	}
+	for _, test := range tests {
+		// nolint: scopelint
+		t.Run(test.name, func(t *testing.T) {
+			data, err := xml.Marshal(test.mutator)
+			assert.NoError(t, err)
+			t.Logf("%s", data)
+			value, target := newFromTemplate(test.mutator)
+			err = xml.Unmarshal(data, target)
+			assert.NoError(t, err)
+			assert.Equal(t, test.mutator, value().(Mutator))
+		})
+	}
+}
+
+func TestMarshal(t *testing.T) {
+	actual := MustNewLexer(&Config{
+		Name:      "PkgConfig",
+		Aliases:   []string{"pkgconfig"},
+		Filenames: []string{"*.pc"},
+	}, func() Rules {
+		return Rules{
+			"root": {
+				{`#.*$`, CommentSingle, nil},
+				{`^(\w+)(=)`, ByGroups(NameAttribute, Operator), nil},
+				{`^([\w.]+)(:)`, ByGroups(NameTag, Punctuation), Push("spvalue")},
+				Include("interp"),
+				{`[^${}#=:\n.]+`, Text, nil},
+				{`.`, Text, nil},
+			},
+			"interp": {
+				{`\$\$`, Text, nil},
+				{`\$\{`, LiteralStringInterpol, Push("curly")},
+			},
+			"curly": {
+				{`\}`, LiteralStringInterpol, Pop(1)},
+				{`\w+`, NameAttribute, nil},
+			},
+			"spvalue": {
+				Include("interp"),
+				{`#.*$`, CommentSingle, Pop(1)},
+				{`\n`, Text, Pop(1)},
+				{`[^${}#\n]+`, Text, nil},
+				{`.`, Text, nil},
+			},
+		}
+	})
+	data, err := Marshal(actual)
+	assert.NoError(t, err)
+	expected, err := Unmarshal(data)
+	assert.NoError(t, err)
+	assert.Equal(t, expected.Config(), actual.Config())
+	assert.Equal(t, mustRules(t, expected), mustRules(t, actual))
+}
+
+func mustRules(t testing.TB, r *RegexLexer) Rules {
+	t.Helper()
+	rules, err := r.Rules()
+	assert.NoError(t, err)
+	return rules
+}
+
+func TestRuleSerialisation(t *testing.T) {
+	tests := []Rule{
+		Include("String"),
+		{`\d+`, Text, nil},
+		{`"`, String, Push("String")},
+	}
+	for _, test := range tests {
+		data, err := xml.Marshal(test)
+		assert.NoError(t, err)
+		t.Log(string(data))
+		actual := Rule{}
+		err = xml.Unmarshal(data, &actual)
+		assert.NoError(t, err)
+		assert.Equal(t, test, actual)
+	}
+}
+
+func TestRulesSerialisation(t *testing.T) {
+	expected := Rules{
+		"root": {
+			{`#.*$`, CommentSingle, nil},
+			{`^(\w+)(=)`, ByGroups(NameAttribute, Operator), nil},
+			{`^([\w.]+)(:)`, ByGroups(NameTag, Punctuation), Push("spvalue")},
+			Include("interp"),
+			{`[^${}#=:\n.]+`, Text, nil},
+			{`.`, Text, nil},
+		},
+		"interp": {
+			{`\$\$`, Text, nil},
+			{`\$\{`, LiteralStringInterpol, Push("curly")},
+		},
+		"curly": {
+			{`\}`, LiteralStringInterpol, Pop(1)},
+			{`\w+`, NameAttribute, nil},
+		},
+		"spvalue": {
+			Include("interp"),
+			{`#.*$`, CommentSingle, Pop(1)},
+			{`\n`, Text, Pop(1)},
+			{`[^${}#\n]+`, Text, nil},
+			{`.`, Text, nil},
+		},
+	}
+	data, err := xml.MarshalIndent(expected, "  ", "  ")
+	assert.NoError(t, err)
+	re := regexp.MustCompile(`></[a-zA-Z]+>`)
+	data = re.ReplaceAll(data, []byte(`/>`))
+	b := &bytes.Buffer{}
+	w := gzip.NewWriter(b)
+	fmt.Fprintln(w, string(data))
+	w.Close()
+	actual := Rules{}
+	err = xml.Unmarshal(data, &actual)
+	assert.NoError(t, err)
+	assert.Equal(t, expected, actual)
+}
diff --git a/style.go b/style.go
new file mode 100644
index 0000000..8cadaec
--- /dev/null
+++ b/style.go
@@ -0,0 +1,493 @@
+package chroma
+
+import (
+	"encoding/xml"
+	"fmt"
+	"io"
+	"sort"
+	"strings"
+)
+
+// Trilean value for StyleEntry value inheritance.
+type Trilean uint8
+
+// Trilean states.
+const (
+	Pass Trilean = iota
+	Yes
+	No
+)
+
+func (t Trilean) String() string {
+	switch t {
+	case Yes:
+		return "Yes"
+	case No:
+		return "No"
+	default:
+		return "Pass"
+	}
+}
+
+// Prefix returns s with "no" as a prefix if Trilean is no.
+func (t Trilean) Prefix(s string) string {
+	if t == Yes {
+		return s
+	} else if t == No {
+		return "no" + s
+	}
+	return ""
+}
+
+// A StyleEntry in the Style map.
+type StyleEntry struct {
+	// Hex colours.
+	Colour     Colour
+	Background Colour
+	Border     Colour
+
+	Bold      Trilean
+	Italic    Trilean
+	Underline Trilean
+	NoInherit bool
+}
+
+func (s StyleEntry) MarshalText() ([]byte, error) {
+	return []byte(s.String()), nil
+}
+
+func (s StyleEntry) String() string {
+	out := []string{}
+	if s.Bold != Pass {
+		out = append(out, s.Bold.Prefix("bold"))
+	}
+	if s.Italic != Pass {
+		out = append(out, s.Italic.Prefix("italic"))
+	}
+	if s.Underline != Pass {
+		out = append(out, s.Underline.Prefix("underline"))
+	}
+	if s.NoInherit {
+		out = append(out, "noinherit")
+	}
+	if s.Colour.IsSet() {
+		out = append(out, s.Colour.String())
+	}
+	if s.Background.IsSet() {
+		out = append(out, "bg:"+s.Background.String())
+	}
+	if s.Border.IsSet() {
+		out = append(out, "border:"+s.Border.String())
+	}
+	return strings.Join(out, " ")
+}
+
+// Sub subtracts e from s where elements match.
+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
+}
+
+// Inherit styles from ancestors.
+//
+// Ancestors should be provided from oldest to newest.
+func (s StyleEntry) Inherit(ancestors ...StyleEntry) StyleEntry {
+	out := s
+	for i := len(ancestors) - 1; i >= 0; i-- {
+		if out.NoInherit {
+			return out
+		}
+		ancestor := ancestors[i]
+		if !out.Colour.IsSet() {
+			out.Colour = ancestor.Colour
+		}
+		if !out.Background.IsSet() {
+			out.Background = ancestor.Background
+		}
+		if !out.Border.IsSet() {
+			out.Border = ancestor.Border
+		}
+		if out.Bold == Pass {
+			out.Bold = ancestor.Bold
+		}
+		if out.Italic == Pass {
+			out.Italic = ancestor.Italic
+		}
+		if out.Underline == Pass {
+			out.Underline = ancestor.Underline
+		}
+	}
+	return out
+}
+
+func (s StyleEntry) IsZero() bool {
+	return s.Colour == 0 && s.Background == 0 && s.Border == 0 && s.Bold == Pass && s.Italic == Pass &&
+		s.Underline == Pass && !s.NoInherit
+}
+
+// A StyleBuilder is a mutable structure for building styles.
+//
+// Once built, a Style is immutable.
+type StyleBuilder struct {
+	entries map[TokenType]string
+	name    string
+	theme   string
+	parent  *Style
+}
+
+func NewStyleBuilder(name string, theme string) *StyleBuilder {
+	return &StyleBuilder{name: name, theme: theme, entries: map[TokenType]string{}}
+}
+
+func (s *StyleBuilder) AddAll(entries StyleEntries) *StyleBuilder {
+	for ttype, entry := range entries {
+		s.entries[ttype] = entry
+	}
+	return s
+}
+
+func (s *StyleBuilder) Get(ttype TokenType) StyleEntry {
+	// This is less than ideal, but it's the price for not having to check errors on each Add().
+	entry, _ := ParseStyleEntry(s.entries[ttype])
+	if s.parent != nil {
+		entry = entry.Inherit(s.parent.Get(ttype))
+	}
+	return entry
+}
+
+// Add an entry to the Style map.
+//
+// See http://pygments.org/docs/styles/#style-rules for details.
+func (s *StyleBuilder) Add(ttype TokenType, entry string) *StyleBuilder { // nolint: gocyclo
+	s.entries[ttype] = entry
+	return s
+}
+
+func (s *StyleBuilder) AddEntry(ttype TokenType, entry StyleEntry) *StyleBuilder {
+	s.entries[ttype] = entry.String()
+	return s
+}
+
+// Transform passes each style entry currently defined in the builder to the supplied
+// function and saves the returned value. This can be used to adjust a style's colours;
+// see Colour's ClampBrightness function, for example.
+func (s *StyleBuilder) Transform(transform func(StyleEntry) StyleEntry) *StyleBuilder {
+	types := make(map[TokenType]struct{})
+	for tt := range s.entries {
+		types[tt] = struct{}{}
+	}
+	if s.parent != nil {
+		for _, tt := range s.parent.Types() {
+			types[tt] = struct{}{}
+		}
+	}
+	for tt := range types {
+		s.AddEntry(tt, transform(s.Get(tt)))
+	}
+	return s
+}
+
+func (s *StyleBuilder) Build() (*Style, error) {
+	style := &Style{
+		Name:    s.name,
+		Theme:   s.theme,
+		entries: map[TokenType]StyleEntry{},
+		parent:  s.parent,
+	}
+	for ttype, descriptor := range s.entries {
+		entry, err := ParseStyleEntry(descriptor)
+		if err != nil {
+			return nil, fmt.Errorf("invalid entry for %s: %s", ttype, err)
+		}
+		style.entries[ttype] = entry
+	}
+	return style, nil
+}
+
+// StyleEntries mapping TokenType to colour definition.
+type StyleEntries map[TokenType]string
+
+// NewXMLStyle parses an XML style definition.
+func NewXMLStyle(r io.Reader) (*Style, error) {
+	dec := xml.NewDecoder(r)
+	style := &Style{}
+	return style, dec.Decode(style)
+}
+
+// MustNewXMLStyle is like NewXMLStyle but panics on error.
+func MustNewXMLStyle(r io.Reader) *Style {
+	style, err := NewXMLStyle(r)
+	if err != nil {
+		panic(err)
+	}
+	return style
+}
+
+// NewStyle creates a new style definition.
+func NewStyle(name string, theme string, entries StyleEntries) (*Style, error) {
+	return NewStyleBuilder(name, theme).AddAll(entries).Build()
+}
+
+// MustNewStyle creates a new style or panics.
+func MustNewStyle(name string, theme string, entries StyleEntries) *Style {
+	style, err := NewStyle(name, theme, entries)
+	if err != nil {
+		panic(err)
+	}
+	return style
+}
+
+// A Style definition.
+//
+// See http://pygments.org/docs/styles/ for details. Semantics are intended to be identical.
+type Style struct {
+	Name    string
+	Theme   string
+	entries map[TokenType]StyleEntry
+	parent  *Style
+}
+
+func (s *Style) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+	if s.parent != nil {
+		return fmt.Errorf("cannot marshal style with parent")
+	}
+	start.Name = xml.Name{Local: "style"}
+	start.Attr = []xml.Attr{
+		{Name: xml.Name{Local: "name"}, Value: s.Name},
+		{Name: xml.Name{Local: "theme"}, Value: s.Theme},
+	}
+	if err := e.EncodeToken(start); err != nil {
+		return err
+	}
+	sorted := make([]TokenType, 0, len(s.entries))
+	for ttype := range s.entries {
+		sorted = append(sorted, ttype)
+	}
+	sort.Slice(sorted, func(i, j int) bool { return sorted[i] < sorted[j] })
+	for _, ttype := range sorted {
+		entry := s.entries[ttype]
+		el := xml.StartElement{Name: xml.Name{Local: "entry"}}
+		el.Attr = []xml.Attr{
+			{Name: xml.Name{Local: "type"}, Value: ttype.String()},
+			{Name: xml.Name{Local: "style"}, Value: entry.String()},
+		}
+		if err := e.EncodeToken(el); err != nil {
+			return err
+		}
+		if err := e.EncodeToken(xml.EndElement{Name: el.Name}); err != nil {
+			return err
+		}
+	}
+	return e.EncodeToken(xml.EndElement{Name: start.Name})
+}
+
+func (s *Style) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+	for _, attr := range start.Attr {
+		if attr.Name.Local == "name" {
+			s.Name = attr.Value
+		} else if attr.Name.Local == "theme" {
+			s.Theme = attr.Value
+		} else {
+			return fmt.Errorf("unexpected attribute %s", attr.Name.Local)
+		}
+	}
+	if s.Name == "" {
+		return fmt.Errorf("missing style name attribute")
+	}
+	if s.Theme == "" {
+		return fmt.Errorf("missing style theme attribute")
+	}
+	s.entries = map[TokenType]StyleEntry{}
+	for {
+		tok, err := d.Token()
+		if err != nil {
+			return err
+		}
+		switch el := tok.(type) {
+		case xml.StartElement:
+			if el.Name.Local != "entry" {
+				return fmt.Errorf("unexpected element %s", el.Name.Local)
+			}
+			var ttype TokenType
+			var entry StyleEntry
+			for _, attr := range el.Attr {
+				switch attr.Name.Local {
+				case "type":
+					ttype, err = TokenTypeString(attr.Value)
+					if err != nil {
+						return err
+					}
+
+				case "style":
+					entry, err = ParseStyleEntry(attr.Value)
+					if err != nil {
+						return err
+					}
+
+				default:
+					return fmt.Errorf("unexpected attribute %s", attr.Name.Local)
+				}
+			}
+			s.entries[ttype] = entry
+
+		case xml.EndElement:
+			if el.Name.Local == start.Name.Local {
+				return nil
+			}
+		}
+	}
+}
+
+// Types that are styled.
+func (s *Style) Types() []TokenType {
+	dedupe := map[TokenType]bool{}
+	for tt := range s.entries {
+		dedupe[tt] = true
+	}
+	if s.parent != nil {
+		for _, tt := range s.parent.Types() {
+			dedupe[tt] = true
+		}
+	}
+	out := make([]TokenType, 0, len(dedupe))
+	for tt := range dedupe {
+		out = append(out, tt)
+	}
+	return out
+}
+
+// Builder creates a mutable builder from this Style.
+//
+// The builder can then be safely modified. This is a cheap operation.
+func (s *Style) Builder() *StyleBuilder {
+	return &StyleBuilder{
+		name:    s.Name,
+		theme:   s.Theme,
+		entries: map[TokenType]string{},
+		parent:  s,
+	}
+}
+
+// Has checks if an exact style entry match exists for a token type.
+//
+// This is distinct from Get() which will merge parent tokens.
+func (s *Style) Has(ttype TokenType) bool {
+	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
+// finally return the Background.
+func (s *Style) Get(ttype TokenType) StyleEntry {
+	return s.get(ttype).Inherit(
+		s.get(Background),
+		s.get(Text),
+		s.get(ttype.Category()),
+		s.get(ttype.SubCategory()))
+}
+
+func (s *Style) get(ttype TokenType) StyleEntry {
+	out := s.entries[ttype]
+	if out.IsZero() && s.parent != nil {
+		return s.parent.get(ttype)
+	}
+	if out.IsZero() && s.synthesisable(ttype) {
+		out = s.synthesise(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
+
+	default:
+		return StyleEntry{}
+	}
+}
+
+func (s *Style) synthesisable(ttype TokenType) bool {
+	return ttype == LineHighlight || ttype == LineNumbers || ttype == LineNumbersTable
+}
+
+// MustParseStyleEntry parses a Pygments style entry or panics.
+func MustParseStyleEntry(entry string) StyleEntry {
+	out, err := ParseStyleEntry(entry)
+	if err != nil {
+		panic(err)
+	}
+	return out
+}
+
+// ParseStyleEntry parses a Pygments style entry.
+func ParseStyleEntry(entry string) (StyleEntry, error) { // nolint: gocyclo
+	out := StyleEntry{}
+	parts := strings.Fields(entry)
+	for _, part := range parts {
+		switch {
+		case part == "italic":
+			out.Italic = Yes
+		case part == "noitalic":
+			out.Italic = No
+		case part == "bold":
+			out.Bold = Yes
+		case part == "nobold":
+			out.Bold = No
+		case part == "underline":
+			out.Underline = Yes
+		case part == "nounderline":
+			out.Underline = No
+		case part == "inherit":
+			out.NoInherit = false
+		case part == "noinherit":
+			out.NoInherit = true
+		case part == "bg:":
+			out.Background = 0
+		case strings.HasPrefix(part, "bg:#"):
+			out.Background = ParseColour(part[3:])
+			if !out.Background.IsSet() {
+				return StyleEntry{}, fmt.Errorf("invalid background colour %q", part)
+			}
+		case strings.HasPrefix(part, "border:#"):
+			out.Border = ParseColour(part[7:])
+			if !out.Border.IsSet() {
+				return StyleEntry{}, fmt.Errorf("invalid border colour %q", part)
+			}
+		case strings.HasPrefix(part, "#"):
+			out.Colour = ParseColour(part)
+			if !out.Colour.IsSet() {
+				return StyleEntry{}, fmt.Errorf("invalid colour %q", part)
+			}
+		default:
+			return StyleEntry{}, fmt.Errorf("unknown style element %q", part)
+		}
+	}
+	return out, nil
+}
diff --git a/style_test.go b/style_test.go
new file mode 100644
index 0000000..becf19d
--- /dev/null
+++ b/style_test.go
@@ -0,0 +1,122 @@
+package chroma
+
+import (
+	"encoding/xml"
+	"testing"
+
+	"github.com/alecthomas/assert/v2"
+)
+
+func TestStyleInherit(t *testing.T) {
+	s, err := NewStyle("test", "dark", StyleEntries{
+		Name:         "bold #f00",
+		NameVariable: "#fff",
+	})
+	assert.NoError(t, err)
+	assert.Equal(t, StyleEntry{Colour: 0x1000000, Bold: Yes}, s.Get(NameVariable))
+}
+
+func TestStyleColours(t *testing.T) {
+	s, err := NewStyle("test", "dark", StyleEntries{
+		Name: "#f00 bg:#001 border:#ansiblue",
+	})
+	assert.NoError(t, err)
+	assert.Equal(t, StyleEntry{Colour: 0xff0001, Background: 0x000012, Border: 0x000100}, s.Get(Name))
+}
+
+func TestStyleClone(t *testing.T) {
+	parent, err := NewStyle("test", "dark", StyleEntries{
+		Background: "bg:#ffffff",
+	})
+	assert.NoError(t, err)
+	clone, err := parent.Builder().Add(Comment, "#0f0").Build()
+	assert.NoError(t, err)
+
+	assert.Equal(t, "bg:#ffffff", clone.Get(Background).String())
+	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", "dark", 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())
+}
+
+func TestSynthesisedStyleClone(t *testing.T) {
+	style, err := NewStyle("test", "dark", StyleEntries{
+		Background:    "bg:#ffffff",
+		LineHighlight: "bg:#ffffff",
+		LineNumbers:   "bg:#fffff1",
+	})
+	assert.NoError(t, err)
+	style, err = style.Builder().Build()
+	assert.NoError(t, err)
+	assert.True(t, style.Has(LineHighlight))
+	assert.True(t, style.Has(LineNumbers))
+	assert.Equal(t, "bg:#ffffff", style.Get(LineHighlight).String())
+	assert.Equal(t, "bg:#fffff1", style.Get(LineNumbers).String())
+}
+
+func TestStyleBuilderTransform(t *testing.T) {
+	orig, err := NewStyle("test", "dark", StyleEntries{
+		Name:         "#000",
+		NameVariable: "bold #f00",
+	})
+	assert.NoError(t, err)
+
+	// Derive a style that inherits entries from orig.
+	builder := orig.Builder()
+	builder.Add(NameVariableGlobal, "#f30")
+	deriv, err := builder.Build()
+	assert.NoError(t, err)
+
+	// Use Transform to brighten or darken all of the colours in the derived style.
+	light, err := deriv.Builder().Transform(func(se StyleEntry) StyleEntry {
+		se.Colour = se.Colour.ClampBrightness(0.9, 1)
+		return se
+	}).Build()
+	assert.NoError(t, err, "Transform failed: %v", err)
+	assert.True(t, light.Get(Name).Colour.Brightness() >= 0.89)
+	assert.True(t, light.Get(NameVariable).Colour.Brightness() >= 0.89)
+	assert.True(t, light.Get(NameVariableGlobal).Colour.Brightness() >= 0.89)
+
+	dark, err := deriv.Builder().Transform(func(se StyleEntry) StyleEntry {
+		se.Colour = se.Colour.ClampBrightness(0, 0.1)
+		return se
+	}).Build()
+	assert.NoError(t, err, "Transform failed: %v", err)
+	assert.True(t, dark.Get(Name).Colour.Brightness() <= 0.11)
+	assert.True(t, dark.Get(NameVariable).Colour.Brightness() <= 0.11)
+	assert.True(t, dark.Get(NameVariableGlobal).Colour.Brightness() <= 0.11)
+
+	// The original styles should be unchanged.
+	assert.Equal(t, "#000000", orig.Get(Name).Colour.String())
+	assert.Equal(t, "#ff0000", orig.Get(NameVariable).Colour.String())
+	assert.Equal(t, "#ff3300", deriv.Get(NameVariableGlobal).Colour.String())
+}
+
+func TestStyleMarshaller(t *testing.T) {
+	expected, err := NewStyle("test", "dark", StyleEntries{
+		Whitespace: "bg:#ffffff",
+		Text:       "#000000 underline",
+	})
+	assert.NoError(t, err)
+	data, err := xml.MarshalIndent(expected, "", "  ")
+	assert.NoError(t, err)
+	assert.Equal(t, `<style name="test">
+  <entry type="Text" style="underline #000000"></entry>
+  <entry type="TextWhitespace" style="bg:#ffffff"></entry>
+</style>`, string(data))
+	actual := &Style{}
+	err = xml.Unmarshal(data, actual)
+	assert.NoError(t, err)
+	assert.Equal(t, expected, actual)
+}
diff --git a/styles/api.go b/styles/api.go
new file mode 100644
index 0000000..2936aeb
--- /dev/null
+++ b/styles/api.go
@@ -0,0 +1,93 @@
+package styles
+
+import (
+	"embed"
+	"io/fs"
+	"path/filepath"
+	"sort"
+
+	"toastielab.dev/toastie-stuff/chroma/v2"
+	"toastielab.dev/toastie-stuff/chroma/v2/base16"
+)
+
+//go:embed embedded
+var embedded embed.FS
+
+// Registry of Styles.
+var Registry = func() map[string]*chroma.Style {
+	registry := map[string]*chroma.Style{}
+	// Register all embedded styles.
+	embeddedSub, err := fs.Sub(embedded, "embedded")
+	if err != nil {
+		panic(err)
+	}
+	styles, err := LoadFromFS(embeddedSub)
+	if err != nil {
+		panic(err)
+	}
+	for _, style := range styles {
+		registry[style.Name] = style
+	}
+	return registry
+}()
+
+// Fallback style. Reassign to change the default fallback style.
+var Fallback = Registry["swapoff"]
+
+func LoadFromFS(fsys fs.FS) ([]*chroma.Style, error) {
+	files, err := fs.ReadDir(fsys, ".")
+	if err != nil {
+		return nil, err
+	}
+
+	styles := make([]*chroma.Style, 0, len(files))
+	for _, file := range files {
+		if file.IsDir() {
+			continue
+		}
+
+		r, err := fsys.Open(file.Name())
+		if err != nil {
+			return nil, err
+		}
+
+		var style *chroma.Style
+		switch filepath.Ext(file.Name()) {
+		case ".xml":
+			style, err = chroma.NewXMLStyle(r)
+		case ".yaml", ".yml":
+			style, err = base16.NewStyle(r)
+		}
+		if err != nil {
+			return nil, err
+		}
+
+		styles = append(styles, style)
+	}
+
+	return styles, nil
+}
+
+// Register a chroma.Style.
+func Register(style *chroma.Style) *chroma.Style {
+	Registry[style.Name] = style
+	return style
+}
+
+// Names of all available styles.
+func Names() []string {
+	out := []string{}
+	for name := range Registry {
+		out = append(out, name)
+	}
+	sort.Strings(out)
+	return out
+}
+
+// Get named style, or Fallback.
+func Get(name string) *chroma.Style {
+	if style, ok := Registry[name]; ok {
+		return style
+	}
+	return Fallback
+}
diff --git a/styles/embedded/abap.xml b/styles/embedded/abap.xml
new file mode 100644
index 0000000..8f0f1d3
--- /dev/null
+++ b/styles/embedded/abap.xml
@@ -0,0 +1,11 @@
+<style name="abap" theme="light">
+  <entry type="Error" style="#ff0000"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="#0000ff"/>
+  <entry type="Name" style="#000000"/>
+  <entry type="LiteralString" style="#55aa22"/>
+  <entry type="LiteralNumber" style="#33aaff"/>
+  <entry type="OperatorWord" style="#0000ff"/>
+  <entry type="Comment" style="italic #888888"/>
+  <entry type="CommentSpecial" style="#888888"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/algol.xml b/styles/embedded/algol.xml
new file mode 100644
index 0000000..8abc640
--- /dev/null
+++ b/styles/embedded/algol.xml
@@ -0,0 +1,18 @@
+<style name="algol" theme="light">
+  <entry type="Error" style="border:#ff0000"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="bold underline"/>
+  <entry type="KeywordDeclaration" style="italic"/>
+  <entry type="NameBuiltin" style="bold italic"/>
+  <entry type="NameBuiltinPseudo" style="bold italic"/>
+  <entry type="NameClass" style="bold italic #666666"/>
+  <entry type="NameConstant" style="bold italic #666666"/>
+  <entry type="NameFunction" style="bold italic #666666"/>
+  <entry type="NameNamespace" style="bold italic #666666"/>
+  <entry type="NameVariable" style="bold italic #666666"/>
+  <entry type="LiteralString" style="italic #666666"/>
+  <entry type="OperatorWord" style="bold"/>
+  <entry type="Comment" style="italic #888888"/>
+  <entry type="CommentSpecial" style="bold noitalic #888888"/>
+  <entry type="CommentPreproc" style="bold noitalic #888888"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/algol_nu.xml b/styles/embedded/algol_nu.xml
new file mode 100644
index 0000000..ad296ca
--- /dev/null
+++ b/styles/embedded/algol_nu.xml
@@ -0,0 +1,18 @@
+<style name="algol_nu" theme="light">
+  <entry type="Error" style="border:#ff0000"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="bold"/>
+  <entry type="KeywordDeclaration" style="italic"/>
+  <entry type="NameBuiltin" style="bold italic"/>
+  <entry type="NameBuiltinPseudo" style="bold italic"/>
+  <entry type="NameClass" style="bold italic #666666"/>
+  <entry type="NameConstant" style="bold italic #666666"/>
+  <entry type="NameFunction" style="bold italic #666666"/>
+  <entry type="NameNamespace" style="bold italic #666666"/>
+  <entry type="NameVariable" style="bold italic #666666"/>
+  <entry type="LiteralString" style="italic #666666"/>
+  <entry type="OperatorWord" style="bold"/>
+  <entry type="Comment" style="italic #888888"/>
+  <entry type="CommentSpecial" style="bold noitalic #888888"/>
+  <entry type="CommentPreproc" style="bold noitalic #888888"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/arduino.xml b/styles/embedded/arduino.xml
new file mode 100644
index 0000000..bbf6197
--- /dev/null
+++ b/styles/embedded/arduino.xml
@@ -0,0 +1,18 @@
+<style name="arduino" theme="light">
+  <entry type="Error" style="#a61717"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="#728e00"/>
+  <entry type="KeywordConstant" style="#00979d"/>
+  <entry type="KeywordPseudo" style="#00979d"/>
+  <entry type="KeywordReserved" style="#00979d"/>
+  <entry type="KeywordType" style="#00979d"/>
+  <entry type="Name" style="#434f54"/>
+  <entry type="NameBuiltin" style="#728e00"/>
+  <entry type="NameFunction" style="#d35400"/>
+  <entry type="NameOther" style="#728e00"/>
+  <entry type="LiteralString" style="#7f8c8d"/>
+  <entry type="LiteralNumber" style="#8a7b52"/>
+  <entry type="Operator" style="#728e00"/>
+  <entry type="Comment" style="#95a5a6"/>
+  <entry type="CommentPreproc" style="#728e00"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/autumn.xml b/styles/embedded/autumn.xml
new file mode 100644
index 0000000..453e407
--- /dev/null
+++ b/styles/embedded/autumn.xml
@@ -0,0 +1,36 @@
+<style name="autumn" theme="light">
+  <entry type="Error" style="#ff0000 bg:#ffaaaa"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="#0000aa"/>
+  <entry type="KeywordType" style="#00aaaa"/>
+  <entry type="NameAttribute" style="#1e90ff"/>
+  <entry type="NameBuiltin" style="#00aaaa"/>
+  <entry type="NameClass" style="underline #00aa00"/>
+  <entry type="NameConstant" style="#aa0000"/>
+  <entry type="NameDecorator" style="#888888"/>
+  <entry type="NameEntity" style="bold #880000"/>
+  <entry type="NameFunction" style="#00aa00"/>
+  <entry type="NameNamespace" style="underline #00aaaa"/>
+  <entry type="NameTag" style="bold #1e90ff"/>
+  <entry type="NameVariable" style="#aa0000"/>
+  <entry type="LiteralString" style="#aa5500"/>
+  <entry type="LiteralStringRegex" style="#009999"/>
+  <entry type="LiteralStringSymbol" style="#0000aa"/>
+  <entry type="LiteralNumber" style="#009999"/>
+  <entry type="OperatorWord" style="#0000aa"/>
+  <entry type="Comment" style="italic #aaaaaa"/>
+  <entry type="CommentSpecial" style="italic #0000aa"/>
+  <entry type="CommentPreproc" style="noitalic #4c8317"/>
+  <entry type="GenericDeleted" style="#aa0000"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#aa0000"/>
+  <entry type="GenericHeading" style="bold #000080"/>
+  <entry type="GenericInserted" style="#00aa00"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="#555555"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #800080"/>
+  <entry type="GenericTraceback" style="#aa0000"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/average.xml b/styles/embedded/average.xml
new file mode 100644
index 0000000..65502fa
--- /dev/null
+++ b/styles/embedded/average.xml
@@ -0,0 +1,74 @@
+<style name="average" theme="dark">
+  <entry type="Other" style="#757575"/>
+  <entry type="Error" style="#ec0000"/>
+  <entry type="Background" style="bg:#000000"/>
+  <entry type="Keyword" style="#ec0000"/>
+  <entry type="KeywordConstant" style="#ec0000"/>
+  <entry type="KeywordDeclaration" style="#ec0000"/>
+  <entry type="KeywordNamespace" style="#ec0000"/>
+  <entry type="KeywordPseudo" style="#ec0000"/>
+  <entry type="KeywordReserved" style="#ec0000"/>
+  <entry type="KeywordType" style="#5f5fff"/>
+  <entry type="Name" style="#757575"/>
+  <entry type="NameAttribute" style="#5f5fff"/>
+  <entry type="NameBuiltin" style="#ec0000"/>
+  <entry type="NameBuiltinPseudo" style="#757575"/>
+  <entry type="NameClass" style="#5f5fff"/>
+  <entry type="NameConstant" style="#008900"/>
+  <entry type="NameDecorator" style="#008900"/>
+  <entry type="NameEntity" style="#757575"/>
+  <entry type="NameException" style="#757575"/>
+  <entry type="NameFunction" style="#5f5fff"/>
+  <entry type="NameLabel" style="#ec0000"/>
+  <entry type="NameNamespace" style="#757575"/>
+  <entry type="NameOther" style="#757575"/>
+  <entry type="NameTag" style="#ec0000"/>
+  <entry type="NameVariable" style="#ec0000"/>
+  <entry type="NameVariableClass" style="#ec0000"/>
+  <entry type="NameVariableGlobal" style="#ec0000"/>
+  <entry type="NameVariableInstance" style="#ec0000"/>
+  <entry type="Literal" style="#757575"/>
+  <entry type="LiteralDate" style="#757575"/>
+  <entry type="LiteralString" style="#008900"/>
+  <entry type="LiteralStringBacktick" style="#008900"/>
+  <entry type="LiteralStringChar" style="#008900"/>
+  <entry type="LiteralStringDoc" style="#008900"/>
+  <entry type="LiteralStringDouble" style="#008900"/>
+  <entry type="LiteralStringEscape" style="#008900"/>
+  <entry type="LiteralStringHeredoc" style="#008900"/>
+  <entry type="LiteralStringInterpol" style="#008900"/>
+  <entry type="LiteralStringOther" style="#008900"/>
+  <entry type="LiteralStringRegex" style="#008900"/>
+  <entry type="LiteralStringSingle" style="#008900"/>
+  <entry type="LiteralStringSymbol" style="#008900"/>
+  <entry type="LiteralNumber" style="#008900"/>
+  <entry type="LiteralNumberBin" style="#008900"/>
+  <entry type="LiteralNumberFloat" style="#008900"/>
+  <entry type="LiteralNumberHex" style="#008900"/>
+  <entry type="LiteralNumberInteger" style="#008900"/>
+  <entry type="LiteralNumberIntegerLong" style="#008900"/>
+  <entry type="LiteralNumberOct" style="#008900"/>
+  <entry type="Operator" style="#ec0000"/>
+  <entry type="OperatorWord" style="#ec0000"/>
+  <entry type="Punctuation" style="#757575"/>
+  <entry type="Comment" style="#757575"/>
+  <entry type="CommentHashbang" style="#757575"/>
+  <entry type="CommentMultiline" style="#757575"/>
+  <entry type="CommentSingle" style="#757575"/>
+  <entry type="CommentSpecial" style="#757575"/>
+  <entry type="CommentPreproc" style="#757575"/>
+  <entry type="Generic" style="#757575"/>
+  <entry type="GenericDeleted" style="#ec0000"/>
+  <entry type="GenericEmph" style="underline #757575"/>
+  <entry type="GenericError" style="#ec0000"/>
+  <entry type="GenericHeading" style="bold #757575"/>
+  <entry type="GenericInserted" style="bold #757575"/>
+  <entry type="GenericOutput" style="#757575"/>
+  <entry type="GenericPrompt" style="#757575"/>
+  <entry type="GenericStrong" style="italic #757575"/>
+  <entry type="GenericSubheading" style="bold #757575"/>
+  <entry type="GenericTraceback" style="#757575"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="Text" style="#757575"/>
+  <entry type="TextWhitespace" style="#757575"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/base16-snazzy.xml b/styles/embedded/base16-snazzy.xml
new file mode 100644
index 0000000..d4a5c0a
--- /dev/null
+++ b/styles/embedded/base16-snazzy.xml
@@ -0,0 +1,74 @@
+<style name="base16-snazzy" theme="dark">
+  <entry type="Other" style="#e2e4e5"/>
+  <entry type="Error" style="#ff5c57"/>
+  <entry type="Background" style="bg:#282a36"/>
+  <entry type="Keyword" style="#ff6ac1"/>
+  <entry type="KeywordConstant" style="#ff6ac1"/>
+  <entry type="KeywordDeclaration" style="#ff5c57"/>
+  <entry type="KeywordNamespace" style="#ff6ac1"/>
+  <entry type="KeywordPseudo" style="#ff6ac1"/>
+  <entry type="KeywordReserved" style="#ff6ac1"/>
+  <entry type="KeywordType" style="#9aedfe"/>
+  <entry type="Name" style="#e2e4e5"/>
+  <entry type="NameAttribute" style="#57c7ff"/>
+  <entry type="NameBuiltin" style="#ff5c57"/>
+  <entry type="NameBuiltinPseudo" style="#e2e4e5"/>
+  <entry type="NameClass" style="#f3f99d"/>
+  <entry type="NameConstant" style="#ff9f43"/>
+  <entry type="NameDecorator" style="#ff9f43"/>
+  <entry type="NameEntity" style="#e2e4e5"/>
+  <entry type="NameException" style="#e2e4e5"/>
+  <entry type="NameFunction" style="#57c7ff"/>
+  <entry type="NameLabel" style="#ff5c57"/>
+  <entry type="NameNamespace" style="#e2e4e5"/>
+  <entry type="NameOther" style="#e2e4e5"/>
+  <entry type="NameTag" style="#ff6ac1"/>
+  <entry type="NameVariable" style="#ff5c57"/>
+  <entry type="NameVariableClass" style="#ff5c57"/>
+  <entry type="NameVariableGlobal" style="#ff5c57"/>
+  <entry type="NameVariableInstance" style="#ff5c57"/>
+  <entry type="Literal" style="#e2e4e5"/>
+  <entry type="LiteralDate" style="#e2e4e5"/>
+  <entry type="LiteralString" style="#5af78e"/>
+  <entry type="LiteralStringBacktick" style="#5af78e"/>
+  <entry type="LiteralStringChar" style="#5af78e"/>
+  <entry type="LiteralStringDoc" style="#5af78e"/>
+  <entry type="LiteralStringDouble" style="#5af78e"/>
+  <entry type="LiteralStringEscape" style="#5af78e"/>
+  <entry type="LiteralStringHeredoc" style="#5af78e"/>
+  <entry type="LiteralStringInterpol" style="#5af78e"/>
+  <entry type="LiteralStringOther" style="#5af78e"/>
+  <entry type="LiteralStringRegex" style="#5af78e"/>
+  <entry type="LiteralStringSingle" style="#5af78e"/>
+  <entry type="LiteralStringSymbol" style="#5af78e"/>
+  <entry type="LiteralNumber" style="#ff9f43"/>
+  <entry type="LiteralNumberBin" style="#ff9f43"/>
+  <entry type="LiteralNumberFloat" style="#ff9f43"/>
+  <entry type="LiteralNumberHex" style="#ff9f43"/>
+  <entry type="LiteralNumberInteger" style="#ff9f43"/>
+  <entry type="LiteralNumberIntegerLong" style="#ff9f43"/>
+  <entry type="LiteralNumberOct" style="#ff9f43"/>
+  <entry type="Operator" style="#ff6ac1"/>
+  <entry type="OperatorWord" style="#ff6ac1"/>
+  <entry type="Punctuation" style="#e2e4e5"/>
+  <entry type="Comment" style="#78787e"/>
+  <entry type="CommentHashbang" style="#78787e"/>
+  <entry type="CommentMultiline" style="#78787e"/>
+  <entry type="CommentSingle" style="#78787e"/>
+  <entry type="CommentSpecial" style="#78787e"/>
+  <entry type="CommentPreproc" style="#78787e"/>
+  <entry type="Generic" style="#e2e4e5"/>
+  <entry type="GenericDeleted" style="#ff5c57"/>
+  <entry type="GenericEmph" style="underline #e2e4e5"/>
+  <entry type="GenericError" style="#ff5c57"/>
+  <entry type="GenericHeading" style="bold #e2e4e5"/>
+  <entry type="GenericInserted" style="bold #e2e4e5"/>
+  <entry type="GenericOutput" style="#43454f"/>
+  <entry type="GenericPrompt" style="#e2e4e5"/>
+  <entry type="GenericStrong" style="italic #e2e4e5"/>
+  <entry type="GenericSubheading" style="bold #e2e4e5"/>
+  <entry type="GenericTraceback" style="#e2e4e5"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="Text" style="#e2e4e5"/>
+  <entry type="TextWhitespace" style="#e2e4e5"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/borland.xml b/styles/embedded/borland.xml
new file mode 100644
index 0000000..0c1d4e9
--- /dev/null
+++ b/styles/embedded/borland.xml
@@ -0,0 +1,26 @@
+<style name="borland" theme="light">
+  <entry type="Error" style="#a61717 bg:#e3d2d2"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="bold #000080"/>
+  <entry type="NameAttribute" style="#ff0000"/>
+  <entry type="NameTag" style="bold #000080"/>
+  <entry type="LiteralString" style="#0000ff"/>
+  <entry type="LiteralStringChar" style="#800080"/>
+  <entry type="LiteralNumber" style="#0000ff"/>
+  <entry type="OperatorWord" style="bold"/>
+  <entry type="Comment" style="italic #008800"/>
+  <entry type="CommentSpecial" style="bold noitalic"/>
+  <entry type="CommentPreproc" style="noitalic #008080"/>
+  <entry type="GenericDeleted" style="#000000 bg:#ffdddd"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#aa0000"/>
+  <entry type="GenericHeading" style="#999999"/>
+  <entry type="GenericInserted" style="#000000 bg:#ddffdd"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="#555555"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#aaaaaa"/>
+  <entry type="GenericTraceback" style="#aa0000"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/bw.xml b/styles/embedded/bw.xml
new file mode 100644
index 0000000..e454f61
--- /dev/null
+++ b/styles/embedded/bw.xml
@@ -0,0 +1,23 @@
+<style name="bw" theme="light">
+  <entry type="Error" style="border:#ff0000"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="bold"/>
+  <entry type="KeywordPseudo" style="nobold"/>
+  <entry type="KeywordType" style="nobold"/>
+  <entry type="NameClass" style="bold"/>
+  <entry type="NameEntity" style="bold"/>
+  <entry type="NameException" style="bold"/>
+  <entry type="NameNamespace" style="bold"/>
+  <entry type="NameTag" style="bold"/>
+  <entry type="LiteralString" style="italic"/>
+  <entry type="LiteralStringEscape" style="bold"/>
+  <entry type="LiteralStringInterpol" style="bold"/>
+  <entry type="OperatorWord" style="bold"/>
+  <entry type="Comment" style="italic"/>
+  <entry type="CommentPreproc" style="noitalic"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericHeading" style="bold"/>
+  <entry type="GenericPrompt" style="bold"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/catppuccin-frappe.xml b/styles/embedded/catppuccin-frappe.xml
new file mode 100644
index 0000000..b3827a3
--- /dev/null
+++ b/styles/embedded/catppuccin-frappe.xml
@@ -0,0 +1,83 @@
+<style name="catppuccin-frappe" theme="dark">
+  <entry type="Background" style="bg:#303446 #c6d0f5"/>
+  <entry type="CodeLine" style="#c6d0f5"/>
+  <entry type="Error" style="#e78284"/>
+  <entry type="Other" style="#c6d0f5"/>
+  <entry type="LineTableTD" style=""/>
+  <entry type="LineTable" style=""/>
+  <entry type="LineHighlight" style="bg:#51576d"/>
+  <entry type="LineNumbersTable" style="#838ba7"/>
+  <entry type="LineNumbers" style="#838ba7"/>
+  <entry type="Keyword" style="#ca9ee6"/>
+  <entry type="KeywordReserved" style="#ca9ee6"/>
+  <entry type="KeywordPseudo" style="#ca9ee6"/>
+  <entry type="KeywordConstant" style="#ef9f76"/>
+  <entry type="KeywordDeclaration" style="#e78284"/>
+  <entry type="KeywordNamespace" style="#81c8be"/>
+  <entry type="KeywordType" style="#e78284"/>
+  <entry type="Name" style="#c6d0f5"/>
+  <entry type="NameClass" style="#e5c890"/>
+  <entry type="NameConstant" style="#e5c890"/>
+  <entry type="NameDecorator" style="bold #8caaee"/>
+  <entry type="NameEntity" style="#81c8be"/>
+  <entry type="NameException" style="#ef9f76"/>
+  <entry type="NameFunction" style="#8caaee"/>
+  <entry type="NameFunctionMagic" style="#8caaee"/>
+  <entry type="NameLabel" style="#99d1db"/>
+  <entry type="NameNamespace" style="#ef9f76"/>
+  <entry type="NameProperty" style="#ef9f76"/>
+  <entry type="NameTag" style="#ca9ee6"/>
+  <entry type="NameVariable" style="#f2d5cf"/>
+  <entry type="NameVariableClass" style="#f2d5cf"/>
+  <entry type="NameVariableGlobal" style="#f2d5cf"/>
+  <entry type="NameVariableInstance" style="#f2d5cf"/>
+  <entry type="NameVariableMagic" style="#f2d5cf"/>
+  <entry type="NameAttribute" style="#8caaee"/>
+  <entry type="NameBuiltin" style="#99d1db"/>
+  <entry type="NameBuiltinPseudo" style="#99d1db"/>
+  <entry type="NameOther" style="#c6d0f5"/>
+  <entry type="Literal" style="#c6d0f5"/>
+  <entry type="LiteralDate" style="#c6d0f5"/>
+  <entry type="LiteralString" style="#a6d189"/>
+  <entry type="LiteralStringChar" style="#a6d189"/>
+  <entry type="LiteralStringSingle" style="#a6d189"/>
+  <entry type="LiteralStringDouble" style="#a6d189"/>
+  <entry type="LiteralStringBacktick" style="#a6d189"/>
+  <entry type="LiteralStringOther" style="#a6d189"/>
+  <entry type="LiteralStringSymbol" style="#a6d189"/>
+  <entry type="LiteralStringInterpol" style="#a6d189"/>
+  <entry type="LiteralStringAffix" style="#e78284"/>
+  <entry type="LiteralStringDelimiter" style="#8caaee"/>
+  <entry type="LiteralStringEscape" style="#8caaee"/>
+  <entry type="LiteralStringRegex" style="#81c8be"/>
+  <entry type="LiteralStringDoc" style="#737994"/>
+  <entry type="LiteralStringHeredoc" style="#737994"/>
+  <entry type="LiteralNumber" style="#ef9f76"/>
+  <entry type="LiteralNumberBin" style="#ef9f76"/>
+  <entry type="LiteralNumberHex" style="#ef9f76"/>
+  <entry type="LiteralNumberInteger" style="#ef9f76"/>
+  <entry type="LiteralNumberFloat" style="#ef9f76"/>
+  <entry type="LiteralNumberIntegerLong" style="#ef9f76"/>
+  <entry type="LiteralNumberOct" style="#ef9f76"/>
+  <entry type="Operator" style="bold #99d1db"/>
+  <entry type="OperatorWord" style="bold #99d1db"/>
+  <entry type="Comment" style="italic #737994"/>
+  <entry type="CommentSingle" style="italic #737994"/>
+  <entry type="CommentMultiline" style="italic #737994"/>
+  <entry type="CommentSpecial" style="italic #737994"/>
+  <entry type="CommentHashbang" style="italic #737994"/>
+  <entry type="CommentPreproc" style="italic #737994"/>
+  <entry type="CommentPreprocFile" style="bold #737994"/>
+  <entry type="Generic" style="#c6d0f5"/>
+  <entry type="GenericInserted" style="bg:#414559 #a6d189"/>
+  <entry type="GenericDeleted" style="#e78284 bg:#414559"/>
+  <entry type="GenericEmph" style="italic #c6d0f5"/>
+  <entry type="GenericStrong" style="bold #c6d0f5"/>
+  <entry type="GenericUnderline" style="underline #c6d0f5"/>
+  <entry type="GenericHeading" style="bold #ef9f76"/>
+  <entry type="GenericSubheading" style="bold #ef9f76"/>
+  <entry type="GenericOutput" style="#c6d0f5"/>
+  <entry type="GenericPrompt" style="#c6d0f5"/>
+  <entry type="GenericError" style="#e78284"/>
+  <entry type="GenericTraceback" style="#e78284"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/catppuccin-latte.xml b/styles/embedded/catppuccin-latte.xml
new file mode 100644
index 0000000..48187f2
--- /dev/null
+++ b/styles/embedded/catppuccin-latte.xml
@@ -0,0 +1,83 @@
+<style name="catppuccin-latte" theme="light">
+  <entry type="Background" style="bg:#eff1f5 #4c4f69"/>
+  <entry type="CodeLine" style="#4c4f69"/>
+  <entry type="Error" style="#d20f39"/>
+  <entry type="Other" style="#4c4f69"/>
+  <entry type="LineTableTD" style=""/>
+  <entry type="LineTable" style=""/>
+  <entry type="LineHighlight" style="bg:#bcc0cc"/>
+  <entry type="LineNumbersTable" style="#8c8fa1"/>
+  <entry type="LineNumbers" style="#8c8fa1"/>
+  <entry type="Keyword" style="#8839ef"/>
+  <entry type="KeywordReserved" style="#8839ef"/>
+  <entry type="KeywordPseudo" style="#8839ef"/>
+  <entry type="KeywordConstant" style="#fe640b"/>
+  <entry type="KeywordDeclaration" style="#d20f39"/>
+  <entry type="KeywordNamespace" style="#179299"/>
+  <entry type="KeywordType" style="#d20f39"/>
+  <entry type="Name" style="#4c4f69"/>
+  <entry type="NameClass" style="#df8e1d"/>
+  <entry type="NameConstant" style="#df8e1d"/>
+  <entry type="NameDecorator" style="bold #1e66f5"/>
+  <entry type="NameEntity" style="#179299"/>
+  <entry type="NameException" style="#fe640b"/>
+  <entry type="NameFunction" style="#1e66f5"/>
+  <entry type="NameFunctionMagic" style="#1e66f5"/>
+  <entry type="NameLabel" style="#04a5e5"/>
+  <entry type="NameNamespace" style="#fe640b"/>
+  <entry type="NameProperty" style="#fe640b"/>
+  <entry type="NameTag" style="#8839ef"/>
+  <entry type="NameVariable" style="#dc8a78"/>
+  <entry type="NameVariableClass" style="#dc8a78"/>
+  <entry type="NameVariableGlobal" style="#dc8a78"/>
+  <entry type="NameVariableInstance" style="#dc8a78"/>
+  <entry type="NameVariableMagic" style="#dc8a78"/>
+  <entry type="NameAttribute" style="#1e66f5"/>
+  <entry type="NameBuiltin" style="#04a5e5"/>
+  <entry type="NameBuiltinPseudo" style="#04a5e5"/>
+  <entry type="NameOther" style="#4c4f69"/>
+  <entry type="Literal" style="#4c4f69"/>
+  <entry type="LiteralDate" style="#4c4f69"/>
+  <entry type="LiteralString" style="#40a02b"/>
+  <entry type="LiteralStringChar" style="#40a02b"/>
+  <entry type="LiteralStringSingle" style="#40a02b"/>
+  <entry type="LiteralStringDouble" style="#40a02b"/>
+  <entry type="LiteralStringBacktick" style="#40a02b"/>
+  <entry type="LiteralStringOther" style="#40a02b"/>
+  <entry type="LiteralStringSymbol" style="#40a02b"/>
+  <entry type="LiteralStringInterpol" style="#40a02b"/>
+  <entry type="LiteralStringAffix" style="#d20f39"/>
+  <entry type="LiteralStringDelimiter" style="#1e66f5"/>
+  <entry type="LiteralStringEscape" style="#1e66f5"/>
+  <entry type="LiteralStringRegex" style="#179299"/>
+  <entry type="LiteralStringDoc" style="#9ca0b0"/>
+  <entry type="LiteralStringHeredoc" style="#9ca0b0"/>
+  <entry type="LiteralNumber" style="#fe640b"/>
+  <entry type="LiteralNumberBin" style="#fe640b"/>
+  <entry type="LiteralNumberHex" style="#fe640b"/>
+  <entry type="LiteralNumberInteger" style="#fe640b"/>
+  <entry type="LiteralNumberFloat" style="#fe640b"/>
+  <entry type="LiteralNumberIntegerLong" style="#fe640b"/>
+  <entry type="LiteralNumberOct" style="#fe640b"/>
+  <entry type="Operator" style="bold #04a5e5"/>
+  <entry type="OperatorWord" style="bold #04a5e5"/>
+  <entry type="Comment" style="italic #9ca0b0"/>
+  <entry type="CommentSingle" style="italic #9ca0b0"/>
+  <entry type="CommentMultiline" style="italic #9ca0b0"/>
+  <entry type="CommentSpecial" style="italic #9ca0b0"/>
+  <entry type="CommentHashbang" style="italic #9ca0b0"/>
+  <entry type="CommentPreproc" style="italic #9ca0b0"/>
+  <entry type="CommentPreprocFile" style="bold #9ca0b0"/>
+  <entry type="Generic" style="#4c4f69"/>
+  <entry type="GenericInserted" style="bg:#ccd0da #40a02b"/>
+  <entry type="GenericDeleted" style="#d20f39 bg:#ccd0da"/>
+  <entry type="GenericEmph" style="italic #4c4f69"/>
+  <entry type="GenericStrong" style="bold #4c4f69"/>
+  <entry type="GenericUnderline" style="underline #4c4f69"/>
+  <entry type="GenericHeading" style="bold #fe640b"/>
+  <entry type="GenericSubheading" style="bold #fe640b"/>
+  <entry type="GenericOutput" style="#4c4f69"/>
+  <entry type="GenericPrompt" style="#4c4f69"/>
+  <entry type="GenericError" style="#d20f39"/>
+  <entry type="GenericTraceback" style="#d20f39"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/catppuccin-macchiato.xml b/styles/embedded/catppuccin-macchiato.xml
new file mode 100644
index 0000000..ca53113
--- /dev/null
+++ b/styles/embedded/catppuccin-macchiato.xml
@@ -0,0 +1,83 @@
+<style name="catppuccin-macchiato" theme="dark">
+  <entry type="Background" style="bg:#24273a #cad3f5"/>
+  <entry type="CodeLine" style="#cad3f5"/>
+  <entry type="Error" style="#ed8796"/>
+  <entry type="Other" style="#cad3f5"/>
+  <entry type="LineTableTD" style=""/>
+  <entry type="LineTable" style=""/>
+  <entry type="LineHighlight" style="bg:#494d64"/>
+  <entry type="LineNumbersTable" style="#8087a2"/>
+  <entry type="LineNumbers" style="#8087a2"/>
+  <entry type="Keyword" style="#c6a0f6"/>
+  <entry type="KeywordReserved" style="#c6a0f6"/>
+  <entry type="KeywordPseudo" style="#c6a0f6"/>
+  <entry type="KeywordConstant" style="#f5a97f"/>
+  <entry type="KeywordDeclaration" style="#ed8796"/>
+  <entry type="KeywordNamespace" style="#8bd5ca"/>
+  <entry type="KeywordType" style="#ed8796"/>
+  <entry type="Name" style="#cad3f5"/>
+  <entry type="NameClass" style="#eed49f"/>
+  <entry type="NameConstant" style="#eed49f"/>
+  <entry type="NameDecorator" style="bold #8aadf4"/>
+  <entry type="NameEntity" style="#8bd5ca"/>
+  <entry type="NameException" style="#f5a97f"/>
+  <entry type="NameFunction" style="#8aadf4"/>
+  <entry type="NameFunctionMagic" style="#8aadf4"/>
+  <entry type="NameLabel" style="#91d7e3"/>
+  <entry type="NameNamespace" style="#f5a97f"/>
+  <entry type="NameProperty" style="#f5a97f"/>
+  <entry type="NameTag" style="#c6a0f6"/>
+  <entry type="NameVariable" style="#f4dbd6"/>
+  <entry type="NameVariableClass" style="#f4dbd6"/>
+  <entry type="NameVariableGlobal" style="#f4dbd6"/>
+  <entry type="NameVariableInstance" style="#f4dbd6"/>
+  <entry type="NameVariableMagic" style="#f4dbd6"/>
+  <entry type="NameAttribute" style="#8aadf4"/>
+  <entry type="NameBuiltin" style="#91d7e3"/>
+  <entry type="NameBuiltinPseudo" style="#91d7e3"/>
+  <entry type="NameOther" style="#cad3f5"/>
+  <entry type="Literal" style="#cad3f5"/>
+  <entry type="LiteralDate" style="#cad3f5"/>
+  <entry type="LiteralString" style="#a6da95"/>
+  <entry type="LiteralStringChar" style="#a6da95"/>
+  <entry type="LiteralStringSingle" style="#a6da95"/>
+  <entry type="LiteralStringDouble" style="#a6da95"/>
+  <entry type="LiteralStringBacktick" style="#a6da95"/>
+  <entry type="LiteralStringOther" style="#a6da95"/>
+  <entry type="LiteralStringSymbol" style="#a6da95"/>
+  <entry type="LiteralStringInterpol" style="#a6da95"/>
+  <entry type="LiteralStringAffix" style="#ed8796"/>
+  <entry type="LiteralStringDelimiter" style="#8aadf4"/>
+  <entry type="LiteralStringEscape" style="#8aadf4"/>
+  <entry type="LiteralStringRegex" style="#8bd5ca"/>
+  <entry type="LiteralStringDoc" style="#6e738d"/>
+  <entry type="LiteralStringHeredoc" style="#6e738d"/>
+  <entry type="LiteralNumber" style="#f5a97f"/>
+  <entry type="LiteralNumberBin" style="#f5a97f"/>
+  <entry type="LiteralNumberHex" style="#f5a97f"/>
+  <entry type="LiteralNumberInteger" style="#f5a97f"/>
+  <entry type="LiteralNumberFloat" style="#f5a97f"/>
+  <entry type="LiteralNumberIntegerLong" style="#f5a97f"/>
+  <entry type="LiteralNumberOct" style="#f5a97f"/>
+  <entry type="Operator" style="bold #91d7e3"/>
+  <entry type="OperatorWord" style="bold #91d7e3"/>
+  <entry type="Comment" style="italic #6e738d"/>
+  <entry type="CommentSingle" style="italic #6e738d"/>
+  <entry type="CommentMultiline" style="italic #6e738d"/>
+  <entry type="CommentSpecial" style="italic #6e738d"/>
+  <entry type="CommentHashbang" style="italic #6e738d"/>
+  <entry type="CommentPreproc" style="italic #6e738d"/>
+  <entry type="CommentPreprocFile" style="bold #6e738d"/>
+  <entry type="Generic" style="#cad3f5"/>
+  <entry type="GenericInserted" style="bg:#363a4f #a6da95"/>
+  <entry type="GenericDeleted" style="#ed8796 bg:#363a4f"/>
+  <entry type="GenericEmph" style="italic #cad3f5"/>
+  <entry type="GenericStrong" style="bold #cad3f5"/>
+  <entry type="GenericUnderline" style="underline #cad3f5"/>
+  <entry type="GenericHeading" style="bold #f5a97f"/>
+  <entry type="GenericSubheading" style="bold #f5a97f"/>
+  <entry type="GenericOutput" style="#cad3f5"/>
+  <entry type="GenericPrompt" style="#cad3f5"/>
+  <entry type="GenericError" style="#ed8796"/>
+  <entry type="GenericTraceback" style="#ed8796"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/catppuccin-mocha.xml b/styles/embedded/catppuccin-mocha.xml
new file mode 100644
index 0000000..2ece4e5
--- /dev/null
+++ b/styles/embedded/catppuccin-mocha.xml
@@ -0,0 +1,83 @@
+<style name="catppuccin-mocha" theme="dark">
+  <entry type="Background" style="bg:#1e1e2e #cdd6f4"/>
+  <entry type="CodeLine" style="#cdd6f4"/>
+  <entry type="Error" style="#f38ba8"/>
+  <entry type="Other" style="#cdd6f4"/>
+  <entry type="LineTableTD" style=""/>
+  <entry type="LineTable" style=""/>
+  <entry type="LineHighlight" style="bg:#45475a"/>
+  <entry type="LineNumbersTable" style="#7f849c"/>
+  <entry type="LineNumbers" style="#7f849c"/>
+  <entry type="Keyword" style="#cba6f7"/>
+  <entry type="KeywordReserved" style="#cba6f7"/>
+  <entry type="KeywordPseudo" style="#cba6f7"/>
+  <entry type="KeywordConstant" style="#fab387"/>
+  <entry type="KeywordDeclaration" style="#f38ba8"/>
+  <entry type="KeywordNamespace" style="#94e2d5"/>
+  <entry type="KeywordType" style="#f38ba8"/>
+  <entry type="Name" style="#cdd6f4"/>
+  <entry type="NameClass" style="#f9e2af"/>
+  <entry type="NameConstant" style="#f9e2af"/>
+  <entry type="NameDecorator" style="bold #89b4fa"/>
+  <entry type="NameEntity" style="#94e2d5"/>
+  <entry type="NameException" style="#fab387"/>
+  <entry type="NameFunction" style="#89b4fa"/>
+  <entry type="NameFunctionMagic" style="#89b4fa"/>
+  <entry type="NameLabel" style="#89dceb"/>
+  <entry type="NameNamespace" style="#fab387"/>
+  <entry type="NameProperty" style="#fab387"/>
+  <entry type="NameTag" style="#cba6f7"/>
+  <entry type="NameVariable" style="#f5e0dc"/>
+  <entry type="NameVariableClass" style="#f5e0dc"/>
+  <entry type="NameVariableGlobal" style="#f5e0dc"/>
+  <entry type="NameVariableInstance" style="#f5e0dc"/>
+  <entry type="NameVariableMagic" style="#f5e0dc"/>
+  <entry type="NameAttribute" style="#89b4fa"/>
+  <entry type="NameBuiltin" style="#89dceb"/>
+  <entry type="NameBuiltinPseudo" style="#89dceb"/>
+  <entry type="NameOther" style="#cdd6f4"/>
+  <entry type="Literal" style="#cdd6f4"/>
+  <entry type="LiteralDate" style="#cdd6f4"/>
+  <entry type="LiteralString" style="#a6e3a1"/>
+  <entry type="LiteralStringChar" style="#a6e3a1"/>
+  <entry type="LiteralStringSingle" style="#a6e3a1"/>
+  <entry type="LiteralStringDouble" style="#a6e3a1"/>
+  <entry type="LiteralStringBacktick" style="#a6e3a1"/>
+  <entry type="LiteralStringOther" style="#a6e3a1"/>
+  <entry type="LiteralStringSymbol" style="#a6e3a1"/>
+  <entry type="LiteralStringInterpol" style="#a6e3a1"/>
+  <entry type="LiteralStringAffix" style="#f38ba8"/>
+  <entry type="LiteralStringDelimiter" style="#89b4fa"/>
+  <entry type="LiteralStringEscape" style="#89b4fa"/>
+  <entry type="LiteralStringRegex" style="#94e2d5"/>
+  <entry type="LiteralStringDoc" style="#6c7086"/>
+  <entry type="LiteralStringHeredoc" style="#6c7086"/>
+  <entry type="LiteralNumber" style="#fab387"/>
+  <entry type="LiteralNumberBin" style="#fab387"/>
+  <entry type="LiteralNumberHex" style="#fab387"/>
+  <entry type="LiteralNumberInteger" style="#fab387"/>
+  <entry type="LiteralNumberFloat" style="#fab387"/>
+  <entry type="LiteralNumberIntegerLong" style="#fab387"/>
+  <entry type="LiteralNumberOct" style="#fab387"/>
+  <entry type="Operator" style="bold #89dceb"/>
+  <entry type="OperatorWord" style="bold #89dceb"/>
+  <entry type="Comment" style="italic #6c7086"/>
+  <entry type="CommentSingle" style="italic #6c7086"/>
+  <entry type="CommentMultiline" style="italic #6c7086"/>
+  <entry type="CommentSpecial" style="italic #6c7086"/>
+  <entry type="CommentHashbang" style="italic #6c7086"/>
+  <entry type="CommentPreproc" style="italic #6c7086"/>
+  <entry type="CommentPreprocFile" style="bold #6c7086"/>
+  <entry type="Generic" style="#cdd6f4"/>
+  <entry type="GenericInserted" style="bg:#313244 #a6e3a1"/>
+  <entry type="GenericDeleted" style="#f38ba8 bg:#313244"/>
+  <entry type="GenericEmph" style="italic #cdd6f4"/>
+  <entry type="GenericStrong" style="bold #cdd6f4"/>
+  <entry type="GenericUnderline" style="underline #cdd6f4"/>
+  <entry type="GenericHeading" style="bold #fab387"/>
+  <entry type="GenericSubheading" style="bold #fab387"/>
+  <entry type="GenericOutput" style="#cdd6f4"/>
+  <entry type="GenericPrompt" style="#cdd6f4"/>
+  <entry type="GenericError" style="#f38ba8"/>
+  <entry type="GenericTraceback" style="#f38ba8"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/colorful.xml b/styles/embedded/colorful.xml
new file mode 100644
index 0000000..dc74e09
--- /dev/null
+++ b/styles/embedded/colorful.xml
@@ -0,0 +1,52 @@
+<style name="colorful" theme="light">
+  <entry type="Error" style="#ff0000 bg:#ffaaaa"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="bold #008800"/>
+  <entry type="KeywordPseudo" style="#003388"/>
+  <entry type="KeywordType" style="#333399"/>
+  <entry type="NameAttribute" style="#0000cc"/>
+  <entry type="NameBuiltin" style="#007020"/>
+  <entry type="NameClass" style="bold #bb0066"/>
+  <entry type="NameConstant" style="bold #003366"/>
+  <entry type="NameDecorator" style="bold #555555"/>
+  <entry type="NameEntity" style="bold #880000"/>
+  <entry type="NameException" style="bold #ff0000"/>
+  <entry type="NameFunction" style="bold #0066bb"/>
+  <entry type="NameLabel" style="bold #997700"/>
+  <entry type="NameNamespace" style="bold #0e84b5"/>
+  <entry type="NameTag" style="#007700"/>
+  <entry type="NameVariable" style="#996633"/>
+  <entry type="NameVariableClass" style="#336699"/>
+  <entry type="NameVariableGlobal" style="bold #dd7700"/>
+  <entry type="NameVariableInstance" style="#3333bb"/>
+  <entry type="LiteralString" style="bg:#fff0f0"/>
+  <entry type="LiteralStringChar" style="#0044dd"/>
+  <entry type="LiteralStringDoc" style="#dd4422"/>
+  <entry type="LiteralStringEscape" style="bold #666666"/>
+  <entry type="LiteralStringInterpol" style="bg:#eeeeee"/>
+  <entry type="LiteralStringOther" style="#dd2200"/>
+  <entry type="LiteralStringRegex" style="#000000 bg:#fff0ff"/>
+  <entry type="LiteralStringSymbol" style="#aa6600"/>
+  <entry type="LiteralNumber" style="bold #6600ee"/>
+  <entry type="LiteralNumberFloat" style="bold #6600ee"/>
+  <entry type="LiteralNumberHex" style="bold #005588"/>
+  <entry type="LiteralNumberInteger" style="bold #0000dd"/>
+  <entry type="LiteralNumberOct" style="bold #4400ee"/>
+  <entry type="Operator" style="#333333"/>
+  <entry type="OperatorWord" style="bold #000000"/>
+  <entry type="Comment" style="#888888"/>
+  <entry type="CommentSpecial" style="bold #cc0000"/>
+  <entry type="CommentPreproc" style="#557799"/>
+  <entry type="GenericDeleted" style="#a00000"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#ff0000"/>
+  <entry type="GenericHeading" style="bold #000080"/>
+  <entry type="GenericInserted" style="#00a000"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="bold #c65d09"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #800080"/>
+  <entry type="GenericTraceback" style="#0044dd"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/doom-one.xml b/styles/embedded/doom-one.xml
new file mode 100644
index 0000000..f5a910a
--- /dev/null
+++ b/styles/embedded/doom-one.xml
@@ -0,0 +1,51 @@
+<style name="doom-one" theme="dark">
+  <entry type="Error" style="#b0c4de"/>
+  <entry type="Background" style="#b0c4de bg:#282c34"/>
+  <entry type="Keyword" style="#c678dd"/>
+  <entry type="KeywordConstant" style="bold #b756ff"/>
+  <entry type="KeywordType" style="#ef8383"/>
+  <entry type="Name" style="#c1abea"/>
+  <entry type="NameAttribute" style="#b3d23c"/>
+  <entry type="NameBuiltin" style="#ef8383"/>
+  <entry type="NameClass" style="#76a9f9"/>
+  <entry type="NameConstant" style="bold #b756ff"/>
+  <entry type="NameDecorator" style="#e5c07b"/>
+  <entry type="NameEntity" style="#bda26f"/>
+  <entry type="NameException" style="bold #fd7474"/>
+  <entry type="NameFunction" style="#00b1f7"/>
+  <entry type="NameLabel" style="#f5a40d"/>
+  <entry type="NameNamespace" style="#76a9f9"/>
+  <entry type="NameProperty" style="#cebc3a"/>
+  <entry type="NameTag" style="#e06c75"/>
+  <entry type="NameVariable" style="#dcaeea"/>
+  <entry type="NameVariableGlobal" style="bold #dcaeea"/>
+  <entry type="NameVariableInstance" style="#e06c75"/>
+  <entry type="Literal" style="#98c379"/>
+  <entry type="LiteralString" style="#98c379"/>
+  <entry type="LiteralStringDoc" style="#7e97c3"/>
+  <entry type="LiteralStringDouble" style="#63c381"/>
+  <entry type="LiteralStringEscape" style="bold #d26464"/>
+  <entry type="LiteralStringHeredoc" style="#98c379"/>
+  <entry type="LiteralStringInterpol" style="#98c379"/>
+  <entry type="LiteralStringOther" style="#70b33f"/>
+  <entry type="LiteralStringRegex" style="#56b6c2"/>
+  <entry type="LiteralStringSingle" style="#98c379"/>
+  <entry type="LiteralStringSymbol" style="#56b6c2"/>
+  <entry type="LiteralNumber" style="#d19a66"/>
+  <entry type="Operator" style="#c7bf54"/>
+  <entry type="OperatorWord" style="bold #b756ff"/>
+  <entry type="Punctuation" style="#b0c4de"/>
+  <entry type="Comment" style="italic #8a93a5"/>
+  <entry type="CommentHashbang" style="bold"/>
+  <entry type="Generic" style="#b0c4de"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericHeading" style="bold #a2cbff"/>
+  <entry type="GenericInserted" style="#a6e22e"/>
+  <entry type="GenericOutput" style="#a6e22e"/>
+  <entry type="GenericPrompt" style="#a6e22e"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#a2cbff"/>
+  <entry type="GenericTraceback" style="#a2cbff"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="Text" style="#b0c4de"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/doom-one2.xml b/styles/embedded/doom-one2.xml
new file mode 100644
index 0000000..d6863f3
--- /dev/null
+++ b/styles/embedded/doom-one2.xml
@@ -0,0 +1,64 @@
+<style name="doom-one2" theme="dark">
+  <entry type="Error" style="#b0c4de"/>
+  <entry type="Background" style="#b0c4de bg:#282c34"/>
+  <entry type="Keyword" style="#76a9f9"/>
+  <entry type="KeywordConstant" style="#e5c07b"/>
+  <entry type="KeywordType" style="#e5c07b"/>
+  <entry type="Name" style="#aa89ea"/>
+  <entry type="NameAttribute" style="#cebc3a"/>
+  <entry type="NameBuiltin" style="#e5c07b"/>
+  <entry type="NameClass" style="#ca72ff"/>
+  <entry type="NameConstant" style="bold"/>
+  <entry type="NameDecorator" style="#e5c07b"/>
+  <entry type="NameEntity" style="#bda26f"/>
+  <entry type="NameException" style="bold #fd7474"/>
+  <entry type="NameFunction" style="#00b1f7"/>
+  <entry type="NameLabel" style="#f5a40d"/>
+  <entry type="NameNamespace" style="#ca72ff"/>
+  <entry type="NameProperty" style="#cebc3a"/>
+  <entry type="NameTag" style="#76a9f9"/>
+  <entry type="NameVariable" style="#dcaeea"/>
+  <entry type="NameVariableClass" style="#dcaeea"/>
+  <entry type="NameVariableGlobal" style="bold #dcaeea"/>
+  <entry type="NameVariableInstance" style="#e06c75"/>
+  <entry type="NameVariableMagic" style="#dcaeea"/>
+  <entry type="Literal" style="#98c379"/>
+  <entry type="LiteralDate" style="#98c379"/>
+  <entry type="LiteralString" style="#98c379"/>
+  <entry type="LiteralStringAffix" style="#98c379"/>
+  <entry type="LiteralStringBacktick" style="#98c379"/>
+  <entry type="LiteralStringDelimiter" style="#98c379"/>
+  <entry type="LiteralStringDoc" style="#7e97c3"/>
+  <entry type="LiteralStringDouble" style="#63c381"/>
+  <entry type="LiteralStringEscape" style="bold #d26464"/>
+  <entry type="LiteralStringHeredoc" style="#98c379"/>
+  <entry type="LiteralStringInterpol" style="#98c379"/>
+  <entry type="LiteralStringOther" style="#70b33f"/>
+  <entry type="LiteralStringRegex" style="#56b6c2"/>
+  <entry type="LiteralStringSingle" style="#98c379"/>
+  <entry type="LiteralStringSymbol" style="#56b6c2"/>
+  <entry type="LiteralNumber" style="#d19a66"/>
+  <entry type="LiteralNumberBin" style="#d19a66"/>
+  <entry type="LiteralNumberFloat" style="#d19a66"/>
+  <entry type="LiteralNumberHex" style="#d19a66"/>
+  <entry type="LiteralNumberInteger" style="#d19a66"/>
+  <entry type="LiteralNumberIntegerLong" style="#d19a66"/>
+  <entry type="LiteralNumberOct" style="#d19a66"/>
+  <entry type="Operator" style="#54b1c7"/>
+  <entry type="OperatorWord" style="bold #b756ff"/>
+  <entry type="Punctuation" style="#abb2bf"/>
+  <entry type="Comment" style="italic #8a93a5"/>
+  <entry type="CommentHashbang" style="bold"/>
+  <entry type="Generic" style="#b0c4de"/>
+  <entry type="GenericDeleted" style="#b0c4de"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericHeading" style="bold #a2cbff"/>
+  <entry type="GenericInserted" style="#a6e22e"/>
+  <entry type="GenericOutput" style="#a6e22e"/>
+  <entry type="GenericPrompt" style="#a6e22e"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#a2cbff"/>
+  <entry type="GenericTraceback" style="#a2cbff"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="Text" style="#b0c4de"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/dracula.xml b/styles/embedded/dracula.xml
new file mode 100644
index 0000000..da436b3
--- /dev/null
+++ b/styles/embedded/dracula.xml
@@ -0,0 +1,74 @@
+<style name="dracula" theme="dark">
+  <entry type="Other" style="#f8f8f2"/>
+  <entry type="Error" style="#f8f8f2"/>
+  <entry type="Background" style="bg:#282a36"/>
+  <entry type="Keyword" style="#ff79c6"/>
+  <entry type="KeywordConstant" style="#ff79c6"/>
+  <entry type="KeywordDeclaration" style="italic #8be9fd"/>
+  <entry type="KeywordNamespace" style="#ff79c6"/>
+  <entry type="KeywordPseudo" style="#ff79c6"/>
+  <entry type="KeywordReserved" style="#ff79c6"/>
+  <entry type="KeywordType" style="#8be9fd"/>
+  <entry type="Name" style="#f8f8f2"/>
+  <entry type="NameAttribute" style="#50fa7b"/>
+  <entry type="NameBuiltin" style="italic #8be9fd"/>
+  <entry type="NameBuiltinPseudo" style="#f8f8f2"/>
+  <entry type="NameClass" style="#50fa7b"/>
+  <entry type="NameConstant" style="#f8f8f2"/>
+  <entry type="NameDecorator" style="#f8f8f2"/>
+  <entry type="NameEntity" style="#f8f8f2"/>
+  <entry type="NameException" style="#f8f8f2"/>
+  <entry type="NameFunction" style="#50fa7b"/>
+  <entry type="NameLabel" style="italic #8be9fd"/>
+  <entry type="NameNamespace" style="#f8f8f2"/>
+  <entry type="NameOther" style="#f8f8f2"/>
+  <entry type="NameTag" style="#ff79c6"/>
+  <entry type="NameVariable" style="italic #8be9fd"/>
+  <entry type="NameVariableClass" style="italic #8be9fd"/>
+  <entry type="NameVariableGlobal" style="italic #8be9fd"/>
+  <entry type="NameVariableInstance" style="italic #8be9fd"/>
+  <entry type="Literal" style="#f8f8f2"/>
+  <entry type="LiteralDate" style="#f8f8f2"/>
+  <entry type="LiteralString" style="#f1fa8c"/>
+  <entry type="LiteralStringBacktick" style="#f1fa8c"/>
+  <entry type="LiteralStringChar" style="#f1fa8c"/>
+  <entry type="LiteralStringDoc" style="#f1fa8c"/>
+  <entry type="LiteralStringDouble" style="#f1fa8c"/>
+  <entry type="LiteralStringEscape" style="#f1fa8c"/>
+  <entry type="LiteralStringHeredoc" style="#f1fa8c"/>
+  <entry type="LiteralStringInterpol" style="#f1fa8c"/>
+  <entry type="LiteralStringOther" style="#f1fa8c"/>
+  <entry type="LiteralStringRegex" style="#f1fa8c"/>
+  <entry type="LiteralStringSingle" style="#f1fa8c"/>
+  <entry type="LiteralStringSymbol" style="#f1fa8c"/>
+  <entry type="LiteralNumber" style="#bd93f9"/>
+  <entry type="LiteralNumberBin" style="#bd93f9"/>
+  <entry type="LiteralNumberFloat" style="#bd93f9"/>
+  <entry type="LiteralNumberHex" style="#bd93f9"/>
+  <entry type="LiteralNumberInteger" style="#bd93f9"/>
+  <entry type="LiteralNumberIntegerLong" style="#bd93f9"/>
+  <entry type="LiteralNumberOct" style="#bd93f9"/>
+  <entry type="Operator" style="#ff79c6"/>
+  <entry type="OperatorWord" style="#ff79c6"/>
+  <entry type="Punctuation" style="#f8f8f2"/>
+  <entry type="Comment" style="#6272a4"/>
+  <entry type="CommentHashbang" style="#6272a4"/>
+  <entry type="CommentMultiline" style="#6272a4"/>
+  <entry type="CommentSingle" style="#6272a4"/>
+  <entry type="CommentSpecial" style="#6272a4"/>
+  <entry type="CommentPreproc" style="#ff79c6"/>
+  <entry type="Generic" style="#f8f8f2"/>
+  <entry type="GenericDeleted" style="#ff5555"/>
+  <entry type="GenericEmph" style="underline #f8f8f2"/>
+  <entry type="GenericError" style="#f8f8f2"/>
+  <entry type="GenericHeading" style="bold #f8f8f2"/>
+  <entry type="GenericInserted" style="bold #50fa7b"/>
+  <entry type="GenericOutput" style="#44475a"/>
+  <entry type="GenericPrompt" style="#f8f8f2"/>
+  <entry type="GenericStrong" style="#f8f8f2"/>
+  <entry type="GenericSubheading" style="bold #f8f8f2"/>
+  <entry type="GenericTraceback" style="#f8f8f2"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="Text" style="#f8f8f2"/>
+  <entry type="TextWhitespace" style="#f8f8f2"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/emacs.xml b/styles/embedded/emacs.xml
new file mode 100644
index 0000000..dd276f2
--- /dev/null
+++ b/styles/embedded/emacs.xml
@@ -0,0 +1,44 @@
+<style name="emacs" theme="light">
+  <entry type="Error" style="border:#ff0000"/>
+  <entry type="Background" style="bg:#f8f8f8"/>
+  <entry type="Keyword" style="bold #aa22ff"/>
+  <entry type="KeywordPseudo" style="nobold"/>
+  <entry type="KeywordType" style="bold #00bb00"/>
+  <entry type="NameAttribute" style="#bb4444"/>
+  <entry type="NameBuiltin" style="#aa22ff"/>
+  <entry type="NameClass" style="#0000ff"/>
+  <entry type="NameConstant" style="#880000"/>
+  <entry type="NameDecorator" style="#aa22ff"/>
+  <entry type="NameEntity" style="bold #999999"/>
+  <entry type="NameException" style="bold #d2413a"/>
+  <entry type="NameFunction" style="#00a000"/>
+  <entry type="NameLabel" style="#a0a000"/>
+  <entry type="NameNamespace" style="bold #0000ff"/>
+  <entry type="NameTag" style="bold #008000"/>
+  <entry type="NameVariable" style="#b8860b"/>
+  <entry type="LiteralString" style="#bb4444"/>
+  <entry type="LiteralStringDoc" style="italic"/>
+  <entry type="LiteralStringEscape" style="bold #bb6622"/>
+  <entry type="LiteralStringInterpol" style="bold #bb6688"/>
+  <entry type="LiteralStringOther" style="#008000"/>
+  <entry type="LiteralStringRegex" style="#bb6688"/>
+  <entry type="LiteralStringSymbol" style="#b8860b"/>
+  <entry type="LiteralNumber" style="#666666"/>
+  <entry type="Operator" style="#666666"/>
+  <entry type="OperatorWord" style="bold #aa22ff"/>
+  <entry type="Comment" style="italic #008800"/>
+  <entry type="CommentSpecial" style="bold noitalic"/>
+  <entry type="CommentPreproc" style="noitalic"/>
+  <entry type="GenericDeleted" style="#a00000"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#ff0000"/>
+  <entry type="GenericHeading" style="bold #000080"/>
+  <entry type="GenericInserted" style="#00a000"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="bold #000080"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #800080"/>
+  <entry type="GenericTraceback" style="#0044dd"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/evergarden.xml b/styles/embedded/evergarden.xml
new file mode 100644
index 0000000..826435d
--- /dev/null
+++ b/styles/embedded/evergarden.xml
@@ -0,0 +1,33 @@
+<style name="evergarden" theme="dark">
+  <entry type="Background" style="noinherit #D6CBB4 bg:#252B2E"/>
+  <entry type="Keyword" style="noinherit #E67E80"/>
+  <entry type="KeywordType" style="noinherit #DBBC7F"/>
+  <entry type="Name" style="#D6CBB4"/>
+  <entry type="NameAttribute" style="bold #D699B6"/>
+  <entry type="NameBuiltin" style="#D699B6"/>
+  <entry type="NameConstant" style="noinherit #D699B6"/>
+  <entry type="NameEntity" style="noinherit #DBBC7F"/>
+  <entry type="NameException" style="noinherit #E67E80"/>
+  <entry type="NameFunction" style="#B2C98F"/>
+  <entry type="NameLabel" style="noinherit #E67E80"/>
+  <entry type="NameTag" style="noinherit #7a8478"/>
+  <entry type="NameVariable" style="noinherit #D6CBB4"/>
+  <entry type="LiteralString" style="noinherit #B2C98F"/>
+  <entry type="LiteralStringSymbol" style="#E69875"/>
+  <entry type="LiteralNumber" style="noinherit #D699B6"/>
+  <entry type="LiteralNumberFloat" style="noinherit #D699B6"/>
+  <entry type="Operator" style="#7a8478"/>
+  <entry type="Comment" style="italic #859289"/>
+  <entry type="CommentPreproc" style="noinherit #E67E80"/>
+  <entry type="Generic" style="#D6CBB4"/>
+  <entry type="GenericDeleted" style="noinherit #252B2E bg:#E67E80"/>
+  <entry type="GenericEmph" style="#6E8585"/>
+  <entry type="GenericError" style="bold bg:#E67E80"/>
+  <entry type="GenericHeading" style="bold #D699B6"/>
+  <entry type="GenericInserted" style="noinherit #252B2E bg:#B2C98F"/>
+  <entry type="GenericOutput" style="noinherit #6E8585"/>
+  <entry type="GenericPrompt" style="#D6CBB4"/>
+  <entry type="GenericStrong" style="#D6CBB4"/>
+  <entry type="GenericSubheading" style="bold #B2C98F"/>
+  <entry type="GenericTraceback" style="bold bg:#E67E80"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/friendly.xml b/styles/embedded/friendly.xml
new file mode 100644
index 0000000..cd583c2
--- /dev/null
+++ b/styles/embedded/friendly.xml
@@ -0,0 +1,44 @@
+<style name="friendly" theme="light">
+  <entry type="Error" style="border:#ff0000"/>
+  <entry type="Background" style="bg:#f0f0f0"/>
+  <entry type="Keyword" style="bold #007020"/>
+  <entry type="KeywordPseudo" style="nobold"/>
+  <entry type="KeywordType" style="nobold #902000"/>
+  <entry type="NameAttribute" style="#4070a0"/>
+  <entry type="NameBuiltin" style="#007020"/>
+  <entry type="NameClass" style="bold #0e84b5"/>
+  <entry type="NameConstant" style="#60add5"/>
+  <entry type="NameDecorator" style="bold #555555"/>
+  <entry type="NameEntity" style="bold #d55537"/>
+  <entry type="NameException" style="#007020"/>
+  <entry type="NameFunction" style="#06287e"/>
+  <entry type="NameLabel" style="bold #002070"/>
+  <entry type="NameNamespace" style="bold #0e84b5"/>
+  <entry type="NameTag" style="bold #062873"/>
+  <entry type="NameVariable" style="#bb60d5"/>
+  <entry type="LiteralString" style="#4070a0"/>
+  <entry type="LiteralStringDoc" style="italic"/>
+  <entry type="LiteralStringEscape" style="bold #4070a0"/>
+  <entry type="LiteralStringInterpol" style="#70a0d0"/>
+  <entry type="LiteralStringOther" style="#c65d09"/>
+  <entry type="LiteralStringRegex" style="#235388"/>
+  <entry type="LiteralStringSymbol" style="#517918"/>
+  <entry type="LiteralNumber" style="#40a070"/>
+  <entry type="Operator" style="#666666"/>
+  <entry type="OperatorWord" style="bold #007020"/>
+  <entry type="Comment" style="italic #60a0b0"/>
+  <entry type="CommentSpecial" style="noitalic bg:#fff0f0"/>
+  <entry type="CommentPreproc" style="noitalic #007020"/>
+  <entry type="GenericDeleted" style="#a00000"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#ff0000"/>
+  <entry type="GenericHeading" style="bold #000080"/>
+  <entry type="GenericInserted" style="#00a000"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="bold #c65d09"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #800080"/>
+  <entry type="GenericTraceback" style="#0044dd"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/fruity.xml b/styles/embedded/fruity.xml
new file mode 100644
index 0000000..00b048d
--- /dev/null
+++ b/styles/embedded/fruity.xml
@@ -0,0 +1,19 @@
+<style name="fruity" theme="dark">
+  <entry type="Background" style="#ffffff bg:#111111"/>
+  <entry type="Keyword" style="bold #fb660a"/>
+  <entry type="KeywordPseudo" style="nobold"/>
+  <entry type="KeywordType" style="bold #cdcaa9"/>
+  <entry type="NameAttribute" style="bold #ff0086"/>
+  <entry type="NameConstant" style="#0086d2"/>
+  <entry type="NameFunction" style="bold #ff0086"/>
+  <entry type="NameTag" style="bold #fb660a"/>
+  <entry type="NameVariable" style="#fb660a"/>
+  <entry type="LiteralString" style="#0086d2"/>
+  <entry type="LiteralNumber" style="bold #0086f7"/>
+  <entry type="Comment" style="italic #008800 bg:#0f140f"/>
+  <entry type="CommentPreproc" style="bold #ff0007"/>
+  <entry type="GenericHeading" style="bold #ffffff"/>
+  <entry type="GenericOutput" style="#444444 bg:#222222"/>
+  <entry type="GenericSubheading" style="bold #ffffff"/>
+  <entry type="TextWhitespace" style="#888888"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/github-dark.xml b/styles/embedded/github-dark.xml
new file mode 100644
index 0000000..85b3fc9
--- /dev/null
+++ b/styles/embedded/github-dark.xml
@@ -0,0 +1,45 @@
+<style name="github-dark" theme="dark">
+  <entry type="Error" style="#f85149"/>
+  <entry type="LineHighlight" style="bg:#6e7681"/>
+  <entry type="LineNumbers" style="#6e7681"/>
+  <entry type="Background" style="#e6edf3 bg:#0d1117"/>
+  <entry type="Keyword" style="#ff7b72"/>
+  <entry type="KeywordConstant" style="#79c0ff"/>
+  <entry type="KeywordPseudo" style="#79c0ff"/>
+  <entry type="Name" style="#e6edf3"/>
+  <entry type="NameClass" style="bold #f0883e"/>
+  <entry type="NameConstant" style="bold #79c0ff"/>
+  <entry type="NameDecorator" style="bold #d2a8ff"/>
+  <entry type="NameEntity" style="#ffa657"/>
+  <entry type="NameException" style="bold #f0883e"/>
+  <entry type="NameFunction" style="bold #d2a8ff"/>
+  <entry type="NameLabel" style="bold #79c0ff"/>
+  <entry type="NameNamespace" style="#ff7b72"/>
+  <entry type="NameProperty" style="#79c0ff"/>
+  <entry type="NameTag" style="#7ee787"/>
+  <entry type="NameVariable" style="#79c0ff"/>
+  <entry type="Literal" style="#a5d6ff"/>
+  <entry type="LiteralDate" style="#79c0ff"/>
+  <entry type="LiteralStringAffix" style="#79c0ff"/>
+  <entry type="LiteralStringDelimiter" style="#79c0ff"/>
+  <entry type="LiteralStringEscape" style="#79c0ff"/>
+  <entry type="LiteralStringHeredoc" style="#79c0ff"/>
+  <entry type="LiteralStringRegex" style="#79c0ff"/>
+  <entry type="Operator" style="bold #ff7b72"/>
+  <entry type="Comment" style="italic #8b949e"/>
+  <entry type="CommentSpecial" style="bold italic #8b949e"/>
+  <entry type="CommentPreproc" style="bold #8b949e"/>
+  <entry type="Generic" style="#e6edf3"/>
+  <entry type="GenericDeleted" style="#ffa198 bg:#490202"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#ffa198"/>
+  <entry type="GenericHeading" style="bold #79c0ff"/>
+  <entry type="GenericInserted" style="#56d364 bg:#0f5323"/>
+  <entry type="GenericOutput" style="#8b949e"/>
+  <entry type="GenericPrompt" style="#8b949e"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#79c0ff"/>
+  <entry type="GenericTraceback" style="#ff7b72"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#6e7681"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/github.xml b/styles/embedded/github.xml
new file mode 100644
index 0000000..06e043a
--- /dev/null
+++ b/styles/embedded/github.xml
@@ -0,0 +1,44 @@
+<style name="github" theme="light">
+  <entry type="Error" style="#a61717 bg:#e3d2d2"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="bold #000000"/>
+  <entry type="KeywordType" style="bold #445588"/>
+  <entry type="NameAttribute" style="#008080"/>
+  <entry type="NameBuiltin" style="#0086b3"/>
+  <entry type="NameBuiltinPseudo" style="#999999"/>
+  <entry type="NameClass" style="bold #445588"/>
+  <entry type="NameConstant" style="#008080"/>
+  <entry type="NameDecorator" style="bold #3c5d5d"/>
+  <entry type="NameEntity" style="#800080"/>
+  <entry type="NameException" style="bold #990000"/>
+  <entry type="NameFunction" style="bold #990000"/>
+  <entry type="NameLabel" style="bold #990000"/>
+  <entry type="NameNamespace" style="#555555"/>
+  <entry type="NameTag" style="#000080"/>
+  <entry type="NameVariable" style="#008080"/>
+  <entry type="NameVariableClass" style="#008080"/>
+  <entry type="NameVariableGlobal" style="#008080"/>
+  <entry type="NameVariableInstance" style="#008080"/>
+  <entry type="LiteralString" style="#dd1144"/>
+  <entry type="LiteralStringRegex" style="#009926"/>
+  <entry type="LiteralStringSymbol" style="#990073"/>
+  <entry type="LiteralNumber" style="#009999"/>
+  <entry type="Operator" style="bold #000000"/>
+  <entry type="Comment" style="italic #999988"/>
+  <entry type="CommentMultiline" style="italic #999988"/>
+  <entry type="CommentSingle" style="italic #999988"/>
+  <entry type="CommentSpecial" style="bold italic #999999"/>
+  <entry type="CommentPreproc" style="bold #999999"/>
+  <entry type="GenericDeleted" style="#000000 bg:#ffdddd"/>
+  <entry type="GenericEmph" style="italic #000000"/>
+  <entry type="GenericError" style="#aa0000"/>
+  <entry type="GenericHeading" style="#999999"/>
+  <entry type="GenericInserted" style="#000000 bg:#ddffdd"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="#555555"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#aaaaaa"/>
+  <entry type="GenericTraceback" style="#aa0000"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/gruvbox-light.xml b/styles/embedded/gruvbox-light.xml
new file mode 100644
index 0000000..c1293c8
--- /dev/null
+++ b/styles/embedded/gruvbox-light.xml
@@ -0,0 +1,33 @@
+<style name="gruvbox-light" theme="light">
+  <entry type="Background" style="noinherit #3c3836 bg:#fbf1c7"/>
+  <entry type="Keyword" style="noinherit #af3a03"/>
+  <entry type="KeywordType" style="noinherit #b57614"/>
+  <entry type="Name" style="#3c3836"/>
+  <entry type="NameAttribute" style="bold #79740e"/>
+  <entry type="NameBuiltin" style="#b57614"/>
+  <entry type="NameConstant" style="noinherit #d3869b"/>
+  <entry type="NameEntity" style="noinherit #b57614"/>
+  <entry type="NameException" style="noinherit #fb4934"/>
+  <entry type="NameFunction" style="#b57614"/>
+  <entry type="NameLabel" style="noinherit #9d0006"/>
+  <entry type="NameTag" style="noinherit #9d0006"/>
+  <entry type="NameVariable" style="noinherit #3c3836"/>
+  <entry type="LiteralString" style="noinherit #79740e"/>
+  <entry type="LiteralStringSymbol" style="#076678"/>
+  <entry type="LiteralNumber" style="noinherit #8f3f71"/>
+  <entry type="LiteralNumberFloat" style="noinherit #8f3f71"/>
+  <entry type="Operator" style="#af3a03"/>
+  <entry type="Comment" style="italic #928374"/>
+  <entry type="CommentPreproc" style="noinherit #427b58"/>
+  <entry type="Generic" style="#3c3836"/>
+  <entry type="GenericDeleted" style="noinherit #282828 bg:#9d0006"/>
+  <entry type="GenericEmph" style="underline #076678"/>
+  <entry type="GenericError" style="bold bg:#9d0006"/>
+  <entry type="GenericHeading" style="bold #79740e"/>
+  <entry type="GenericInserted" style="noinherit #282828 bg:#79740e"/>
+  <entry type="GenericOutput" style="noinherit #504945"/>
+  <entry type="GenericPrompt" style="#3c3836"/>
+  <entry type="GenericStrong" style="#3c3836"/>
+  <entry type="GenericSubheading" style="bold #79740e"/>
+  <entry type="GenericTraceback" style="bold bg:#3c3836"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/gruvbox.xml b/styles/embedded/gruvbox.xml
new file mode 100644
index 0000000..9cb974d
--- /dev/null
+++ b/styles/embedded/gruvbox.xml
@@ -0,0 +1,33 @@
+<style name="gruvbox" theme="dark">
+  <entry type="Background" style="noinherit #ebdbb2 bg:#282828"/>
+  <entry type="Keyword" style="noinherit #fe8019"/>
+  <entry type="KeywordType" style="noinherit #fabd2f"/>
+  <entry type="Name" style="#ebdbb2"/>
+  <entry type="NameAttribute" style="bold #b8bb26"/>
+  <entry type="NameBuiltin" style="#fabd2f"/>
+  <entry type="NameConstant" style="noinherit #d3869b"/>
+  <entry type="NameEntity" style="noinherit #fabd2f"/>
+  <entry type="NameException" style="noinherit #fb4934"/>
+  <entry type="NameFunction" style="#fabd2f"/>
+  <entry type="NameLabel" style="noinherit #fb4934"/>
+  <entry type="NameTag" style="noinherit #fb4934"/>
+  <entry type="NameVariable" style="noinherit #ebdbb2"/>
+  <entry type="LiteralString" style="noinherit #b8bb26"/>
+  <entry type="LiteralStringSymbol" style="#83a598"/>
+  <entry type="LiteralNumber" style="noinherit #d3869b"/>
+  <entry type="LiteralNumberFloat" style="noinherit #d3869b"/>
+  <entry type="Operator" style="#fe8019"/>
+  <entry type="Comment" style="italic #928374"/>
+  <entry type="CommentPreproc" style="noinherit #8ec07c"/>
+  <entry type="Generic" style="#ebdbb2"/>
+  <entry type="GenericDeleted" style="noinherit #282828 bg:#fb4934"/>
+  <entry type="GenericEmph" style="underline #83a598"/>
+  <entry type="GenericError" style="bold bg:#fb4934"/>
+  <entry type="GenericHeading" style="bold #b8bb26"/>
+  <entry type="GenericInserted" style="noinherit #282828 bg:#b8bb26"/>
+  <entry type="GenericOutput" style="noinherit #504945"/>
+  <entry type="GenericPrompt" style="#ebdbb2"/>
+  <entry type="GenericStrong" style="#ebdbb2"/>
+  <entry type="GenericSubheading" style="bold #b8bb26"/>
+  <entry type="GenericTraceback" style="bold bg:#fb4934"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/hr_high_contrast.xml b/styles/embedded/hr_high_contrast.xml
new file mode 100644
index 0000000..811d5eb
--- /dev/null
+++ b/styles/embedded/hr_high_contrast.xml
@@ -0,0 +1,12 @@
+<style name="hr_high_contrast" theme="light">
+  <entry type="Other" style="#d5d500"/>
+  <entry type="Background" style="#000000"/>
+  <entry type="Keyword" style="#467faf"/>
+  <entry type="Name" style="#ffffff"/>
+  <entry type="LiteralString" style="#a87662"/>
+  <entry type="LiteralStringBoolean" style="#467faf"/>
+  <entry type="LiteralNumber" style="#ffffff"/>
+  <entry type="Operator" style="#e4e400"/>
+  <entry type="OperatorWord" style="#467faf"/>
+  <entry type="Comment" style="#5a8349"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/hrdark.xml b/styles/embedded/hrdark.xml
new file mode 100644
index 0000000..418e713
--- /dev/null
+++ b/styles/embedded/hrdark.xml
@@ -0,0 +1,10 @@
+<style name="hrdark" theme="light">
+  <entry type="Other" style="#ffffff"/>
+  <entry type="Background" style="#1d2432"/>
+  <entry type="Keyword" style="#ff636f"/>
+  <entry type="Name" style="#58a1dd"/>
+  <entry type="Literal" style="#a6be9d"/>
+  <entry type="Operator" style="#ff636f"/>
+  <entry type="OperatorWord" style="#ff636f"/>
+  <entry type="Comment" style="italic #828b96"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/igor.xml b/styles/embedded/igor.xml
new file mode 100644
index 0000000..6957562
--- /dev/null
+++ b/styles/embedded/igor.xml
@@ -0,0 +1,9 @@
+<style name="igor" theme="light">
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="#0000ff"/>
+  <entry type="NameClass" style="#007575"/>
+  <entry type="NameDecorator" style="#cc00a3"/>
+  <entry type="NameFunction" style="#c34e00"/>
+  <entry type="LiteralString" style="#009c00"/>
+  <entry type="Comment" style="italic #ff0000"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/lovelace.xml b/styles/embedded/lovelace.xml
new file mode 100644
index 0000000..d4f9954
--- /dev/null
+++ b/styles/embedded/lovelace.xml
@@ -0,0 +1,53 @@
+<style name="lovelace" theme="light">
+  <entry type="Error" style="bg:#a848a8"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="#2838b0"/>
+  <entry type="KeywordConstant" style="italic #444444"/>
+  <entry type="KeywordDeclaration" style="italic"/>
+  <entry type="KeywordType" style="italic"/>
+  <entry type="NameAttribute" style="#388038"/>
+  <entry type="NameBuiltin" style="#388038"/>
+  <entry type="NameBuiltinPseudo" style="italic"/>
+  <entry type="NameClass" style="#287088"/>
+  <entry type="NameConstant" style="#b85820"/>
+  <entry type="NameDecorator" style="#287088"/>
+  <entry type="NameEntity" style="#709030"/>
+  <entry type="NameException" style="#908828"/>
+  <entry type="NameFunction" style="#785840"/>
+  <entry type="NameFunctionMagic" style="#b85820"/>
+  <entry type="NameLabel" style="#289870"/>
+  <entry type="NameNamespace" style="#289870"/>
+  <entry type="NameTag" style="#2838b0"/>
+  <entry type="NameVariable" style="#b04040"/>
+  <entry type="NameVariableGlobal" style="#908828"/>
+  <entry type="NameVariableMagic" style="#b85820"/>
+  <entry type="LiteralString" style="#b83838"/>
+  <entry type="LiteralStringAffix" style="#444444"/>
+  <entry type="LiteralStringChar" style="#a848a8"/>
+  <entry type="LiteralStringDelimiter" style="#b85820"/>
+  <entry type="LiteralStringDoc" style="italic #b85820"/>
+  <entry type="LiteralStringEscape" style="#709030"/>
+  <entry type="LiteralStringInterpol" style="underline"/>
+  <entry type="LiteralStringOther" style="#a848a8"/>
+  <entry type="LiteralStringRegex" style="#a848a8"/>
+  <entry type="LiteralNumber" style="#444444"/>
+  <entry type="Operator" style="#666666"/>
+  <entry type="OperatorWord" style="#a848a8"/>
+  <entry type="Punctuation" style="#888888"/>
+  <entry type="Comment" style="italic #888888"/>
+  <entry type="CommentHashbang" style="#287088"/>
+  <entry type="CommentMultiline" style="#888888"/>
+  <entry type="CommentPreproc" style="noitalic #289870"/>
+  <entry type="GenericDeleted" style="#c02828"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#c02828"/>
+  <entry type="GenericHeading" style="#666666"/>
+  <entry type="GenericInserted" style="#388038"/>
+  <entry type="GenericOutput" style="#666666"/>
+  <entry type="GenericPrompt" style="#444444"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#444444"/>
+  <entry type="GenericTraceback" style="#2838b0"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#a89028"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/manni.xml b/styles/embedded/manni.xml
new file mode 100644
index 0000000..b1c5f88
--- /dev/null
+++ b/styles/embedded/manni.xml
@@ -0,0 +1,44 @@
+<style name="manni" theme="light">
+  <entry type="Error" style="#aa0000 bg:#ffaaaa"/>
+  <entry type="Background" style="bg:#f0f3f3"/>
+  <entry type="Keyword" style="bold #006699"/>
+  <entry type="KeywordPseudo" style="nobold"/>
+  <entry type="KeywordType" style="#007788"/>
+  <entry type="NameAttribute" style="#330099"/>
+  <entry type="NameBuiltin" style="#336666"/>
+  <entry type="NameClass" style="bold #00aa88"/>
+  <entry type="NameConstant" style="#336600"/>
+  <entry type="NameDecorator" style="#9999ff"/>
+  <entry type="NameEntity" style="bold #999999"/>
+  <entry type="NameException" style="bold #cc0000"/>
+  <entry type="NameFunction" style="#cc00ff"/>
+  <entry type="NameLabel" style="#9999ff"/>
+  <entry type="NameNamespace" style="bold #00ccff"/>
+  <entry type="NameTag" style="bold #330099"/>
+  <entry type="NameVariable" style="#003333"/>
+  <entry type="LiteralString" style="#cc3300"/>
+  <entry type="LiteralStringDoc" style="italic"/>
+  <entry type="LiteralStringEscape" style="bold #cc3300"/>
+  <entry type="LiteralStringInterpol" style="#aa0000"/>
+  <entry type="LiteralStringOther" style="#cc3300"/>
+  <entry type="LiteralStringRegex" style="#33aaaa"/>
+  <entry type="LiteralStringSymbol" style="#ffcc33"/>
+  <entry type="LiteralNumber" style="#ff6600"/>
+  <entry type="Operator" style="#555555"/>
+  <entry type="OperatorWord" style="bold #000000"/>
+  <entry type="Comment" style="italic #0099ff"/>
+  <entry type="CommentSpecial" style="bold"/>
+  <entry type="CommentPreproc" style="noitalic #009999"/>
+  <entry type="GenericDeleted" style="bg:#ffcccc border:#cc0000"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#ff0000"/>
+  <entry type="GenericHeading" style="bold #003300"/>
+  <entry type="GenericInserted" style="bg:#ccffcc border:#00cc00"/>
+  <entry type="GenericOutput" style="#aaaaaa"/>
+  <entry type="GenericPrompt" style="bold #000099"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #003300"/>
+  <entry type="GenericTraceback" style="#99cc66"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/modus-operandi.xml b/styles/embedded/modus-operandi.xml
new file mode 100644
index 0000000..7fa72d9
--- /dev/null
+++ b/styles/embedded/modus-operandi.xml
@@ -0,0 +1,13 @@
+<style name="modus-operandi" theme="light">
+  <entry type="Background" style="#000000 bg:#ffffff"/>
+  <entry type="Keyword" style="#5317ac"/>
+  <entry type="KeywordConstant" style="#0000c0"/>
+  <entry type="KeywordType" style="#005a5f"/>
+  <entry type="NameBuiltin" style="#8f0075"/>
+  <entry type="NameFunction" style="#721045"/>
+  <entry type="NameVariable" style="#00538b"/>
+  <entry type="Literal" style="#0000c0"/>
+  <entry type="LiteralString" style="#2544bb"/>
+  <entry type="Operator" style="#00538b"/>
+  <entry type="Comment" style="#505050"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/modus-vivendi.xml b/styles/embedded/modus-vivendi.xml
new file mode 100644
index 0000000..62fff97
--- /dev/null
+++ b/styles/embedded/modus-vivendi.xml
@@ -0,0 +1,13 @@
+<style name="modus-vivendi" theme="dark">
+  <entry type="Background" style="#ffffff bg:#000000"/>
+  <entry type="Keyword" style="#b6a0ff"/>
+  <entry type="KeywordConstant" style="#00bcff"/>
+  <entry type="KeywordType" style="#6ae4b9"/>
+  <entry type="NameBuiltin" style="#f78fe7"/>
+  <entry type="NameFunction" style="#feacd0"/>
+  <entry type="NameVariable" style="#00d3d0"/>
+  <entry type="Literal" style="#00bcff"/>
+  <entry type="LiteralString" style="#79a8ff"/>
+  <entry type="Operator" style="#00d3d0"/>
+  <entry type="Comment" style="#a8a8a8"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/monokai.xml b/styles/embedded/monokai.xml
new file mode 100644
index 0000000..e5ce083
--- /dev/null
+++ b/styles/embedded/monokai.xml
@@ -0,0 +1,29 @@
+<style name="monokai" theme="dark">
+  <entry type="Error" style="#960050 bg:#1e0010"/>
+  <entry type="Background" style="bg:#272822"/>
+  <entry type="Keyword" style="#66d9ef"/>
+  <entry type="KeywordNamespace" style="#f92672"/>
+  <entry type="Name" style="#f8f8f2"/>
+  <entry type="NameAttribute" style="#a6e22e"/>
+  <entry type="NameClass" style="#a6e22e"/>
+  <entry type="NameConstant" style="#66d9ef"/>
+  <entry type="NameDecorator" style="#a6e22e"/>
+  <entry type="NameException" style="#a6e22e"/>
+  <entry type="NameFunction" style="#a6e22e"/>
+  <entry type="NameOther" style="#a6e22e"/>
+  <entry type="NameTag" style="#f92672"/>
+  <entry type="Literal" style="#ae81ff"/>
+  <entry type="LiteralDate" style="#e6db74"/>
+  <entry type="LiteralString" style="#e6db74"/>
+  <entry type="LiteralStringEscape" style="#ae81ff"/>
+  <entry type="LiteralNumber" style="#ae81ff"/>
+  <entry type="Operator" style="#f92672"/>
+  <entry type="Punctuation" style="#f8f8f2"/>
+  <entry type="Comment" style="#75715e"/>
+  <entry type="GenericDeleted" style="#f92672"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericInserted" style="#a6e22e"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#75715e"/>
+  <entry type="Text" style="#f8f8f2"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/monokailight.xml b/styles/embedded/monokailight.xml
new file mode 100644
index 0000000..27bb8f0
--- /dev/null
+++ b/styles/embedded/monokailight.xml
@@ -0,0 +1,26 @@
+<style name="monokailight" theme="light">
+  <entry type="Error" style="#960050 bg:#1e0010"/>
+  <entry type="Background" style="bg:#fafafa"/>
+  <entry type="Keyword" style="#00a8c8"/>
+  <entry type="KeywordNamespace" style="#f92672"/>
+  <entry type="Name" style="#111111"/>
+  <entry type="NameAttribute" style="#75af00"/>
+  <entry type="NameClass" style="#75af00"/>
+  <entry type="NameConstant" style="#00a8c8"/>
+  <entry type="NameDecorator" style="#75af00"/>
+  <entry type="NameException" style="#75af00"/>
+  <entry type="NameFunction" style="#75af00"/>
+  <entry type="NameOther" style="#75af00"/>
+  <entry type="NameTag" style="#f92672"/>
+  <entry type="Literal" style="#ae81ff"/>
+  <entry type="LiteralDate" style="#d88200"/>
+  <entry type="LiteralString" style="#d88200"/>
+  <entry type="LiteralStringEscape" style="#8045ff"/>
+  <entry type="LiteralNumber" style="#ae81ff"/>
+  <entry type="Operator" style="#f92672"/>
+  <entry type="Punctuation" style="#111111"/>
+  <entry type="Comment" style="#75715e"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="Text" style="#272822"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/murphy.xml b/styles/embedded/murphy.xml
new file mode 100644
index 0000000..867d9ee
--- /dev/null
+++ b/styles/embedded/murphy.xml
@@ -0,0 +1,52 @@
+<style name="murphy" theme="light">
+  <entry type="Error" style="#ff0000 bg:#ffaaaa"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="bold #228899"/>
+  <entry type="KeywordPseudo" style="#0088ff"/>
+  <entry type="KeywordType" style="#6666ff"/>
+  <entry type="NameAttribute" style="#000077"/>
+  <entry type="NameBuiltin" style="#007722"/>
+  <entry type="NameClass" style="bold #ee99ee"/>
+  <entry type="NameConstant" style="bold #55eedd"/>
+  <entry type="NameDecorator" style="bold #555555"/>
+  <entry type="NameEntity" style="#880000"/>
+  <entry type="NameException" style="bold #ff0000"/>
+  <entry type="NameFunction" style="bold #55eedd"/>
+  <entry type="NameLabel" style="bold #997700"/>
+  <entry type="NameNamespace" style="bold #0e84b5"/>
+  <entry type="NameTag" style="#007700"/>
+  <entry type="NameVariable" style="#003366"/>
+  <entry type="NameVariableClass" style="#ccccff"/>
+  <entry type="NameVariableGlobal" style="#ff8844"/>
+  <entry type="NameVariableInstance" style="#aaaaff"/>
+  <entry type="LiteralString" style="bg:#e0e0ff"/>
+  <entry type="LiteralStringChar" style="#8888ff"/>
+  <entry type="LiteralStringDoc" style="#dd4422"/>
+  <entry type="LiteralStringEscape" style="bold #666666"/>
+  <entry type="LiteralStringInterpol" style="bg:#eeeeee"/>
+  <entry type="LiteralStringOther" style="#ff8888"/>
+  <entry type="LiteralStringRegex" style="#000000 bg:#e0e0ff"/>
+  <entry type="LiteralStringSymbol" style="#ffcc88"/>
+  <entry type="LiteralNumber" style="bold #6600ee"/>
+  <entry type="LiteralNumberFloat" style="bold #6600ee"/>
+  <entry type="LiteralNumberHex" style="bold #005588"/>
+  <entry type="LiteralNumberInteger" style="bold #6666ff"/>
+  <entry type="LiteralNumberOct" style="bold #4400ee"/>
+  <entry type="Operator" style="#333333"/>
+  <entry type="OperatorWord" style="bold #000000"/>
+  <entry type="Comment" style="italic #666666"/>
+  <entry type="CommentSpecial" style="bold #cc0000"/>
+  <entry type="CommentPreproc" style="noitalic #557799"/>
+  <entry type="GenericDeleted" style="#a00000"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#ff0000"/>
+  <entry type="GenericHeading" style="bold #000080"/>
+  <entry type="GenericInserted" style="#00a000"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="bold #c65d09"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #800080"/>
+  <entry type="GenericTraceback" style="#0044dd"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/native.xml b/styles/embedded/native.xml
new file mode 100644
index 0000000..e60fb3a
--- /dev/null
+++ b/styles/embedded/native.xml
@@ -0,0 +1,35 @@
+<style name="native" theme="dark">
+  <entry type="Error" style="#a61717 bg:#e3d2d2"/>
+  <entry type="Background" style="#d0d0d0 bg:#202020"/>
+  <entry type="Keyword" style="bold #6ab825"/>
+  <entry type="KeywordPseudo" style="nobold"/>
+  <entry type="NameAttribute" style="#bbbbbb"/>
+  <entry type="NameBuiltin" style="#24909d"/>
+  <entry type="NameClass" style="underline #447fcf"/>
+  <entry type="NameConstant" style="#40ffff"/>
+  <entry type="NameDecorator" style="#ffa500"/>
+  <entry type="NameException" style="#bbbbbb"/>
+  <entry type="NameFunction" style="#447fcf"/>
+  <entry type="NameNamespace" style="underline #447fcf"/>
+  <entry type="NameTag" style="bold #6ab825"/>
+  <entry type="NameVariable" style="#40ffff"/>
+  <entry type="LiteralString" style="#ed9d13"/>
+  <entry type="LiteralStringOther" style="#ffa500"/>
+  <entry type="LiteralNumber" style="#3677a9"/>
+  <entry type="OperatorWord" style="bold #6ab825"/>
+  <entry type="Comment" style="italic #999999"/>
+  <entry type="CommentSpecial" style="bold noitalic #e50808 bg:#520000"/>
+  <entry type="CommentPreproc" style="bold noitalic #cd2828"/>
+  <entry type="GenericDeleted" style="#d22323"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#d22323"/>
+  <entry type="GenericHeading" style="bold #ffffff"/>
+  <entry type="GenericInserted" style="#589819"/>
+  <entry type="GenericOutput" style="#cccccc"/>
+  <entry type="GenericPrompt" style="#aaaaaa"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="underline #ffffff"/>
+  <entry type="GenericTraceback" style="#d22323"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#666666"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/nord.xml b/styles/embedded/nord.xml
new file mode 100644
index 0000000..0004fd7
--- /dev/null
+++ b/styles/embedded/nord.xml
@@ -0,0 +1,46 @@
+<style name="nord" theme="dark">
+  <entry type="Error" style="#bf616a"/>
+  <entry type="Background" style="#d8dee9 bg:#2e3440"/>
+  <entry type="Keyword" style="bold #81a1c1"/>
+  <entry type="KeywordPseudo" style="nobold #81a1c1"/>
+  <entry type="KeywordType" style="nobold #81a1c1"/>
+  <entry type="Name" style="#d8dee9"/>
+  <entry type="NameAttribute" style="#8fbcbb"/>
+  <entry type="NameBuiltin" style="#81a1c1"/>
+  <entry type="NameClass" style="#8fbcbb"/>
+  <entry type="NameConstant" style="#8fbcbb"/>
+  <entry type="NameDecorator" style="#d08770"/>
+  <entry type="NameEntity" style="#d08770"/>
+  <entry type="NameException" style="#bf616a"/>
+  <entry type="NameFunction" style="#88c0d0"/>
+  <entry type="NameLabel" style="#8fbcbb"/>
+  <entry type="NameNamespace" style="#8fbcbb"/>
+  <entry type="NameOther" style="#d8dee9"/>
+  <entry type="NameTag" style="#81a1c1"/>
+  <entry type="NameVariable" style="#d8dee9"/>
+  <entry type="NameProperty" style="#8fbcbb"/>
+  <entry type="LiteralString" style="#a3be8c"/>
+  <entry type="LiteralStringDoc" style="#616e87"/>
+  <entry type="LiteralStringEscape" style="#ebcb8b"/>
+  <entry type="LiteralStringInterpol" style="#a3be8c"/>
+  <entry type="LiteralStringOther" style="#a3be8c"/>
+  <entry type="LiteralStringRegex" style="#ebcb8b"/>
+  <entry type="LiteralStringSymbol" style="#a3be8c"/>
+  <entry type="LiteralNumber" style="#b48ead"/>
+  <entry type="Operator" style="#81a1c1"/>
+  <entry type="OperatorWord" style="bold #81a1c1"/>
+  <entry type="Punctuation" style="#eceff4"/>
+  <entry type="Comment" style="italic #616e87"/>
+  <entry type="CommentPreproc" style="#5e81ac"/>
+  <entry type="GenericDeleted" style="#bf616a"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#bf616a"/>
+  <entry type="GenericHeading" style="bold #88c0d0"/>
+  <entry type="GenericInserted" style="#a3be8c"/>
+  <entry type="GenericOutput" style="#d8dee9"/>
+  <entry type="GenericPrompt" style="bold #4c566a"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #88c0d0"/>
+  <entry type="GenericTraceback" style="#bf616a"/>
+  <entry type="TextWhitespace" style="#d8dee9"/>
+</style>
diff --git a/styles/embedded/onedark.xml b/styles/embedded/onedark.xml
new file mode 100644
index 0000000..9ce9d17
--- /dev/null
+++ b/styles/embedded/onedark.xml
@@ -0,0 +1,25 @@
+<style name="onedark" theme="dark">
+  <entry type="Background" style="#ABB2BF bg:#282C34"/>
+  <entry type="Punctuation" style="#ABB2BF"/>
+  <entry type="Keyword" style="#C678DD"/>
+  <entry type="KeywordConstant" style="#E5C07B"/>
+  <entry type="KeywordDeclaration" style="#C678DD"/>
+  <entry type="KeywordNamespace" style="#C678DD"/>
+  <entry type="KeywordReserved" style="#C678DD"/>
+  <entry type="KeywordType" style="#E5C07B"/>
+  <entry type="Name" style="#E06C75"/>
+  <entry type="NameAttribute" style="#E06C75"/>
+  <entry type="NameBuiltin" style="#E5C07B"/>
+  <entry type="NameClass" style="#E5C07B"/>
+  <entry type="NameFunction" style="bold #61AFEF"/>
+  <entry type="NameFunctionMagic" style="bold #56B6C2"/>
+  <entry type="NameOther" style="#E06C75"/>
+  <entry type="NameTag" style="#E06C75"/>
+  <entry type="NameDecorator" style="#61AFEF"/>
+  <entry type="LiteralString" style="#98C379"/>
+  <entry type="LiteralNumber" style="#D19A66"/>
+  <entry type="Operator" style="#56B6C2"/>
+  <entry type="Comment" style="#7F848E"/>
+  <entry type="GenericDeleted" style="#E06C75"/>
+  <entry type="GenericInserted" style="bold #98C379"/>
+</style>
diff --git a/styles/embedded/onesenterprise.xml b/styles/embedded/onesenterprise.xml
new file mode 100644
index 0000000..efe93b8
--- /dev/null
+++ b/styles/embedded/onesenterprise.xml
@@ -0,0 +1,10 @@
+<style name="onesenterprise" theme="light">
+  <entry type="Keyword" style="#ff0000"/>
+  <entry type="Name" style="#0000ff"/>
+  <entry type="LiteralString" style="#000000"/>
+  <entry type="Operator" style="#ff0000"/>
+  <entry type="Punctuation" style="#ff0000"/>
+  <entry type="Comment" style="#008000"/>
+  <entry type="CommentPreproc" style="#963200"/>
+  <entry type="Text" style="#000000"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/paraiso-dark.xml b/styles/embedded/paraiso-dark.xml
new file mode 100644
index 0000000..45e0aa0
--- /dev/null
+++ b/styles/embedded/paraiso-dark.xml
@@ -0,0 +1,37 @@
+<style name="paraiso-dark" theme="dark">
+  <entry type="Error" style="#ef6155"/>
+  <entry type="Background" style="bg:#2f1e2e"/>
+  <entry type="Keyword" style="#815ba4"/>
+  <entry type="KeywordNamespace" style="#5bc4bf"/>
+  <entry type="KeywordType" style="#fec418"/>
+  <entry type="Name" style="#e7e9db"/>
+  <entry type="NameAttribute" style="#06b6ef"/>
+  <entry type="NameClass" style="#fec418"/>
+  <entry type="NameConstant" style="#ef6155"/>
+  <entry type="NameDecorator" style="#5bc4bf"/>
+  <entry type="NameException" style="#ef6155"/>
+  <entry type="NameFunction" style="#06b6ef"/>
+  <entry type="NameNamespace" style="#fec418"/>
+  <entry type="NameOther" style="#06b6ef"/>
+  <entry type="NameTag" style="#5bc4bf"/>
+  <entry type="NameVariable" style="#ef6155"/>
+  <entry type="Literal" style="#f99b15"/>
+  <entry type="LiteralDate" style="#48b685"/>
+  <entry type="LiteralString" style="#48b685"/>
+  <entry type="LiteralStringChar" style="#e7e9db"/>
+  <entry type="LiteralStringDoc" style="#776e71"/>
+  <entry type="LiteralStringEscape" style="#f99b15"/>
+  <entry type="LiteralStringInterpol" style="#f99b15"/>
+  <entry type="LiteralNumber" style="#f99b15"/>
+  <entry type="Operator" style="#5bc4bf"/>
+  <entry type="Punctuation" style="#e7e9db"/>
+  <entry type="Comment" style="#776e71"/>
+  <entry type="GenericDeleted" style="#ef6155"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericHeading" style="bold #e7e9db"/>
+  <entry type="GenericInserted" style="#48b685"/>
+  <entry type="GenericPrompt" style="bold #776e71"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #5bc4bf"/>
+  <entry type="Text" style="#e7e9db"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/paraiso-light.xml b/styles/embedded/paraiso-light.xml
new file mode 100644
index 0000000..f4e7ef6
--- /dev/null
+++ b/styles/embedded/paraiso-light.xml
@@ -0,0 +1,37 @@
+<style name="paraiso-light" theme="light">
+  <entry type="Error" style="#ef6155"/>
+  <entry type="Background" style="bg:#e7e9db"/>
+  <entry type="Keyword" style="#815ba4"/>
+  <entry type="KeywordNamespace" style="#5bc4bf"/>
+  <entry type="KeywordType" style="#fec418"/>
+  <entry type="Name" style="#2f1e2e"/>
+  <entry type="NameAttribute" style="#06b6ef"/>
+  <entry type="NameClass" style="#fec418"/>
+  <entry type="NameConstant" style="#ef6155"/>
+  <entry type="NameDecorator" style="#5bc4bf"/>
+  <entry type="NameException" style="#ef6155"/>
+  <entry type="NameFunction" style="#06b6ef"/>
+  <entry type="NameNamespace" style="#fec418"/>
+  <entry type="NameOther" style="#06b6ef"/>
+  <entry type="NameTag" style="#5bc4bf"/>
+  <entry type="NameVariable" style="#ef6155"/>
+  <entry type="Literal" style="#f99b15"/>
+  <entry type="LiteralDate" style="#48b685"/>
+  <entry type="LiteralString" style="#48b685"/>
+  <entry type="LiteralStringChar" style="#2f1e2e"/>
+  <entry type="LiteralStringDoc" style="#8d8687"/>
+  <entry type="LiteralStringEscape" style="#f99b15"/>
+  <entry type="LiteralStringInterpol" style="#f99b15"/>
+  <entry type="LiteralNumber" style="#f99b15"/>
+  <entry type="Operator" style="#5bc4bf"/>
+  <entry type="Punctuation" style="#2f1e2e"/>
+  <entry type="Comment" style="#8d8687"/>
+  <entry type="GenericDeleted" style="#ef6155"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericHeading" style="bold #2f1e2e"/>
+  <entry type="GenericInserted" style="#48b685"/>
+  <entry type="GenericPrompt" style="bold #8d8687"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #5bc4bf"/>
+  <entry type="Text" style="#2f1e2e"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/pastie.xml b/styles/embedded/pastie.xml
new file mode 100644
index 0000000..56297b1
--- /dev/null
+++ b/styles/embedded/pastie.xml
@@ -0,0 +1,45 @@
+<style name="pastie" theme="light">
+  <entry type="Error" style="#a61717 bg:#e3d2d2"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="bold #008800"/>
+  <entry type="KeywordPseudo" style="nobold"/>
+  <entry type="KeywordType" style="#888888"/>
+  <entry type="NameAttribute" style="#336699"/>
+  <entry type="NameBuiltin" style="#003388"/>
+  <entry type="NameClass" style="bold #bb0066"/>
+  <entry type="NameConstant" style="bold #003366"/>
+  <entry type="NameDecorator" style="#555555"/>
+  <entry type="NameException" style="bold #bb0066"/>
+  <entry type="NameFunction" style="bold #0066bb"/>
+  <entry type="NameLabel" style="italic #336699"/>
+  <entry type="NameNamespace" style="bold #bb0066"/>
+  <entry type="NameProperty" style="bold #336699"/>
+  <entry type="NameTag" style="bold #bb0066"/>
+  <entry type="NameVariable" style="#336699"/>
+  <entry type="NameVariableClass" style="#336699"/>
+  <entry type="NameVariableGlobal" style="#dd7700"/>
+  <entry type="NameVariableInstance" style="#3333bb"/>
+  <entry type="LiteralString" style="#dd2200 bg:#fff0f0"/>
+  <entry type="LiteralStringEscape" style="#0044dd"/>
+  <entry type="LiteralStringInterpol" style="#3333bb"/>
+  <entry type="LiteralStringOther" style="#22bb22 bg:#f0fff0"/>
+  <entry type="LiteralStringRegex" style="#008800 bg:#fff0ff"/>
+  <entry type="LiteralStringSymbol" style="#aa6600"/>
+  <entry type="LiteralNumber" style="bold #0000dd"/>
+  <entry type="OperatorWord" style="#008800"/>
+  <entry type="Comment" style="#888888"/>
+  <entry type="CommentSpecial" style="bold #cc0000 bg:#fff0f0"/>
+  <entry type="CommentPreproc" style="bold #cc0000"/>
+  <entry type="GenericDeleted" style="#000000 bg:#ffdddd"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#aa0000"/>
+  <entry type="GenericHeading" style="#333333"/>
+  <entry type="GenericInserted" style="#000000 bg:#ddffdd"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="#555555"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#666666"/>
+  <entry type="GenericTraceback" style="#aa0000"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/perldoc.xml b/styles/embedded/perldoc.xml
new file mode 100644
index 0000000..6521246
--- /dev/null
+++ b/styles/embedded/perldoc.xml
@@ -0,0 +1,37 @@
+<style name="perldoc" theme="light">
+  <entry type="Error" style="#a61717 bg:#e3d2d2"/>
+  <entry type="Background" style="bg:#eeeedd"/>
+  <entry type="Keyword" style="bold #8b008b"/>
+  <entry type="KeywordType" style="#00688b"/>
+  <entry type="NameAttribute" style="#658b00"/>
+  <entry type="NameBuiltin" style="#658b00"/>
+  <entry type="NameClass" style="bold #008b45"/>
+  <entry type="NameConstant" style="#00688b"/>
+  <entry type="NameDecorator" style="#707a7c"/>
+  <entry type="NameException" style="bold #008b45"/>
+  <entry type="NameFunction" style="#008b45"/>
+  <entry type="NameNamespace" style="underline #008b45"/>
+  <entry type="NameTag" style="bold #8b008b"/>
+  <entry type="NameVariable" style="#00688b"/>
+  <entry type="LiteralString" style="#cd5555"/>
+  <entry type="LiteralStringHeredoc" style="italic #1c7e71"/>
+  <entry type="LiteralStringOther" style="#cb6c20"/>
+  <entry type="LiteralStringRegex" style="#1c7e71"/>
+  <entry type="LiteralNumber" style="#b452cd"/>
+  <entry type="OperatorWord" style="#8b008b"/>
+  <entry type="Comment" style="#228b22"/>
+  <entry type="CommentSpecial" style="bold #8b008b"/>
+  <entry type="CommentPreproc" style="#1e889b"/>
+  <entry type="GenericDeleted" style="#aa0000"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#aa0000"/>
+  <entry type="GenericHeading" style="bold #000080"/>
+  <entry type="GenericInserted" style="#00aa00"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="#555555"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #800080"/>
+  <entry type="GenericTraceback" style="#aa0000"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/pygments.xml b/styles/embedded/pygments.xml
new file mode 100644
index 0000000..ffbd782
--- /dev/null
+++ b/styles/embedded/pygments.xml
@@ -0,0 +1,42 @@
+<style name="pygments" theme="light">
+  <entry type="Error" style="border:#ff0000"/>
+  <entry type="Keyword" style="bold #008000"/>
+  <entry type="KeywordPseudo" style="nobold"/>
+  <entry type="KeywordType" style="nobold #b00040"/>
+  <entry type="NameAttribute" style="#7d9029"/>
+  <entry type="NameBuiltin" style="#008000"/>
+  <entry type="NameClass" style="bold #0000ff"/>
+  <entry type="NameConstant" style="#880000"/>
+  <entry type="NameDecorator" style="#aa22ff"/>
+  <entry type="NameEntity" style="bold #999999"/>
+  <entry type="NameException" style="bold #d2413a"/>
+  <entry type="NameFunction" style="#0000ff"/>
+  <entry type="NameLabel" style="#a0a000"/>
+  <entry type="NameNamespace" style="bold #0000ff"/>
+  <entry type="NameTag" style="bold #008000"/>
+  <entry type="NameVariable" style="#19177c"/>
+  <entry type="LiteralString" style="#ba2121"/>
+  <entry type="LiteralStringDoc" style="italic"/>
+  <entry type="LiteralStringEscape" style="bold #bb6622"/>
+  <entry type="LiteralStringInterpol" style="bold #bb6688"/>
+  <entry type="LiteralStringOther" style="#008000"/>
+  <entry type="LiteralStringRegex" style="#bb6688"/>
+  <entry type="LiteralStringSymbol" style="#19177c"/>
+  <entry type="LiteralNumber" style="#666666"/>
+  <entry type="Operator" style="#666666"/>
+  <entry type="OperatorWord" style="bold #aa22ff"/>
+  <entry type="Comment" style="italic #408080"/>
+  <entry type="CommentPreproc" style="noitalic #bc7a00"/>
+  <entry type="GenericDeleted" style="#a00000"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#ff0000"/>
+  <entry type="GenericHeading" style="bold #000080"/>
+  <entry type="GenericInserted" style="#00a000"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="bold #000080"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #800080"/>
+  <entry type="GenericTraceback" style="#0044dd"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/rainbow_dash.xml b/styles/embedded/rainbow_dash.xml
new file mode 100644
index 0000000..ffe6463
--- /dev/null
+++ b/styles/embedded/rainbow_dash.xml
@@ -0,0 +1,40 @@
+<style name="rainbow_dash" theme="light">
+  <entry type="Error" style="#ffffff bg:#cc0000"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="bold #2c5dcd"/>
+  <entry type="KeywordPseudo" style="nobold"/>
+  <entry type="KeywordType" style="#5918bb"/>
+  <entry type="NameAttribute" style="italic #2c5dcd"/>
+  <entry type="NameBuiltin" style="bold #5918bb"/>
+  <entry type="NameClass" style="underline"/>
+  <entry type="NameConstant" style="#318495"/>
+  <entry type="NameDecorator" style="bold #ff8000"/>
+  <entry type="NameEntity" style="bold #5918bb"/>
+  <entry type="NameException" style="bold #5918bb"/>
+  <entry type="NameFunction" style="bold #ff8000"/>
+  <entry type="NameTag" style="bold #2c5dcd"/>
+  <entry type="LiteralString" style="#00cc66"/>
+  <entry type="LiteralStringDoc" style="italic"/>
+  <entry type="LiteralStringEscape" style="bold #c5060b"/>
+  <entry type="LiteralStringOther" style="#318495"/>
+  <entry type="LiteralStringSymbol" style="bold #c5060b"/>
+  <entry type="LiteralNumber" style="bold #5918bb"/>
+  <entry type="Operator" style="#2c5dcd"/>
+  <entry type="OperatorWord" style="bold"/>
+  <entry type="Comment" style="italic #0080ff"/>
+  <entry type="CommentSpecial" style="bold"/>
+  <entry type="CommentPreproc" style="noitalic"/>
+  <entry type="GenericDeleted" style="bg:#ffcccc border:#c5060b"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#ff0000"/>
+  <entry type="GenericHeading" style="bold #2c5dcd"/>
+  <entry type="GenericInserted" style="bg:#ccffcc border:#00cc00"/>
+  <entry type="GenericOutput" style="#aaaaaa"/>
+  <entry type="GenericPrompt" style="bold #2c5dcd"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #2c5dcd"/>
+  <entry type="GenericTraceback" style="#c5060b"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="Text" style="#4d4d4d"/>
+  <entry type="TextWhitespace" style="#cbcbcb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/rose-pine-dawn.xml b/styles/embedded/rose-pine-dawn.xml
new file mode 100644
index 0000000..f2fa25d
--- /dev/null
+++ b/styles/embedded/rose-pine-dawn.xml
@@ -0,0 +1,29 @@
+<style name="rose-pine-dawn" theme="light">
+  <entry type="Error" style="#b4637a"/>
+  <entry type="Background" style="bg:#faf4ed"/>
+  <entry type="Keyword" style="#286983"/>
+  <entry type="KeywordNamespace" style="#907aa9"/>
+  <entry type="Name" style="#d7827e"/>
+  <entry type="NameAttribute" style="#d7827e"/>
+  <entry type="NameClass" style="#56949f"/>
+  <entry type="NameConstant" style="#ea9d34"/>
+  <entry type="NameDecorator" style="#797593"/>
+  <entry type="NameException" style="#286983"/>
+  <entry type="NameFunction" style="#d7827e"/>
+  <entry type="NameOther" style="#575279"/>
+  <entry type="NameTag" style="#d7827e"/>
+  <entry type="Literal" style="#ea9d34"/>
+  <entry type="LiteralDate" style="#ea9d34"/>
+  <entry type="LiteralString" style="#ea9d34"/>
+  <entry type="LiteralStringEscape" style="#286983"/>
+  <entry type="LiteralNumber" style="#ea9d34"/>
+  <entry type="Operator" style="#797593"/>
+  <entry type="Punctuation" style="#797593"/>
+  <entry type="Comment" style="#9893a5"/>
+  <entry type="GenericDeleted" style="#b4637a"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericInserted" style="#56949f"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#907aa9"/>
+  <entry type="Text" style="#575279"/>
+</style>
diff --git a/styles/embedded/rose-pine-moon.xml b/styles/embedded/rose-pine-moon.xml
new file mode 100644
index 0000000..9df4245
--- /dev/null
+++ b/styles/embedded/rose-pine-moon.xml
@@ -0,0 +1,29 @@
+<style name="rose-pine-moon" theme="dark">
+  <entry type="Error" style="#eb6f92"/>
+  <entry type="Background" style="bg:#232136"/>
+  <entry type="Keyword" style="#3e8fb0"/>
+  <entry type="KeywordNamespace" style="#c4a7e7"/>
+  <entry type="Name" style="#ea9a97"/>
+  <entry type="NameAttribute" style="#ea9a97"/>
+  <entry type="NameClass" style="#9ccfd8"/>
+  <entry type="NameConstant" style="#f6c177"/>
+  <entry type="NameDecorator" style="#908caa"/>
+  <entry type="NameException" style="#3e8fb0"/>
+  <entry type="NameFunction" style="#ea9a97"/>
+  <entry type="NameOther" style="#e0def4"/>
+  <entry type="NameTag" style="#ea9a97"/>
+  <entry type="Literal" style="#f6c177"/>
+  <entry type="LiteralDate" style="#f6c177"/>
+  <entry type="LiteralString" style="#f6c177"/>
+  <entry type="LiteralStringEscape" style="#3e8fb0"/>
+  <entry type="LiteralNumber" style="#f6c177"/>
+  <entry type="Operator" style="#908caa"/>
+  <entry type="Punctuation" style="#908caa"/>
+  <entry type="Comment" style="#6e6a86"/>
+  <entry type="GenericDeleted" style="#eb6f92"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericInserted" style="#9ccfd8"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#c4a7e7"/>
+  <entry type="Text" style="#e0def4"/>
+</style>
diff --git a/styles/embedded/rose-pine.xml b/styles/embedded/rose-pine.xml
new file mode 100644
index 0000000..80bb45e
--- /dev/null
+++ b/styles/embedded/rose-pine.xml
@@ -0,0 +1,29 @@
+<style name="rose-pine" theme="dark">
+  <entry type="Error" style="#eb6f92"/>
+  <entry type="Background" style="bg:#191724"/>
+  <entry type="Keyword" style="#31748f"/>
+  <entry type="KeywordNamespace" style="#c4a7e7"/>
+  <entry type="Name" style="#ebbcba"/>
+  <entry type="NameAttribute" style="#ebbcba"/>
+  <entry type="NameClass" style="#9ccfd8"/>
+  <entry type="NameConstant" style="#f6c177"/>
+  <entry type="NameDecorator" style="#908caa"/>
+  <entry type="NameException" style="#31748f"/>
+  <entry type="NameFunction" style="#ebbcba"/>
+  <entry type="NameOther" style="#e0def4"/>
+  <entry type="NameTag" style="#ebbcba"/>
+  <entry type="Literal" style="#f6c177"/>
+  <entry type="LiteralDate" style="#f6c177"/>
+  <entry type="LiteralString" style="#f6c177"/>
+  <entry type="LiteralStringEscape" style="#31748f"/>
+  <entry type="LiteralNumber" style="#f6c177"/>
+  <entry type="Operator" style="#908caa"/>
+  <entry type="Punctuation" style="#908caa"/>
+  <entry type="Comment" style="#6e6a86"/>
+  <entry type="GenericDeleted" style="#eb6f92"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericInserted" style="#9ccfd8"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#c4a7e7"/>
+  <entry type="Text" style="#e0def4"/>
+</style>
diff --git a/styles/embedded/rrt.xml b/styles/embedded/rrt.xml
new file mode 100644
index 0000000..063e66d
--- /dev/null
+++ b/styles/embedded/rrt.xml
@@ -0,0 +1,13 @@
+<style name="rrt" theme="dark">
+  <entry type="Background" style="#f8f8f2 bg:#000000"/>
+  <entry type="Keyword" style="#ff0000"/>
+  <entry type="KeywordType" style="#ee82ee"/>
+  <entry type="NameConstant" style="#7fffd4"/>
+  <entry type="NameFunction" style="#ffff00"/>
+  <entry type="NameVariable" style="#eedd82"/>
+  <entry type="LiteralString" style="#87ceeb"/>
+  <entry type="LiteralStringSymbol" style="#ff6600"/>
+  <entry type="LiteralNumber" style="#ff6600"/>
+  <entry type="Comment" style="#00ff00"/>
+  <entry type="CommentPreproc" style="#e5e5e5"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/solarized-dark.xml b/styles/embedded/solarized-dark.xml
new file mode 100644
index 0000000..ae157ee
--- /dev/null
+++ b/styles/embedded/solarized-dark.xml
@@ -0,0 +1,39 @@
+<style name="solarized-dark" theme="dark">
+  <entry type="Other" style="#cb4b16"/>
+  <entry type="Background" style="#93a1a1 bg:#002b36"/>
+  <entry type="Keyword" style="#719e07"/>
+  <entry type="KeywordConstant" style="#cb4b16"/>
+  <entry type="KeywordDeclaration" style="#268bd2"/>
+  <entry type="KeywordReserved" style="#268bd2"/>
+  <entry type="KeywordType" style="#dc322f"/>
+  <entry type="NameAttribute" style="#93a1a1"/>
+  <entry type="NameBuiltin" style="#b58900"/>
+  <entry type="NameBuiltinPseudo" style="#268bd2"/>
+  <entry type="NameClass" style="#268bd2"/>
+  <entry type="NameConstant" style="#cb4b16"/>
+  <entry type="NameDecorator" style="#268bd2"/>
+  <entry type="NameEntity" style="#cb4b16"/>
+  <entry type="NameException" style="#cb4b16"/>
+  <entry type="NameFunction" style="#268bd2"/>
+  <entry type="NameTag" style="#268bd2"/>
+  <entry type="NameVariable" style="#268bd2"/>
+  <entry type="LiteralString" style="#2aa198"/>
+  <entry type="LiteralStringBacktick" style="#586e75"/>
+  <entry type="LiteralStringChar" style="#2aa198"/>
+  <entry type="LiteralStringDoc" style="#93a1a1"/>
+  <entry type="LiteralStringEscape" style="#cb4b16"/>
+  <entry type="LiteralStringHeredoc" style="#93a1a1"/>
+  <entry type="LiteralStringRegex" style="#dc322f"/>
+  <entry type="LiteralNumber" style="#2aa198"/>
+  <entry type="Operator" style="#719e07"/>
+  <entry type="Comment" style="#586e75"/>
+  <entry type="CommentSpecial" style="#719e07"/>
+  <entry type="CommentPreproc" style="#719e07"/>
+  <entry type="GenericDeleted" style="#dc322f"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="bold #dc322f"/>
+  <entry type="GenericHeading" style="#cb4b16"/>
+  <entry type="GenericInserted" style="#719e07"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#268bd2"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/solarized-dark256.xml b/styles/embedded/solarized-dark256.xml
new file mode 100644
index 0000000..1693861
--- /dev/null
+++ b/styles/embedded/solarized-dark256.xml
@@ -0,0 +1,41 @@
+<style name="solarized-dark256" theme="dark">
+  <entry type="Other" style="#d75f00"/>
+  <entry type="Background" style="#8a8a8a bg:#1c1c1c"/>
+  <entry type="Keyword" style="#5f8700"/>
+  <entry type="KeywordConstant" style="#d75f00"/>
+  <entry type="KeywordDeclaration" style="#0087ff"/>
+  <entry type="KeywordNamespace" style="#d75f00"/>
+  <entry type="KeywordReserved" style="#0087ff"/>
+  <entry type="KeywordType" style="#af0000"/>
+  <entry type="NameAttribute" style="#8a8a8a"/>
+  <entry type="NameBuiltin" style="#0087ff"/>
+  <entry type="NameBuiltinPseudo" style="#0087ff"/>
+  <entry type="NameClass" style="#0087ff"/>
+  <entry type="NameConstant" style="#d75f00"/>
+  <entry type="NameDecorator" style="#0087ff"/>
+  <entry type="NameEntity" style="#d75f00"/>
+  <entry type="NameException" style="#af8700"/>
+  <entry type="NameFunction" style="#0087ff"/>
+  <entry type="NameTag" style="#0087ff"/>
+  <entry type="NameVariable" style="#0087ff"/>
+  <entry type="LiteralString" style="#00afaf"/>
+  <entry type="LiteralStringBacktick" style="#4e4e4e"/>
+  <entry type="LiteralStringChar" style="#00afaf"/>
+  <entry type="LiteralStringDoc" style="#00afaf"/>
+  <entry type="LiteralStringEscape" style="#af0000"/>
+  <entry type="LiteralStringHeredoc" style="#00afaf"/>
+  <entry type="LiteralStringRegex" style="#af0000"/>
+  <entry type="LiteralNumber" style="#00afaf"/>
+  <entry type="Operator" style="#8a8a8a"/>
+  <entry type="OperatorWord" style="#5f8700"/>
+  <entry type="Comment" style="#4e4e4e"/>
+  <entry type="CommentSpecial" style="#5f8700"/>
+  <entry type="CommentPreproc" style="#5f8700"/>
+  <entry type="GenericDeleted" style="#af0000"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="bold #af0000"/>
+  <entry type="GenericHeading" style="#d75f00"/>
+  <entry type="GenericInserted" style="#5f8700"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#0087ff"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/solarized-light.xml b/styles/embedded/solarized-light.xml
new file mode 100644
index 0000000..67f2475
--- /dev/null
+++ b/styles/embedded/solarized-light.xml
@@ -0,0 +1,17 @@
+<style name="solarized-light" theme="light">
+  <entry type="Background" style="bg:#eee8d5"/>
+  <entry type="Keyword" style="#859900"/>
+  <entry type="KeywordConstant" style="bold"/>
+  <entry type="KeywordNamespace" style="bold #dc322f"/>
+  <entry type="KeywordType" style="bold"/>
+  <entry type="Name" style="#268bd2"/>
+  <entry type="NameBuiltin" style="#cb4b16"/>
+  <entry type="NameClass" style="#cb4b16"/>
+  <entry type="NameTag" style="bold"/>
+  <entry type="Literal" style="#2aa198"/>
+  <entry type="LiteralNumber" style="bold"/>
+  <entry type="OperatorWord" style="#859900"/>
+  <entry type="Comment" style="italic #93a1a1"/>
+  <entry type="Generic" style="#d33682"/>
+  <entry type="Text" style="#586e75"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/swapoff.xml b/styles/embedded/swapoff.xml
new file mode 100644
index 0000000..c396008
--- /dev/null
+++ b/styles/embedded/swapoff.xml
@@ -0,0 +1,18 @@
+<style name="swapoff" theme="dark">
+  <entry type="Error" style="#ff0000"/>
+  <entry type="Background" style="#e5e5e5 bg:#000000"/>
+  <entry type="Keyword" style="bold #ffffff"/>
+  <entry type="NameAttribute" style="#007f7f"/>
+  <entry type="NameBuiltin" style="bold #ffffff"/>
+  <entry type="NameKeyword" style="bold #ffffff"/>
+  <entry type="NameTag" style="bold"/>
+  <entry type="LiteralDate" style="bold #ffff00"/>
+  <entry type="LiteralString" style="bold #00ffff"/>
+  <entry type="LiteralNumber" style="bold #ffff00"/>
+  <entry type="Comment" style="#007f7f"/>
+  <entry type="CommentPreproc" style="bold #00ff00"/>
+  <entry type="GenericHeading" style="bold"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold"/>
+  <entry type="GenericUnderline" style="underline"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/tango.xml b/styles/embedded/tango.xml
new file mode 100644
index 0000000..431fe10
--- /dev/null
+++ b/styles/embedded/tango.xml
@@ -0,0 +1,72 @@
+<style name="tango" theme="light">
+  <entry type="Other" style="#000000"/>
+  <entry type="Error" style="#a40000 border:#ef2929"/>
+  <entry type="Background" style="bg:#f8f8f8"/>
+  <entry type="Keyword" style="bold #204a87"/>
+  <entry type="KeywordConstant" style="bold #204a87"/>
+  <entry type="KeywordDeclaration" style="bold #204a87"/>
+  <entry type="KeywordNamespace" style="bold #204a87"/>
+  <entry type="KeywordPseudo" style="bold #204a87"/>
+  <entry type="KeywordReserved" style="bold #204a87"/>
+  <entry type="KeywordType" style="bold #204a87"/>
+  <entry type="Name" style="#000000"/>
+  <entry type="NameAttribute" style="#c4a000"/>
+  <entry type="NameBuiltin" style="#204a87"/>
+  <entry type="NameBuiltinPseudo" style="#3465a4"/>
+  <entry type="NameClass" style="#000000"/>
+  <entry type="NameConstant" style="#000000"/>
+  <entry type="NameDecorator" style="bold #5c35cc"/>
+  <entry type="NameEntity" style="#ce5c00"/>
+  <entry type="NameException" style="bold #cc0000"/>
+  <entry type="NameFunction" style="#000000"/>
+  <entry type="NameLabel" style="#f57900"/>
+  <entry type="NameNamespace" style="#000000"/>
+  <entry type="NameOther" style="#000000"/>
+  <entry type="NameProperty" style="#000000"/>
+  <entry type="NameTag" style="bold #204a87"/>
+  <entry type="NameVariable" style="#000000"/>
+  <entry type="NameVariableClass" style="#000000"/>
+  <entry type="NameVariableGlobal" style="#000000"/>
+  <entry type="NameVariableInstance" style="#000000"/>
+  <entry type="Literal" style="#000000"/>
+  <entry type="LiteralDate" style="#000000"/>
+  <entry type="LiteralString" style="#4e9a06"/>
+  <entry type="LiteralStringBacktick" style="#4e9a06"/>
+  <entry type="LiteralStringChar" style="#4e9a06"/>
+  <entry type="LiteralStringDoc" style="italic #8f5902"/>
+  <entry type="LiteralStringDouble" style="#4e9a06"/>
+  <entry type="LiteralStringEscape" style="#4e9a06"/>
+  <entry type="LiteralStringHeredoc" style="#4e9a06"/>
+  <entry type="LiteralStringInterpol" style="#4e9a06"/>
+  <entry type="LiteralStringOther" style="#4e9a06"/>
+  <entry type="LiteralStringRegex" style="#4e9a06"/>
+  <entry type="LiteralStringSingle" style="#4e9a06"/>
+  <entry type="LiteralStringSymbol" style="#4e9a06"/>
+  <entry type="LiteralNumber" style="bold #0000cf"/>
+  <entry type="LiteralNumberFloat" style="bold #0000cf"/>
+  <entry type="LiteralNumberHex" style="bold #0000cf"/>
+  <entry type="LiteralNumberInteger" style="bold #0000cf"/>
+  <entry type="LiteralNumberIntegerLong" style="bold #0000cf"/>
+  <entry type="LiteralNumberOct" style="bold #0000cf"/>
+  <entry type="Operator" style="bold #ce5c00"/>
+  <entry type="OperatorWord" style="bold #204a87"/>
+  <entry type="Punctuation" style="bold #000000"/>
+  <entry type="Comment" style="italic #8f5902"/>
+  <entry type="CommentMultiline" style="italic #8f5902"/>
+  <entry type="CommentSingle" style="italic #8f5902"/>
+  <entry type="CommentSpecial" style="italic #8f5902"/>
+  <entry type="CommentPreproc" style="italic #8f5902"/>
+  <entry type="Generic" style="#000000"/>
+  <entry type="GenericDeleted" style="#a40000"/>
+  <entry type="GenericEmph" style="italic #000000"/>
+  <entry type="GenericError" style="#ef2929"/>
+  <entry type="GenericHeading" style="bold #000080"/>
+  <entry type="GenericInserted" style="#00a000"/>
+  <entry type="GenericOutput" style="italic #000000"/>
+  <entry type="GenericPrompt" style="#8f5902"/>
+  <entry type="GenericStrong" style="bold #000000"/>
+  <entry type="GenericSubheading" style="bold #800080"/>
+  <entry type="GenericTraceback" style="bold #a40000"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="underline #f8f8f8"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/tokyonight-day.xml b/styles/embedded/tokyonight-day.xml
new file mode 100644
index 0000000..a146a18
--- /dev/null
+++ b/styles/embedded/tokyonight-day.xml
@@ -0,0 +1,83 @@
+<style name="tokyonight-day" theme="light">
+  <entry type="Background" style="bg:#e1e2e7 #3760bf"/>
+  <entry type="CodeLine" style="#3760bf"/>
+  <entry type="Error" style="#c64343"/>
+  <entry type="Other" style="#3760bf"/>
+  <entry type="LineTableTD" style=""/>
+  <entry type="LineTable" style=""/>
+  <entry type="LineHighlight" style="bg:#a1a6c5"/>
+  <entry type="LineNumbersTable" style="#6172b0"/>
+  <entry type="LineNumbers" style="#6172b0"/>
+  <entry type="Keyword" style="#9854f1"/>
+  <entry type="KeywordReserved" style="#9854f1"/>
+  <entry type="KeywordPseudo" style="#9854f1"/>
+  <entry type="KeywordConstant" style="#8c6c3e"/>
+  <entry type="KeywordDeclaration" style="#9d7cd8"/>
+  <entry type="KeywordNamespace" style="#007197"/>
+  <entry type="KeywordType" style="#0db9d7"/>
+  <entry type="Name" style="#3760bf"/>
+  <entry type="NameClass" style="#b15c00"/>
+  <entry type="NameConstant" style="#b15c00"/>
+  <entry type="NameDecorator" style="bold #2e7de9"/>
+  <entry type="NameEntity" style="#007197"/>
+  <entry type="NameException" style="#8c6c3e"/>
+  <entry type="NameFunction" style="#2e7de9"/>
+  <entry type="NameFunctionMagic" style="#2e7de9"/>
+  <entry type="NameLabel" style="#587539"/>
+  <entry type="NameNamespace" style="#8c6c3e"/>
+  <entry type="NameProperty" style="#8c6c3e"/>
+  <entry type="NameTag" style="#9854f1"/>
+  <entry type="NameVariable" style="#3760bf"/>
+  <entry type="NameVariableClass" style="#3760bf"/>
+  <entry type="NameVariableGlobal" style="#3760bf"/>
+  <entry type="NameVariableInstance" style="#3760bf"/>
+  <entry type="NameVariableMagic" style="#3760bf"/>
+  <entry type="NameAttribute" style="#2e7de9"/>
+  <entry type="NameBuiltin" style="#587539"/>
+  <entry type="NameBuiltinPseudo" style="#587539"/>
+  <entry type="NameOther" style="#3760bf"/>
+  <entry type="Literal" style="#3760bf"/>
+  <entry type="LiteralDate" style="#3760bf"/>
+  <entry type="LiteralString" style="#587539"/>
+  <entry type="LiteralStringChar" style="#587539"/>
+  <entry type="LiteralStringSingle" style="#587539"/>
+  <entry type="LiteralStringDouble" style="#587539"/>
+  <entry type="LiteralStringBacktick" style="#587539"/>
+  <entry type="LiteralStringOther" style="#587539"/>
+  <entry type="LiteralStringSymbol" style="#587539"/>
+  <entry type="LiteralStringInterpol" style="#587539"/>
+  <entry type="LiteralStringAffix" style="#9d7cd8"/>
+  <entry type="LiteralStringDelimiter" style="#2e7de9"/>
+  <entry type="LiteralStringEscape" style="#2e7de9"/>
+  <entry type="LiteralStringRegex" style="#007197"/>
+  <entry type="LiteralStringDoc" style="#a1a6c5"/>
+  <entry type="LiteralStringHeredoc" style="#a1a6c5"/>
+  <entry type="LiteralNumber" style="#8c6c3e"/>
+  <entry type="LiteralNumberBin" style="#8c6c3e"/>
+  <entry type="LiteralNumberHex" style="#8c6c3e"/>
+  <entry type="LiteralNumberInteger" style="#8c6c3e"/>
+  <entry type="LiteralNumberFloat" style="#8c6c3e"/>
+  <entry type="LiteralNumberIntegerLong" style="#8c6c3e"/>
+  <entry type="LiteralNumberOct" style="#8c6c3e"/>
+  <entry type="Operator" style="bold #587539"/>
+  <entry type="OperatorWord" style="bold #587539"/>
+  <entry type="Comment" style="italic #a1a6c5"/>
+  <entry type="CommentSingle" style="italic #a1a6c5"/>
+  <entry type="CommentMultiline" style="italic #a1a6c5"/>
+  <entry type="CommentSpecial" style="italic #a1a6c5"/>
+  <entry type="CommentHashbang" style="italic #a1a6c5"/>
+  <entry type="CommentPreproc" style="italic #a1a6c5"/>
+  <entry type="CommentPreprocFile" style="bold #a1a6c5"/>
+  <entry type="Generic" style="#3760bf"/>
+  <entry type="GenericInserted" style="bg:#e9e9ed #587539"/>
+  <entry type="GenericDeleted" style="#c64343 bg:#e9e9ed"/>
+  <entry type="GenericEmph" style="italic #3760bf"/>
+  <entry type="GenericStrong" style="bold #3760bf"/>
+  <entry type="GenericUnderline" style="underline #3760bf"/>
+  <entry type="GenericHeading" style="bold #8c6c3e"/>
+  <entry type="GenericSubheading" style="bold #8c6c3e"/>
+  <entry type="GenericOutput" style="#3760bf"/>
+  <entry type="GenericPrompt" style="#3760bf"/>
+  <entry type="GenericError" style="#c64343"/>
+  <entry type="GenericTraceback" style="#c64343"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/tokyonight-moon.xml b/styles/embedded/tokyonight-moon.xml
new file mode 100644
index 0000000..0af8992
--- /dev/null
+++ b/styles/embedded/tokyonight-moon.xml
@@ -0,0 +1,83 @@
+<style name="tokyonight-moon" theme="dark">
+  <entry type="Background" style="bg:#222436 #c8d3f5"/>
+  <entry type="CodeLine" style="#c8d3f5"/>
+  <entry type="Error" style="#c53b53"/>
+  <entry type="Other" style="#c8d3f5"/>
+  <entry type="LineTableTD" style=""/>
+  <entry type="LineTable" style=""/>
+  <entry type="LineHighlight" style="bg:#444a73"/>
+  <entry type="LineNumbersTable" style="#828bb8"/>
+  <entry type="LineNumbers" style="#828bb8"/>
+  <entry type="Keyword" style="#c099ff"/>
+  <entry type="KeywordReserved" style="#c099ff"/>
+  <entry type="KeywordPseudo" style="#c099ff"/>
+  <entry type="KeywordConstant" style="#ffc777"/>
+  <entry type="KeywordDeclaration" style="#c099ff"/>
+  <entry type="KeywordNamespace" style="#86e1fc"/>
+  <entry type="KeywordType" style="#4fd6be"/>
+  <entry type="Name" style="#c8d3f5"/>
+  <entry type="NameClass" style="#ff966c"/>
+  <entry type="NameConstant" style="#ff966c"/>
+  <entry type="NameDecorator" style="bold #82aaff"/>
+  <entry type="NameEntity" style="#86e1fc"/>
+  <entry type="NameException" style="#ffc777"/>
+  <entry type="NameFunction" style="#82aaff"/>
+  <entry type="NameFunctionMagic" style="#82aaff"/>
+  <entry type="NameLabel" style="#c3e88d"/>
+  <entry type="NameNamespace" style="#ffc777"/>
+  <entry type="NameProperty" style="#ffc777"/>
+  <entry type="NameTag" style="#c099ff"/>
+  <entry type="NameVariable" style="#c8d3f5"/>
+  <entry type="NameVariableClass" style="#c8d3f5"/>
+  <entry type="NameVariableGlobal" style="#c8d3f5"/>
+  <entry type="NameVariableInstance" style="#c8d3f5"/>
+  <entry type="NameVariableMagic" style="#c8d3f5"/>
+  <entry type="NameAttribute" style="#82aaff"/>
+  <entry type="NameBuiltin" style="#c3e88d"/>
+  <entry type="NameBuiltinPseudo" style="#c3e88d"/>
+  <entry type="NameOther" style="#c8d3f5"/>
+  <entry type="Literal" style="#c8d3f5"/>
+  <entry type="LiteralDate" style="#c8d3f5"/>
+  <entry type="LiteralString" style="#c3e88d"/>
+  <entry type="LiteralStringChar" style="#c3e88d"/>
+  <entry type="LiteralStringSingle" style="#c3e88d"/>
+  <entry type="LiteralStringDouble" style="#c3e88d"/>
+  <entry type="LiteralStringBacktick" style="#c3e88d"/>
+  <entry type="LiteralStringOther" style="#c3e88d"/>
+  <entry type="LiteralStringSymbol" style="#c3e88d"/>
+  <entry type="LiteralStringInterpol" style="#c3e88d"/>
+  <entry type="LiteralStringAffix" style="#c099ff"/>
+  <entry type="LiteralStringDelimiter" style="#82aaff"/>
+  <entry type="LiteralStringEscape" style="#82aaff"/>
+  <entry type="LiteralStringRegex" style="#86e1fc"/>
+  <entry type="LiteralStringDoc" style="#444a73"/>
+  <entry type="LiteralStringHeredoc" style="#444a73"/>
+  <entry type="LiteralNumber" style="#ffc777"/>
+  <entry type="LiteralNumberBin" style="#ffc777"/>
+  <entry type="LiteralNumberHex" style="#ffc777"/>
+  <entry type="LiteralNumberInteger" style="#ffc777"/>
+  <entry type="LiteralNumberFloat" style="#ffc777"/>
+  <entry type="LiteralNumberIntegerLong" style="#ffc777"/>
+  <entry type="LiteralNumberOct" style="#ffc777"/>
+  <entry type="Operator" style="bold #c3e88d"/>
+  <entry type="OperatorWord" style="bold #c3e88d"/>
+  <entry type="Comment" style="italic #444a73"/>
+  <entry type="CommentSingle" style="italic #444a73"/>
+  <entry type="CommentMultiline" style="italic #444a73"/>
+  <entry type="CommentSpecial" style="italic #444a73"/>
+  <entry type="CommentHashbang" style="italic #444a73"/>
+  <entry type="CommentPreproc" style="italic #444a73"/>
+  <entry type="CommentPreprocFile" style="bold #444a73"/>
+  <entry type="Generic" style="#c8d3f5"/>
+  <entry type="GenericInserted" style="bg:#1b1d2b #c3e88d"/>
+  <entry type="GenericDeleted" style="#c53b53 bg:#1b1d2b"/>
+  <entry type="GenericEmph" style="italic #c8d3f5"/>
+  <entry type="GenericStrong" style="bold #c8d3f5"/>
+  <entry type="GenericUnderline" style="underline #c8d3f5"/>
+  <entry type="GenericHeading" style="bold #ffc777"/>
+  <entry type="GenericSubheading" style="bold #ffc777"/>
+  <entry type="GenericOutput" style="#c8d3f5"/>
+  <entry type="GenericPrompt" style="#c8d3f5"/>
+  <entry type="GenericError" style="#c53b53"/>
+  <entry type="GenericTraceback" style="#c53b53"/>
+</style>
diff --git a/styles/embedded/tokyonight-night.xml b/styles/embedded/tokyonight-night.xml
new file mode 100644
index 0000000..a82ed38
--- /dev/null
+++ b/styles/embedded/tokyonight-night.xml
@@ -0,0 +1,83 @@
+<style name="tokyonight-night" theme="dark">
+  <entry type="Background" style="bg:#1a1b26 #c0caf5"/>
+  <entry type="CodeLine" style="#c0caf5"/>
+  <entry type="Error" style="#db4b4b"/>
+  <entry type="Other" style="#c0caf5"/>
+  <entry type="LineTableTD" style=""/>
+  <entry type="LineTable" style=""/>
+  <entry type="LineHighlight" style="bg:#414868"/>
+  <entry type="LineNumbersTable" style="#a9b1d6"/>
+  <entry type="LineNumbers" style="#a9b1d6"/>
+  <entry type="Keyword" style="#bb9af7"/>
+  <entry type="KeywordReserved" style="#bb9af7"/>
+  <entry type="KeywordPseudo" style="#bb9af7"/>
+  <entry type="KeywordConstant" style="#e0af68"/>
+  <entry type="KeywordDeclaration" style="#9d7cd8"/>
+  <entry type="KeywordNamespace" style="#7dcfff"/>
+  <entry type="KeywordType" style="#41a6b5"/>
+  <entry type="Name" style="#c0caf5"/>
+  <entry type="NameClass" style="#ff9e64"/>
+  <entry type="NameConstant" style="#ff9e64"/>
+  <entry type="NameDecorator" style="bold #7aa2f7"/>
+  <entry type="NameEntity" style="#7dcfff"/>
+  <entry type="NameException" style="#e0af68"/>
+  <entry type="NameFunction" style="#7aa2f7"/>
+  <entry type="NameFunctionMagic" style="#7aa2f7"/>
+  <entry type="NameLabel" style="#9ece6a"/>
+  <entry type="NameNamespace" style="#e0af68"/>
+  <entry type="NameProperty" style="#e0af68"/>
+  <entry type="NameTag" style="#bb9af7"/>
+  <entry type="NameVariable" style="#c0caf5"/>
+  <entry type="NameVariableClass" style="#c0caf5"/>
+  <entry type="NameVariableGlobal" style="#c0caf5"/>
+  <entry type="NameVariableInstance" style="#c0caf5"/>
+  <entry type="NameVariableMagic" style="#c0caf5"/>
+  <entry type="NameAttribute" style="#7aa2f7"/>
+  <entry type="NameBuiltin" style="#9ece6a"/>
+  <entry type="NameBuiltinPseudo" style="#9ece6a"/>
+  <entry type="NameOther" style="#c0caf5"/>
+  <entry type="Literal" style="#c0caf5"/>
+  <entry type="LiteralDate" style="#c0caf5"/>
+  <entry type="LiteralString" style="#9ece6a"/>
+  <entry type="LiteralStringChar" style="#9ece6a"/>
+  <entry type="LiteralStringSingle" style="#9ece6a"/>
+  <entry type="LiteralStringDouble" style="#9ece6a"/>
+  <entry type="LiteralStringBacktick" style="#9ece6a"/>
+  <entry type="LiteralStringOther" style="#9ece6a"/>
+  <entry type="LiteralStringSymbol" style="#9ece6a"/>
+  <entry type="LiteralStringInterpol" style="#9ece6a"/>
+  <entry type="LiteralStringAffix" style="#9d7cd8"/>
+  <entry type="LiteralStringDelimiter" style="#7aa2f7"/>
+  <entry type="LiteralStringEscape" style="#7aa2f7"/>
+  <entry type="LiteralStringRegex" style="#7dcfff"/>
+  <entry type="LiteralStringDoc" style="#414868"/>
+  <entry type="LiteralStringHeredoc" style="#414868"/>
+  <entry type="LiteralNumber" style="#e0af68"/>
+  <entry type="LiteralNumberBin" style="#e0af68"/>
+  <entry type="LiteralNumberHex" style="#e0af68"/>
+  <entry type="LiteralNumberInteger" style="#e0af68"/>
+  <entry type="LiteralNumberFloat" style="#e0af68"/>
+  <entry type="LiteralNumberIntegerLong" style="#e0af68"/>
+  <entry type="LiteralNumberOct" style="#e0af68"/>
+  <entry type="Operator" style="bold #9ece6a"/>
+  <entry type="OperatorWord" style="bold #9ece6a"/>
+  <entry type="Comment" style="italic #414868"/>
+  <entry type="CommentSingle" style="italic #414868"/>
+  <entry type="CommentMultiline" style="italic #414868"/>
+  <entry type="CommentSpecial" style="italic #414868"/>
+  <entry type="CommentHashbang" style="italic #414868"/>
+  <entry type="CommentPreproc" style="italic #414868"/>
+  <entry type="CommentPreprocFile" style="bold #414868"/>
+  <entry type="Generic" style="#c0caf5"/>
+  <entry type="GenericInserted" style="bg:#15161e #9ece6a"/>
+  <entry type="GenericDeleted" style="#db4b4b bg:#15161e"/>
+  <entry type="GenericEmph" style="italic #c0caf5"/>
+  <entry type="GenericStrong" style="bold #c0caf5"/>
+  <entry type="GenericUnderline" style="underline #c0caf5"/>
+  <entry type="GenericHeading" style="bold #e0af68"/>
+  <entry type="GenericSubheading" style="bold #e0af68"/>
+  <entry type="GenericOutput" style="#c0caf5"/>
+  <entry type="GenericPrompt" style="#c0caf5"/>
+  <entry type="GenericError" style="#db4b4b"/>
+  <entry type="GenericTraceback" style="#db4b4b"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/tokyonight-storm.xml b/styles/embedded/tokyonight-storm.xml
new file mode 100644
index 0000000..3c3773a
--- /dev/null
+++ b/styles/embedded/tokyonight-storm.xml
@@ -0,0 +1,83 @@
+<style name="tokyonight-storm" theme="dark">
+  <entry type="Background" style="bg:#1a1b26 #c0caf5"/>
+  <entry type="CodeLine" style="#c0caf5"/>
+  <entry type="Error" style="#db4b4b"/>
+  <entry type="Other" style="#c0caf5"/>
+  <entry type="LineTableTD" style=""/>
+  <entry type="LineTable" style=""/>
+  <entry type="LineHighlight" style="bg:#414868"/>
+  <entry type="LineNumbersTable" style="#a9b1d6"/>
+  <entry type="LineNumbers" style="#a9b1d6"/>
+  <entry type="Keyword" style="#bb9af7"/>
+  <entry type="KeywordReserved" style="#bb9af7"/>
+  <entry type="KeywordPseudo" style="#bb9af7"/>
+  <entry type="KeywordConstant" style="#e0af68"/>
+  <entry type="KeywordDeclaration" style="#9d7cd8"/>
+  <entry type="KeywordNamespace" style="#7dcfff"/>
+  <entry type="KeywordType" style="#41a6b5"/>
+  <entry type="Name" style="#c0caf5"/>
+  <entry type="NameClass" style="#ff9e64"/>
+  <entry type="NameConstant" style="#ff9e64"/>
+  <entry type="NameDecorator" style="bold #7aa2f7"/>
+  <entry type="NameEntity" style="#7dcfff"/>
+  <entry type="NameException" style="#e0af68"/>
+  <entry type="NameFunction" style="#7aa2f7"/>
+  <entry type="NameFunctionMagic" style="#7aa2f7"/>
+  <entry type="NameLabel" style="#9ece6a"/>
+  <entry type="NameNamespace" style="#e0af68"/>
+  <entry type="NameProperty" style="#e0af68"/>
+  <entry type="NameTag" style="#bb9af7"/>
+  <entry type="NameVariable" style="#c0caf5"/>
+  <entry type="NameVariableClass" style="#c0caf5"/>
+  <entry type="NameVariableGlobal" style="#c0caf5"/>
+  <entry type="NameVariableInstance" style="#c0caf5"/>
+  <entry type="NameVariableMagic" style="#c0caf5"/>
+  <entry type="NameAttribute" style="#7aa2f7"/>
+  <entry type="NameBuiltin" style="#9ece6a"/>
+  <entry type="NameBuiltinPseudo" style="#9ece6a"/>
+  <entry type="NameOther" style="#c0caf5"/>
+  <entry type="Literal" style="#c0caf5"/>
+  <entry type="LiteralDate" style="#c0caf5"/>
+  <entry type="LiteralString" style="#9ece6a"/>
+  <entry type="LiteralStringChar" style="#9ece6a"/>
+  <entry type="LiteralStringSingle" style="#9ece6a"/>
+  <entry type="LiteralStringDouble" style="#9ece6a"/>
+  <entry type="LiteralStringBacktick" style="#9ece6a"/>
+  <entry type="LiteralStringOther" style="#9ece6a"/>
+  <entry type="LiteralStringSymbol" style="#9ece6a"/>
+  <entry type="LiteralStringInterpol" style="#9ece6a"/>
+  <entry type="LiteralStringAffix" style="#9d7cd8"/>
+  <entry type="LiteralStringDelimiter" style="#7aa2f7"/>
+  <entry type="LiteralStringEscape" style="#7aa2f7"/>
+  <entry type="LiteralStringRegex" style="#7dcfff"/>
+  <entry type="LiteralStringDoc" style="#414868"/>
+  <entry type="LiteralStringHeredoc" style="#414868"/>
+  <entry type="LiteralNumber" style="#e0af68"/>
+  <entry type="LiteralNumberBin" style="#e0af68"/>
+  <entry type="LiteralNumberHex" style="#e0af68"/>
+  <entry type="LiteralNumberInteger" style="#e0af68"/>
+  <entry type="LiteralNumberFloat" style="#e0af68"/>
+  <entry type="LiteralNumberIntegerLong" style="#e0af68"/>
+  <entry type="LiteralNumberOct" style="#e0af68"/>
+  <entry type="Operator" style="bold #9ece6a"/>
+  <entry type="OperatorWord" style="bold #9ece6a"/>
+  <entry type="Comment" style="italic #414868"/>
+  <entry type="CommentSingle" style="italic #414868"/>
+  <entry type="CommentMultiline" style="italic #414868"/>
+  <entry type="CommentSpecial" style="italic #414868"/>
+  <entry type="CommentHashbang" style="italic #414868"/>
+  <entry type="CommentPreproc" style="italic #414868"/>
+  <entry type="CommentPreprocFile" style="bold #414868"/>
+  <entry type="Generic" style="#c0caf5"/>
+  <entry type="GenericInserted" style="bg:#15161e #9ece6a"/>
+  <entry type="GenericDeleted" style="#db4b4b bg:#15161e"/>
+  <entry type="GenericEmph" style="italic #c0caf5"/>
+  <entry type="GenericStrong" style="bold #c0caf5"/>
+  <entry type="GenericUnderline" style="underline #c0caf5"/>
+  <entry type="GenericHeading" style="bold #e0af68"/>
+  <entry type="GenericSubheading" style="bold #e0af68"/>
+  <entry type="GenericOutput" style="#c0caf5"/>
+  <entry type="GenericPrompt" style="#c0caf5"/>
+  <entry type="GenericError" style="#db4b4b"/>
+  <entry type="GenericTraceback" style="#db4b4b"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/trac.xml b/styles/embedded/trac.xml
new file mode 100644
index 0000000..377989c
--- /dev/null
+++ b/styles/embedded/trac.xml
@@ -0,0 +1,35 @@
+<style name="trac" theme="light">
+  <entry type="Error" style="#a61717 bg:#e3d2d2"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="bold"/>
+  <entry type="KeywordType" style="#445588"/>
+  <entry type="NameAttribute" style="#008080"/>
+  <entry type="NameBuiltin" style="#999999"/>
+  <entry type="NameClass" style="bold #445588"/>
+  <entry type="NameConstant" style="#008080"/>
+  <entry type="NameEntity" style="#800080"/>
+  <entry type="NameException" style="bold #990000"/>
+  <entry type="NameFunction" style="bold #990000"/>
+  <entry type="NameNamespace" style="#555555"/>
+  <entry type="NameTag" style="#000080"/>
+  <entry type="NameVariable" style="#008080"/>
+  <entry type="LiteralString" style="#bb8844"/>
+  <entry type="LiteralStringRegex" style="#808000"/>
+  <entry type="LiteralNumber" style="#009999"/>
+  <entry type="Operator" style="bold"/>
+  <entry type="Comment" style="italic #999988"/>
+  <entry type="CommentSpecial" style="bold #999999"/>
+  <entry type="CommentPreproc" style="bold noitalic #999999"/>
+  <entry type="GenericDeleted" style="#000000 bg:#ffdddd"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#aa0000"/>
+  <entry type="GenericHeading" style="#999999"/>
+  <entry type="GenericInserted" style="#000000 bg:#ddffdd"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="#555555"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#aaaaaa"/>
+  <entry type="GenericTraceback" style="#aa0000"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="TextWhitespace" style="#bbbbbb"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/vim.xml b/styles/embedded/vim.xml
new file mode 100644
index 0000000..2920512
--- /dev/null
+++ b/styles/embedded/vim.xml
@@ -0,0 +1,29 @@
+<style name="vim" theme="dark">
+  <entry type="Error" style="border:#ff0000"/>
+  <entry type="Background" style="#cccccc bg:#000000"/>
+  <entry type="Keyword" style="#cdcd00"/>
+  <entry type="KeywordDeclaration" style="#00cd00"/>
+  <entry type="KeywordNamespace" style="#cd00cd"/>
+  <entry type="KeywordType" style="#00cd00"/>
+  <entry type="NameBuiltin" style="#cd00cd"/>
+  <entry type="NameClass" style="#00cdcd"/>
+  <entry type="NameException" style="bold #666699"/>
+  <entry type="NameVariable" style="#00cdcd"/>
+  <entry type="LiteralString" style="#cd0000"/>
+  <entry type="LiteralNumber" style="#cd00cd"/>
+  <entry type="Operator" style="#3399cc"/>
+  <entry type="OperatorWord" style="#cdcd00"/>
+  <entry type="Comment" style="#000080"/>
+  <entry type="CommentSpecial" style="bold #cd0000"/>
+  <entry type="GenericDeleted" style="#cd0000"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericError" style="#ff0000"/>
+  <entry type="GenericHeading" style="bold #000080"/>
+  <entry type="GenericInserted" style="#00cd00"/>
+  <entry type="GenericOutput" style="#888888"/>
+  <entry type="GenericPrompt" style="bold #000080"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold #800080"/>
+  <entry type="GenericTraceback" style="#0044dd"/>
+  <entry type="GenericUnderline" style="underline"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/vs.xml b/styles/embedded/vs.xml
new file mode 100644
index 0000000..b9fa734
--- /dev/null
+++ b/styles/embedded/vs.xml
@@ -0,0 +1,16 @@
+<style name="vs" theme="light">
+  <entry type="Error" style="border:#ff0000"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="#0000ff"/>
+  <entry type="KeywordType" style="#2b91af"/>
+  <entry type="NameClass" style="#2b91af"/>
+  <entry type="LiteralString" style="#a31515"/>
+  <entry type="OperatorWord" style="#0000ff"/>
+  <entry type="Comment" style="#008000"/>
+  <entry type="CommentPreproc" style="#0000ff"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericHeading" style="bold"/>
+  <entry type="GenericPrompt" style="bold"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="bold"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/vulcan.xml b/styles/embedded/vulcan.xml
new file mode 100644
index 0000000..717ffd2
--- /dev/null
+++ b/styles/embedded/vulcan.xml
@@ -0,0 +1,74 @@
+<style name="vulcan" theme="dark">
+  <entry type="Other" style="#c9c9c9"/>
+  <entry type="Error" style="#cf5967"/>
+  <entry type="Background" style="bg:#282c34"/>
+  <entry type="Keyword" style="#7fbaf5"/>
+  <entry type="KeywordConstant" style="#cf5967 bg:#43454f"/>
+  <entry type="KeywordDeclaration" style="#7fbaf5"/>
+  <entry type="KeywordNamespace" style="#bc74c4"/>
+  <entry type="KeywordPseudo" style="#bc74c4"/>
+  <entry type="KeywordReserved" style="#7fbaf5"/>
+  <entry type="KeywordType" style="bold #57c7ff"/>
+  <entry type="Name" style="#c9c9c9"/>
+  <entry type="NameAttribute" style="#bc74c4"/>
+  <entry type="NameBuiltin" style="#7fbaf5"/>
+  <entry type="NameBuiltinPseudo" style="#7fbaf5"/>
+  <entry type="NameClass" style="#ecbe7b"/>
+  <entry type="NameConstant" style="#ecbe7b"/>
+  <entry type="NameDecorator" style="#ecbe7b"/>
+  <entry type="NameEntity" style="#c9c9c9"/>
+  <entry type="NameException" style="#cf5967"/>
+  <entry type="NameFunction" style="#57c7ff"/>
+  <entry type="NameLabel" style="#cf5967"/>
+  <entry type="NameNamespace" style="#c9c9c9"/>
+  <entry type="NameOther" style="#c9c9c9"/>
+  <entry type="NameTag" style="#bc74c4"/>
+  <entry type="NameVariable" style="italic #bc74c4"/>
+  <entry type="NameVariableClass" style="bold #57c7ff"/>
+  <entry type="NameVariableGlobal" style="#ecbe7b"/>
+  <entry type="NameVariableInstance" style="#57c7ff"/>
+  <entry type="Literal" style="#c9c9c9"/>
+  <entry type="LiteralDate" style="#57c7ff"/>
+  <entry type="LiteralString" style="#82cc6a"/>
+  <entry type="LiteralStringBacktick" style="#57c7ff"/>
+  <entry type="LiteralStringChar" style="#57c7ff"/>
+  <entry type="LiteralStringDoc" style="#82cc6a"/>
+  <entry type="LiteralStringDouble" style="#82cc6a"/>
+  <entry type="LiteralStringEscape" style="#56b6c2"/>
+  <entry type="LiteralStringHeredoc" style="#56b6c2"/>
+  <entry type="LiteralStringInterpol" style="#82cc6a"/>
+  <entry type="LiteralStringOther" style="#82cc6a"/>
+  <entry type="LiteralStringRegex" style="#57c7ff"/>
+  <entry type="LiteralStringSingle" style="#82cc6a"/>
+  <entry type="LiteralStringSymbol" style="#82cc6a"/>
+  <entry type="LiteralNumber" style="#56b6c2"/>
+  <entry type="LiteralNumberBin" style="#57c7ff"/>
+  <entry type="LiteralNumberFloat" style="#56b6c2"/>
+  <entry type="LiteralNumberHex" style="#57c7ff"/>
+  <entry type="LiteralNumberInteger" style="#56b6c2"/>
+  <entry type="LiteralNumberIntegerLong" style="#56b6c2"/>
+  <entry type="LiteralNumberOct" style="#57c7ff"/>
+  <entry type="Operator" style="#bc74c4"/>
+  <entry type="OperatorWord" style="#bc74c4"/>
+  <entry type="Punctuation" style="#56b6c2"/>
+  <entry type="Comment" style="#3e4460"/>
+  <entry type="CommentHashbang" style="italic #3e4460"/>
+  <entry type="CommentMultiline" style="#3e4460"/>
+  <entry type="CommentSingle" style="#3e4460"/>
+  <entry type="CommentSpecial" style="italic #bc74c4"/>
+  <entry type="CommentPreproc" style="#7fbaf5"/>
+  <entry type="Generic" style="#c9c9c9"/>
+  <entry type="GenericDeleted" style="#cf5967"/>
+  <entry type="GenericEmph" style="underline #c9c9c9"/>
+  <entry type="GenericError" style="bold #cf5967"/>
+  <entry type="GenericHeading" style="bold #ecbe7b"/>
+  <entry type="GenericInserted" style="#ecbe7b"/>
+  <entry type="GenericOutput" style="#43454f"/>
+  <entry type="GenericPrompt" style="#c9c9c9"/>
+  <entry type="GenericStrong" style="bold #cf5967"/>
+  <entry type="GenericSubheading" style="italic #cf5967"/>
+  <entry type="GenericTraceback" style="#c9c9c9"/>
+  <entry type="GenericUnderline" style="underline"/>
+  <entry type="Text" style="#c9c9c9"/>
+  <entry type="TextWhitespace" style="#c9c9c9"/>
+</style>
diff --git a/styles/embedded/witchhazel.xml b/styles/embedded/witchhazel.xml
new file mode 100644
index 0000000..4c175c9
--- /dev/null
+++ b/styles/embedded/witchhazel.xml
@@ -0,0 +1,31 @@
+<style name="witchhazel" theme="dark">
+  <entry type="Error" style="#960050 bg:#1e0010"/>
+  <entry type="Background" style="bg:#433e56"/>
+  <entry type="Keyword" style="#c2ffdf"/>
+  <entry type="KeywordNamespace" style="#ffb8d1"/>
+  <entry type="Name" style="#f8f8f2"/>
+  <entry type="NameAttribute" style="#ceb1ff"/>
+  <entry type="NameBuiltinPseudo" style="#80cbc4"/>
+  <entry type="NameClass" style="#ceb1ff"/>
+  <entry type="NameConstant" style="#c5a3ff"/>
+  <entry type="NameDecorator" style="#ceb1ff"/>
+  <entry type="NameException" style="#ceb1ff"/>
+  <entry type="NameFunction" style="#ceb1ff"/>
+  <entry type="NameProperty" style="#f8f8f2"/>
+  <entry type="NameTag" style="#ffb8d1"/>
+  <entry type="NameVariable" style="#f8f8f2"/>
+  <entry type="Literal" style="#ae81ff"/>
+  <entry type="LiteralDate" style="#e6db74"/>
+  <entry type="LiteralString" style="#1bc5e0"/>
+  <entry type="LiteralNumber" style="#c5a3ff"/>
+  <entry type="Operator" style="#ffb8d1"/>
+  <entry type="Punctuation" style="#f8f8f2"/>
+  <entry type="Comment" style="#b0bec5"/>
+  <entry type="GenericDeleted" style="#f92672"/>
+  <entry type="GenericEmph" style="italic"/>
+  <entry type="GenericInserted" style="#a6e22e"/>
+  <entry type="GenericStrong" style="bold"/>
+  <entry type="GenericSubheading" style="#75715e"/>
+  <entry type="Text" style="#f8f8f2"/>
+  <entry type="TextWhitespace" style="#a8757b"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/xcode-dark.xml b/styles/embedded/xcode-dark.xml
new file mode 100644
index 0000000..d2ba679
--- /dev/null
+++ b/styles/embedded/xcode-dark.xml
@@ -0,0 +1,31 @@
+<style name="xcode-dark" theme="dark">
+  <entry type="Error" style="#960050"/>
+  <entry type="Background" style="#ffffff bg:#1f1f24"/>
+  <entry type="Keyword" style="#fc5fa3"/>
+  <entry type="KeywordConstant" style="#fc5fa3"/>
+  <entry type="KeywordDeclaration" style="#fc5fa3"/>
+  <entry type="KeywordReserved" style="#fc5fa3"/>
+  <entry type="Name" style="#ffffff"/>
+  <entry type="NameBuiltin" style="#d0a8ff"/>
+  <entry type="NameBuiltinPseudo" style="#a167e6"/>
+  <entry type="NameClass" style="#5dd8ff"/>
+  <entry type="NameFunction" style="#41a1c0"/>
+  <entry type="NameVariable" style="#41a1c0"/>
+  <entry type="LiteralString" style="#fc6a5d"/>
+  <entry type="LiteralStringEscape" style="#fc6a5d"/>
+  <entry type="LiteralStringInterpol" style="#ffffff"/>
+  <entry type="LiteralNumber" style="#d0bf69"/>
+  <entry type="LiteralNumberBin" style="#d0bf69"/>
+  <entry type="LiteralNumberFloat" style="#d0bf69"/>
+  <entry type="LiteralNumberHex" style="#d0bf69"/>
+  <entry type="LiteralNumberInteger" style="#d0bf69"/>
+  <entry type="LiteralNumberOct" style="#d0bf69"/>
+  <entry type="Operator" style="#ffffff"/>
+  <entry type="Punctuation" style="#ffffff"/>
+  <entry type="Comment" style="#6c7986"/>
+  <entry type="CommentMultiline" style="#6c7986"/>
+  <entry type="CommentSingle" style="#6c7986"/>
+  <entry type="CommentSpecial" style="italic #6c7986"/>
+  <entry type="CommentPreproc" style="#fd8f3f"/>
+  <entry type="Text" style="#ffffff"/>
+</style>
\ No newline at end of file
diff --git a/styles/embedded/xcode.xml b/styles/embedded/xcode.xml
new file mode 100644
index 0000000..9bfa0d1
--- /dev/null
+++ b/styles/embedded/xcode.xml
@@ -0,0 +1,22 @@
+<style name="xcode" theme="light">
+  <entry type="Error" style="#000000"/>
+  <entry type="Background" style="bg:#ffffff"/>
+  <entry type="Keyword" style="#a90d91"/>
+  <entry type="Name" style="#000000"/>
+  <entry type="NameAttribute" style="#836c28"/>
+  <entry type="NameBuiltin" style="#a90d91"/>
+  <entry type="NameBuiltinPseudo" style="#5b269a"/>
+  <entry type="NameClass" style="#3f6e75"/>
+  <entry type="NameDecorator" style="#000000"/>
+  <entry type="NameFunction" style="#000000"/>
+  <entry type="NameLabel" style="#000000"/>
+  <entry type="NameTag" style="#000000"/>
+  <entry type="NameVariable" style="#000000"/>
+  <entry type="Literal" style="#1c01ce"/>
+  <entry type="LiteralString" style="#c41a16"/>
+  <entry type="LiteralStringChar" style="#2300ce"/>
+  <entry type="LiteralNumber" style="#1c01ce"/>
+  <entry type="Operator" style="#000000"/>
+  <entry type="Comment" style="#177500"/>
+  <entry type="CommentPreproc" style="#633820"/>
+</style>
\ No newline at end of file
diff --git a/tokentype_enumer.go b/tokentype_enumer.go
new file mode 100644
index 0000000..696e9ce
--- /dev/null
+++ b/tokentype_enumer.go
@@ -0,0 +1,573 @@
+// Code generated by "enumer -text -type TokenType"; DO NOT EDIT.
+
+package chroma
+
+import (
+	"fmt"
+	"strings"
+)
+
+const _TokenTypeName = "NoneOtherErrorCodeLineLineLinkLineTableTDLineTableLineHighlightLineNumbersTableLineNumbersLinePreWrapperBackgroundEOFTypeKeywordKeywordConstantKeywordDeclarationKeywordNamespaceKeywordPseudoKeywordReservedKeywordTypeNameNameAttributeNameBuiltinNameBuiltinPseudoNameClassNameConstantNameDecoratorNameEntityNameExceptionNameFunctionNameFunctionMagicNameKeywordNameLabelNameNamespaceNameOperatorNameOtherNamePseudoNamePropertyNameTagNameVariableNameVariableAnonymousNameVariableClassNameVariableGlobalNameVariableInstanceNameVariableMagicLiteralLiteralDateLiteralOtherLiteralStringLiteralStringAffixLiteralStringAtomLiteralStringBacktickLiteralStringBooleanLiteralStringCharLiteralStringDelimiterLiteralStringDocLiteralStringDoubleLiteralStringEscapeLiteralStringHeredocLiteralStringInterpolLiteralStringNameLiteralStringOtherLiteralStringRegexLiteralStringSingleLiteralStringSymbolLiteralNumberLiteralNumberBinLiteralNumberFloatLiteralNumberHexLiteralNumberIntegerLiteralNumberIntegerLongLiteralNumberOctOperatorOperatorWordPunctuationCommentCommentHashbangCommentMultilineCommentSingleCommentSpecialCommentPreprocCommentPreprocFileGenericGenericDeletedGenericEmphGenericErrorGenericHeadingGenericInsertedGenericOutputGenericPromptGenericStrongGenericSubheadingGenericTracebackGenericUnderlineTextTextWhitespaceTextSymbolTextPunctuation"
+const _TokenTypeLowerName = "noneothererrorcodelinelinelinklinetabletdlinetablelinehighlightlinenumberstablelinenumberslineprewrapperbackgroundeoftypekeywordkeywordconstantkeyworddeclarationkeywordnamespacekeywordpseudokeywordreservedkeywordtypenamenameattributenamebuiltinnamebuiltinpseudonameclassnameconstantnamedecoratornameentitynameexceptionnamefunctionnamefunctionmagicnamekeywordnamelabelnamenamespacenameoperatornameothernamepseudonamepropertynametagnamevariablenamevariableanonymousnamevariableclassnamevariableglobalnamevariableinstancenamevariablemagicliteralliteraldateliteralotherliteralstringliteralstringaffixliteralstringatomliteralstringbacktickliteralstringbooleanliteralstringcharliteralstringdelimiterliteralstringdocliteralstringdoubleliteralstringescapeliteralstringheredocliteralstringinterpolliteralstringnameliteralstringotherliteralstringregexliteralstringsingleliteralstringsymbolliteralnumberliteralnumberbinliteralnumberfloatliteralnumberhexliteralnumberintegerliteralnumberintegerlongliteralnumberoctoperatoroperatorwordpunctuationcommentcommenthashbangcommentmultilinecommentsinglecommentspecialcommentpreproccommentpreprocfilegenericgenericdeletedgenericemphgenericerrorgenericheadinggenericinsertedgenericoutputgenericpromptgenericstronggenericsubheadinggenerictracebackgenericunderlinetexttextwhitespacetextsymboltextpunctuation"
+
+var _TokenTypeMap = map[TokenType]string{
+	-13:  _TokenTypeName[0:4],
+	-12:  _TokenTypeName[4:9],
+	-11:  _TokenTypeName[9:14],
+	-10:  _TokenTypeName[14:22],
+	-9:   _TokenTypeName[22:30],
+	-8:   _TokenTypeName[30:41],
+	-7:   _TokenTypeName[41:50],
+	-6:   _TokenTypeName[50:63],
+	-5:   _TokenTypeName[63:79],
+	-4:   _TokenTypeName[79:90],
+	-3:   _TokenTypeName[90:94],
+	-2:   _TokenTypeName[94:104],
+	-1:   _TokenTypeName[104:114],
+	0:    _TokenTypeName[114:121],
+	1000: _TokenTypeName[121:128],
+	1001: _TokenTypeName[128:143],
+	1002: _TokenTypeName[143:161],
+	1003: _TokenTypeName[161:177],
+	1004: _TokenTypeName[177:190],
+	1005: _TokenTypeName[190:205],
+	1006: _TokenTypeName[205:216],
+	2000: _TokenTypeName[216:220],
+	2001: _TokenTypeName[220:233],
+	2002: _TokenTypeName[233:244],
+	2003: _TokenTypeName[244:261],
+	2004: _TokenTypeName[261:270],
+	2005: _TokenTypeName[270:282],
+	2006: _TokenTypeName[282:295],
+	2007: _TokenTypeName[295:305],
+	2008: _TokenTypeName[305:318],
+	2009: _TokenTypeName[318:330],
+	2010: _TokenTypeName[330:347],
+	2011: _TokenTypeName[347:358],
+	2012: _TokenTypeName[358:367],
+	2013: _TokenTypeName[367:380],
+	2014: _TokenTypeName[380:392],
+	2015: _TokenTypeName[392:401],
+	2016: _TokenTypeName[401:411],
+	2017: _TokenTypeName[411:423],
+	2018: _TokenTypeName[423:430],
+	2019: _TokenTypeName[430:442],
+	2020: _TokenTypeName[442:463],
+	2021: _TokenTypeName[463:480],
+	2022: _TokenTypeName[480:498],
+	2023: _TokenTypeName[498:518],
+	2024: _TokenTypeName[518:535],
+	3000: _TokenTypeName[535:542],
+	3001: _TokenTypeName[542:553],
+	3002: _TokenTypeName[553:565],
+	3100: _TokenTypeName[565:578],
+	3101: _TokenTypeName[578:596],
+	3102: _TokenTypeName[596:613],
+	3103: _TokenTypeName[613:634],
+	3104: _TokenTypeName[634:654],
+	3105: _TokenTypeName[654:671],
+	3106: _TokenTypeName[671:693],
+	3107: _TokenTypeName[693:709],
+	3108: _TokenTypeName[709:728],
+	3109: _TokenTypeName[728:747],
+	3110: _TokenTypeName[747:767],
+	3111: _TokenTypeName[767:788],
+	3112: _TokenTypeName[788:805],
+	3113: _TokenTypeName[805:823],
+	3114: _TokenTypeName[823:841],
+	3115: _TokenTypeName[841:860],
+	3116: _TokenTypeName[860:879],
+	3200: _TokenTypeName[879:892],
+	3201: _TokenTypeName[892:908],
+	3202: _TokenTypeName[908:926],
+	3203: _TokenTypeName[926:942],
+	3204: _TokenTypeName[942:962],
+	3205: _TokenTypeName[962:986],
+	3206: _TokenTypeName[986:1002],
+	4000: _TokenTypeName[1002:1010],
+	4001: _TokenTypeName[1010:1022],
+	5000: _TokenTypeName[1022:1033],
+	6000: _TokenTypeName[1033:1040],
+	6001: _TokenTypeName[1040:1055],
+	6002: _TokenTypeName[1055:1071],
+	6003: _TokenTypeName[1071:1084],
+	6004: _TokenTypeName[1084:1098],
+	6100: _TokenTypeName[1098:1112],
+	6101: _TokenTypeName[1112:1130],
+	7000: _TokenTypeName[1130:1137],
+	7001: _TokenTypeName[1137:1151],
+	7002: _TokenTypeName[1151:1162],
+	7003: _TokenTypeName[1162:1174],
+	7004: _TokenTypeName[1174:1188],
+	7005: _TokenTypeName[1188:1203],
+	7006: _TokenTypeName[1203:1216],
+	7007: _TokenTypeName[1216:1229],
+	7008: _TokenTypeName[1229:1242],
+	7009: _TokenTypeName[1242:1259],
+	7010: _TokenTypeName[1259:1275],
+	7011: _TokenTypeName[1275:1291],
+	8000: _TokenTypeName[1291:1295],
+	8001: _TokenTypeName[1295:1309],
+	8002: _TokenTypeName[1309:1319],
+	8003: _TokenTypeName[1319:1334],
+}
+
+func (i TokenType) String() string {
+	if str, ok := _TokenTypeMap[i]; ok {
+		return str
+	}
+	return fmt.Sprintf("TokenType(%d)", i)
+}
+
+// An "invalid array index" compiler error signifies that the constant values have changed.
+// Re-run the stringer command to generate them again.
+func _TokenTypeNoOp() {
+	var x [1]struct{}
+	_ = x[None-(-13)]
+	_ = x[Other-(-12)]
+	_ = x[Error-(-11)]
+	_ = x[CodeLine-(-10)]
+	_ = x[LineLink-(-9)]
+	_ = x[LineTableTD-(-8)]
+	_ = x[LineTable-(-7)]
+	_ = x[LineHighlight-(-6)]
+	_ = x[LineNumbersTable-(-5)]
+	_ = x[LineNumbers-(-4)]
+	_ = x[Line-(-3)]
+	_ = x[PreWrapper-(-2)]
+	_ = x[Background-(-1)]
+	_ = x[EOFType-(0)]
+	_ = x[Keyword-(1000)]
+	_ = x[KeywordConstant-(1001)]
+	_ = x[KeywordDeclaration-(1002)]
+	_ = x[KeywordNamespace-(1003)]
+	_ = x[KeywordPseudo-(1004)]
+	_ = x[KeywordReserved-(1005)]
+	_ = x[KeywordType-(1006)]
+	_ = x[Name-(2000)]
+	_ = x[NameAttribute-(2001)]
+	_ = x[NameBuiltin-(2002)]
+	_ = x[NameBuiltinPseudo-(2003)]
+	_ = x[NameClass-(2004)]
+	_ = x[NameConstant-(2005)]
+	_ = x[NameDecorator-(2006)]
+	_ = x[NameEntity-(2007)]
+	_ = x[NameException-(2008)]
+	_ = x[NameFunction-(2009)]
+	_ = x[NameFunctionMagic-(2010)]
+	_ = x[NameKeyword-(2011)]
+	_ = x[NameLabel-(2012)]
+	_ = x[NameNamespace-(2013)]
+	_ = x[NameOperator-(2014)]
+	_ = x[NameOther-(2015)]
+	_ = x[NamePseudo-(2016)]
+	_ = x[NameProperty-(2017)]
+	_ = x[NameTag-(2018)]
+	_ = x[NameVariable-(2019)]
+	_ = x[NameVariableAnonymous-(2020)]
+	_ = x[NameVariableClass-(2021)]
+	_ = x[NameVariableGlobal-(2022)]
+	_ = x[NameVariableInstance-(2023)]
+	_ = x[NameVariableMagic-(2024)]
+	_ = x[Literal-(3000)]
+	_ = x[LiteralDate-(3001)]
+	_ = x[LiteralOther-(3002)]
+	_ = x[LiteralString-(3100)]
+	_ = x[LiteralStringAffix-(3101)]
+	_ = x[LiteralStringAtom-(3102)]
+	_ = x[LiteralStringBacktick-(3103)]
+	_ = x[LiteralStringBoolean-(3104)]
+	_ = x[LiteralStringChar-(3105)]
+	_ = x[LiteralStringDelimiter-(3106)]
+	_ = x[LiteralStringDoc-(3107)]
+	_ = x[LiteralStringDouble-(3108)]
+	_ = x[LiteralStringEscape-(3109)]
+	_ = x[LiteralStringHeredoc-(3110)]
+	_ = x[LiteralStringInterpol-(3111)]
+	_ = x[LiteralStringName-(3112)]
+	_ = x[LiteralStringOther-(3113)]
+	_ = x[LiteralStringRegex-(3114)]
+	_ = x[LiteralStringSingle-(3115)]
+	_ = x[LiteralStringSymbol-(3116)]
+	_ = x[LiteralNumber-(3200)]
+	_ = x[LiteralNumberBin-(3201)]
+	_ = x[LiteralNumberFloat-(3202)]
+	_ = x[LiteralNumberHex-(3203)]
+	_ = x[LiteralNumberInteger-(3204)]
+	_ = x[LiteralNumberIntegerLong-(3205)]
+	_ = x[LiteralNumberOct-(3206)]
+	_ = x[Operator-(4000)]
+	_ = x[OperatorWord-(4001)]
+	_ = x[Punctuation-(5000)]
+	_ = x[Comment-(6000)]
+	_ = x[CommentHashbang-(6001)]
+	_ = x[CommentMultiline-(6002)]
+	_ = x[CommentSingle-(6003)]
+	_ = x[CommentSpecial-(6004)]
+	_ = x[CommentPreproc-(6100)]
+	_ = x[CommentPreprocFile-(6101)]
+	_ = x[Generic-(7000)]
+	_ = x[GenericDeleted-(7001)]
+	_ = x[GenericEmph-(7002)]
+	_ = x[GenericError-(7003)]
+	_ = x[GenericHeading-(7004)]
+	_ = x[GenericInserted-(7005)]
+	_ = x[GenericOutput-(7006)]
+	_ = x[GenericPrompt-(7007)]
+	_ = x[GenericStrong-(7008)]
+	_ = x[GenericSubheading-(7009)]
+	_ = x[GenericTraceback-(7010)]
+	_ = x[GenericUnderline-(7011)]
+	_ = x[Text-(8000)]
+	_ = x[TextWhitespace-(8001)]
+	_ = x[TextSymbol-(8002)]
+	_ = x[TextPunctuation-(8003)]
+}
+
+var _TokenTypeValues = []TokenType{None, Other, Error, CodeLine, LineLink, LineTableTD, LineTable, LineHighlight, LineNumbersTable, LineNumbers, Line, PreWrapper, Background, EOFType, Keyword, KeywordConstant, KeywordDeclaration, KeywordNamespace, KeywordPseudo, KeywordReserved, KeywordType, Name, NameAttribute, NameBuiltin, NameBuiltinPseudo, NameClass, NameConstant, NameDecorator, NameEntity, NameException, NameFunction, NameFunctionMagic, NameKeyword, NameLabel, NameNamespace, NameOperator, NameOther, NamePseudo, NameProperty, NameTag, NameVariable, NameVariableAnonymous, NameVariableClass, NameVariableGlobal, NameVariableInstance, NameVariableMagic, Literal, LiteralDate, LiteralOther, LiteralString, LiteralStringAffix, LiteralStringAtom, LiteralStringBacktick, LiteralStringBoolean, LiteralStringChar, LiteralStringDelimiter, LiteralStringDoc, LiteralStringDouble, LiteralStringEscape, LiteralStringHeredoc, LiteralStringInterpol, LiteralStringName, LiteralStringOther, LiteralStringRegex, LiteralStringSingle, LiteralStringSymbol, LiteralNumber, LiteralNumberBin, LiteralNumberFloat, LiteralNumberHex, LiteralNumberInteger, LiteralNumberIntegerLong, LiteralNumberOct, Operator, OperatorWord, Punctuation, Comment, CommentHashbang, CommentMultiline, CommentSingle, CommentSpecial, CommentPreproc, CommentPreprocFile, Generic, GenericDeleted, GenericEmph, GenericError, GenericHeading, GenericInserted, GenericOutput, GenericPrompt, GenericStrong, GenericSubheading, GenericTraceback, GenericUnderline, Text, TextWhitespace, TextSymbol, TextPunctuation}
+
+var _TokenTypeNameToValueMap = map[string]TokenType{
+	_TokenTypeName[0:4]:            None,
+	_TokenTypeLowerName[0:4]:       None,
+	_TokenTypeName[4:9]:            Other,
+	_TokenTypeLowerName[4:9]:       Other,
+	_TokenTypeName[9:14]:           Error,
+	_TokenTypeLowerName[9:14]:      Error,
+	_TokenTypeName[14:22]:          CodeLine,
+	_TokenTypeLowerName[14:22]:     CodeLine,
+	_TokenTypeName[22:30]:          LineLink,
+	_TokenTypeLowerName[22:30]:     LineLink,
+	_TokenTypeName[30:41]:          LineTableTD,
+	_TokenTypeLowerName[30:41]:     LineTableTD,
+	_TokenTypeName[41:50]:          LineTable,
+	_TokenTypeLowerName[41:50]:     LineTable,
+	_TokenTypeName[50:63]:          LineHighlight,
+	_TokenTypeLowerName[50:63]:     LineHighlight,
+	_TokenTypeName[63:79]:          LineNumbersTable,
+	_TokenTypeLowerName[63:79]:     LineNumbersTable,
+	_TokenTypeName[79:90]:          LineNumbers,
+	_TokenTypeLowerName[79:90]:     LineNumbers,
+	_TokenTypeName[90:94]:          Line,
+	_TokenTypeLowerName[90:94]:     Line,
+	_TokenTypeName[94:104]:         PreWrapper,
+	_TokenTypeLowerName[94:104]:    PreWrapper,
+	_TokenTypeName[104:114]:        Background,
+	_TokenTypeLowerName[104:114]:   Background,
+	_TokenTypeName[114:121]:        EOFType,
+	_TokenTypeLowerName[114:121]:   EOFType,
+	_TokenTypeName[121:128]:        Keyword,
+	_TokenTypeLowerName[121:128]:   Keyword,
+	_TokenTypeName[128:143]:        KeywordConstant,
+	_TokenTypeLowerName[128:143]:   KeywordConstant,
+	_TokenTypeName[143:161]:        KeywordDeclaration,
+	_TokenTypeLowerName[143:161]:   KeywordDeclaration,
+	_TokenTypeName[161:177]:        KeywordNamespace,
+	_TokenTypeLowerName[161:177]:   KeywordNamespace,
+	_TokenTypeName[177:190]:        KeywordPseudo,
+	_TokenTypeLowerName[177:190]:   KeywordPseudo,
+	_TokenTypeName[190:205]:        KeywordReserved,
+	_TokenTypeLowerName[190:205]:   KeywordReserved,
+	_TokenTypeName[205:216]:        KeywordType,
+	_TokenTypeLowerName[205:216]:   KeywordType,
+	_TokenTypeName[216:220]:        Name,
+	_TokenTypeLowerName[216:220]:   Name,
+	_TokenTypeName[220:233]:        NameAttribute,
+	_TokenTypeLowerName[220:233]:   NameAttribute,
+	_TokenTypeName[233:244]:        NameBuiltin,
+	_TokenTypeLowerName[233:244]:   NameBuiltin,
+	_TokenTypeName[244:261]:        NameBuiltinPseudo,
+	_TokenTypeLowerName[244:261]:   NameBuiltinPseudo,
+	_TokenTypeName[261:270]:        NameClass,
+	_TokenTypeLowerName[261:270]:   NameClass,
+	_TokenTypeName[270:282]:        NameConstant,
+	_TokenTypeLowerName[270:282]:   NameConstant,
+	_TokenTypeName[282:295]:        NameDecorator,
+	_TokenTypeLowerName[282:295]:   NameDecorator,
+	_TokenTypeName[295:305]:        NameEntity,
+	_TokenTypeLowerName[295:305]:   NameEntity,
+	_TokenTypeName[305:318]:        NameException,
+	_TokenTypeLowerName[305:318]:   NameException,
+	_TokenTypeName[318:330]:        NameFunction,
+	_TokenTypeLowerName[318:330]:   NameFunction,
+	_TokenTypeName[330:347]:        NameFunctionMagic,
+	_TokenTypeLowerName[330:347]:   NameFunctionMagic,
+	_TokenTypeName[347:358]:        NameKeyword,
+	_TokenTypeLowerName[347:358]:   NameKeyword,
+	_TokenTypeName[358:367]:        NameLabel,
+	_TokenTypeLowerName[358:367]:   NameLabel,
+	_TokenTypeName[367:380]:        NameNamespace,
+	_TokenTypeLowerName[367:380]:   NameNamespace,
+	_TokenTypeName[380:392]:        NameOperator,
+	_TokenTypeLowerName[380:392]:   NameOperator,
+	_TokenTypeName[392:401]:        NameOther,
+	_TokenTypeLowerName[392:401]:   NameOther,
+	_TokenTypeName[401:411]:        NamePseudo,
+	_TokenTypeLowerName[401:411]:   NamePseudo,
+	_TokenTypeName[411:423]:        NameProperty,
+	_TokenTypeLowerName[411:423]:   NameProperty,
+	_TokenTypeName[423:430]:        NameTag,
+	_TokenTypeLowerName[423:430]:   NameTag,
+	_TokenTypeName[430:442]:        NameVariable,
+	_TokenTypeLowerName[430:442]:   NameVariable,
+	_TokenTypeName[442:463]:        NameVariableAnonymous,
+	_TokenTypeLowerName[442:463]:   NameVariableAnonymous,
+	_TokenTypeName[463:480]:        NameVariableClass,
+	_TokenTypeLowerName[463:480]:   NameVariableClass,
+	_TokenTypeName[480:498]:        NameVariableGlobal,
+	_TokenTypeLowerName[480:498]:   NameVariableGlobal,
+	_TokenTypeName[498:518]:        NameVariableInstance,
+	_TokenTypeLowerName[498:518]:   NameVariableInstance,
+	_TokenTypeName[518:535]:        NameVariableMagic,
+	_TokenTypeLowerName[518:535]:   NameVariableMagic,
+	_TokenTypeName[535:542]:        Literal,
+	_TokenTypeLowerName[535:542]:   Literal,
+	_TokenTypeName[542:553]:        LiteralDate,
+	_TokenTypeLowerName[542:553]:   LiteralDate,
+	_TokenTypeName[553:565]:        LiteralOther,
+	_TokenTypeLowerName[553:565]:   LiteralOther,
+	_TokenTypeName[565:578]:        LiteralString,
+	_TokenTypeLowerName[565:578]:   LiteralString,
+	_TokenTypeName[578:596]:        LiteralStringAffix,
+	_TokenTypeLowerName[578:596]:   LiteralStringAffix,
+	_TokenTypeName[596:613]:        LiteralStringAtom,
+	_TokenTypeLowerName[596:613]:   LiteralStringAtom,
+	_TokenTypeName[613:634]:        LiteralStringBacktick,
+	_TokenTypeLowerName[613:634]:   LiteralStringBacktick,
+	_TokenTypeName[634:654]:        LiteralStringBoolean,
+	_TokenTypeLowerName[634:654]:   LiteralStringBoolean,
+	_TokenTypeName[654:671]:        LiteralStringChar,
+	_TokenTypeLowerName[654:671]:   LiteralStringChar,
+	_TokenTypeName[671:693]:        LiteralStringDelimiter,
+	_TokenTypeLowerName[671:693]:   LiteralStringDelimiter,
+	_TokenTypeName[693:709]:        LiteralStringDoc,
+	_TokenTypeLowerName[693:709]:   LiteralStringDoc,
+	_TokenTypeName[709:728]:        LiteralStringDouble,
+	_TokenTypeLowerName[709:728]:   LiteralStringDouble,
+	_TokenTypeName[728:747]:        LiteralStringEscape,
+	_TokenTypeLowerName[728:747]:   LiteralStringEscape,
+	_TokenTypeName[747:767]:        LiteralStringHeredoc,
+	_TokenTypeLowerName[747:767]:   LiteralStringHeredoc,
+	_TokenTypeName[767:788]:        LiteralStringInterpol,
+	_TokenTypeLowerName[767:788]:   LiteralStringInterpol,
+	_TokenTypeName[788:805]:        LiteralStringName,
+	_TokenTypeLowerName[788:805]:   LiteralStringName,
+	_TokenTypeName[805:823]:        LiteralStringOther,
+	_TokenTypeLowerName[805:823]:   LiteralStringOther,
+	_TokenTypeName[823:841]:        LiteralStringRegex,
+	_TokenTypeLowerName[823:841]:   LiteralStringRegex,
+	_TokenTypeName[841:860]:        LiteralStringSingle,
+	_TokenTypeLowerName[841:860]:   LiteralStringSingle,
+	_TokenTypeName[860:879]:        LiteralStringSymbol,
+	_TokenTypeLowerName[860:879]:   LiteralStringSymbol,
+	_TokenTypeName[879:892]:        LiteralNumber,
+	_TokenTypeLowerName[879:892]:   LiteralNumber,
+	_TokenTypeName[892:908]:        LiteralNumberBin,
+	_TokenTypeLowerName[892:908]:   LiteralNumberBin,
+	_TokenTypeName[908:926]:        LiteralNumberFloat,
+	_TokenTypeLowerName[908:926]:   LiteralNumberFloat,
+	_TokenTypeName[926:942]:        LiteralNumberHex,
+	_TokenTypeLowerName[926:942]:   LiteralNumberHex,
+	_TokenTypeName[942:962]:        LiteralNumberInteger,
+	_TokenTypeLowerName[942:962]:   LiteralNumberInteger,
+	_TokenTypeName[962:986]:        LiteralNumberIntegerLong,
+	_TokenTypeLowerName[962:986]:   LiteralNumberIntegerLong,
+	_TokenTypeName[986:1002]:       LiteralNumberOct,
+	_TokenTypeLowerName[986:1002]:  LiteralNumberOct,
+	_TokenTypeName[1002:1010]:      Operator,
+	_TokenTypeLowerName[1002:1010]: Operator,
+	_TokenTypeName[1010:1022]:      OperatorWord,
+	_TokenTypeLowerName[1010:1022]: OperatorWord,
+	_TokenTypeName[1022:1033]:      Punctuation,
+	_TokenTypeLowerName[1022:1033]: Punctuation,
+	_TokenTypeName[1033:1040]:      Comment,
+	_TokenTypeLowerName[1033:1040]: Comment,
+	_TokenTypeName[1040:1055]:      CommentHashbang,
+	_TokenTypeLowerName[1040:1055]: CommentHashbang,
+	_TokenTypeName[1055:1071]:      CommentMultiline,
+	_TokenTypeLowerName[1055:1071]: CommentMultiline,
+	_TokenTypeName[1071:1084]:      CommentSingle,
+	_TokenTypeLowerName[1071:1084]: CommentSingle,
+	_TokenTypeName[1084:1098]:      CommentSpecial,
+	_TokenTypeLowerName[1084:1098]: CommentSpecial,
+	_TokenTypeName[1098:1112]:      CommentPreproc,
+	_TokenTypeLowerName[1098:1112]: CommentPreproc,
+	_TokenTypeName[1112:1130]:      CommentPreprocFile,
+	_TokenTypeLowerName[1112:1130]: CommentPreprocFile,
+	_TokenTypeName[1130:1137]:      Generic,
+	_TokenTypeLowerName[1130:1137]: Generic,
+	_TokenTypeName[1137:1151]:      GenericDeleted,
+	_TokenTypeLowerName[1137:1151]: GenericDeleted,
+	_TokenTypeName[1151:1162]:      GenericEmph,
+	_TokenTypeLowerName[1151:1162]: GenericEmph,
+	_TokenTypeName[1162:1174]:      GenericError,
+	_TokenTypeLowerName[1162:1174]: GenericError,
+	_TokenTypeName[1174:1188]:      GenericHeading,
+	_TokenTypeLowerName[1174:1188]: GenericHeading,
+	_TokenTypeName[1188:1203]:      GenericInserted,
+	_TokenTypeLowerName[1188:1203]: GenericInserted,
+	_TokenTypeName[1203:1216]:      GenericOutput,
+	_TokenTypeLowerName[1203:1216]: GenericOutput,
+	_TokenTypeName[1216:1229]:      GenericPrompt,
+	_TokenTypeLowerName[1216:1229]: GenericPrompt,
+	_TokenTypeName[1229:1242]:      GenericStrong,
+	_TokenTypeLowerName[1229:1242]: GenericStrong,
+	_TokenTypeName[1242:1259]:      GenericSubheading,
+	_TokenTypeLowerName[1242:1259]: GenericSubheading,
+	_TokenTypeName[1259:1275]:      GenericTraceback,
+	_TokenTypeLowerName[1259:1275]: GenericTraceback,
+	_TokenTypeName[1275:1291]:      GenericUnderline,
+	_TokenTypeLowerName[1275:1291]: GenericUnderline,
+	_TokenTypeName[1291:1295]:      Text,
+	_TokenTypeLowerName[1291:1295]: Text,
+	_TokenTypeName[1295:1309]:      TextWhitespace,
+	_TokenTypeLowerName[1295:1309]: TextWhitespace,
+	_TokenTypeName[1309:1319]:      TextSymbol,
+	_TokenTypeLowerName[1309:1319]: TextSymbol,
+	_TokenTypeName[1319:1334]:      TextPunctuation,
+	_TokenTypeLowerName[1319:1334]: TextPunctuation,
+}
+
+var _TokenTypeNames = []string{
+	_TokenTypeName[0:4],
+	_TokenTypeName[4:9],
+	_TokenTypeName[9:14],
+	_TokenTypeName[14:22],
+	_TokenTypeName[22:30],
+	_TokenTypeName[30:41],
+	_TokenTypeName[41:50],
+	_TokenTypeName[50:63],
+	_TokenTypeName[63:79],
+	_TokenTypeName[79:90],
+	_TokenTypeName[90:94],
+	_TokenTypeName[94:104],
+	_TokenTypeName[104:114],
+	_TokenTypeName[114:121],
+	_TokenTypeName[121:128],
+	_TokenTypeName[128:143],
+	_TokenTypeName[143:161],
+	_TokenTypeName[161:177],
+	_TokenTypeName[177:190],
+	_TokenTypeName[190:205],
+	_TokenTypeName[205:216],
+	_TokenTypeName[216:220],
+	_TokenTypeName[220:233],
+	_TokenTypeName[233:244],
+	_TokenTypeName[244:261],
+	_TokenTypeName[261:270],
+	_TokenTypeName[270:282],
+	_TokenTypeName[282:295],
+	_TokenTypeName[295:305],
+	_TokenTypeName[305:318],
+	_TokenTypeName[318:330],
+	_TokenTypeName[330:347],
+	_TokenTypeName[347:358],
+	_TokenTypeName[358:367],
+	_TokenTypeName[367:380],
+	_TokenTypeName[380:392],
+	_TokenTypeName[392:401],
+	_TokenTypeName[401:411],
+	_TokenTypeName[411:423],
+	_TokenTypeName[423:430],
+	_TokenTypeName[430:442],
+	_TokenTypeName[442:463],
+	_TokenTypeName[463:480],
+	_TokenTypeName[480:498],
+	_TokenTypeName[498:518],
+	_TokenTypeName[518:535],
+	_TokenTypeName[535:542],
+	_TokenTypeName[542:553],
+	_TokenTypeName[553:565],
+	_TokenTypeName[565:578],
+	_TokenTypeName[578:596],
+	_TokenTypeName[596:613],
+	_TokenTypeName[613:634],
+	_TokenTypeName[634:654],
+	_TokenTypeName[654:671],
+	_TokenTypeName[671:693],
+	_TokenTypeName[693:709],
+	_TokenTypeName[709:728],
+	_TokenTypeName[728:747],
+	_TokenTypeName[747:767],
+	_TokenTypeName[767:788],
+	_TokenTypeName[788:805],
+	_TokenTypeName[805:823],
+	_TokenTypeName[823:841],
+	_TokenTypeName[841:860],
+	_TokenTypeName[860:879],
+	_TokenTypeName[879:892],
+	_TokenTypeName[892:908],
+	_TokenTypeName[908:926],
+	_TokenTypeName[926:942],
+	_TokenTypeName[942:962],
+	_TokenTypeName[962:986],
+	_TokenTypeName[986:1002],
+	_TokenTypeName[1002:1010],
+	_TokenTypeName[1010:1022],
+	_TokenTypeName[1022:1033],
+	_TokenTypeName[1033:1040],
+	_TokenTypeName[1040:1055],
+	_TokenTypeName[1055:1071],
+	_TokenTypeName[1071:1084],
+	_TokenTypeName[1084:1098],
+	_TokenTypeName[1098:1112],
+	_TokenTypeName[1112:1130],
+	_TokenTypeName[1130:1137],
+	_TokenTypeName[1137:1151],
+	_TokenTypeName[1151:1162],
+	_TokenTypeName[1162:1174],
+	_TokenTypeName[1174:1188],
+	_TokenTypeName[1188:1203],
+	_TokenTypeName[1203:1216],
+	_TokenTypeName[1216:1229],
+	_TokenTypeName[1229:1242],
+	_TokenTypeName[1242:1259],
+	_TokenTypeName[1259:1275],
+	_TokenTypeName[1275:1291],
+	_TokenTypeName[1291:1295],
+	_TokenTypeName[1295:1309],
+	_TokenTypeName[1309:1319],
+	_TokenTypeName[1319:1334],
+}
+
+// TokenTypeString retrieves an enum value from the enum constants string name.
+// Throws an error if the param is not part of the enum.
+func TokenTypeString(s string) (TokenType, error) {
+	if val, ok := _TokenTypeNameToValueMap[s]; ok {
+		return val, nil
+	}
+
+	if val, ok := _TokenTypeNameToValueMap[strings.ToLower(s)]; ok {
+		return val, nil
+	}
+	return 0, fmt.Errorf("%s does not belong to TokenType values", s)
+}
+
+// TokenTypeValues returns all values of the enum
+func TokenTypeValues() []TokenType {
+	return _TokenTypeValues
+}
+
+// TokenTypeStrings returns a slice of all String values of the enum
+func TokenTypeStrings() []string {
+	strs := make([]string, len(_TokenTypeNames))
+	copy(strs, _TokenTypeNames)
+	return strs
+}
+
+// IsATokenType returns "true" if the value is listed in the enum definition. "false" otherwise
+func (i TokenType) IsATokenType() bool {
+	_, ok := _TokenTypeMap[i]
+	return ok
+}
+
+// MarshalText implements the encoding.TextMarshaler interface for TokenType
+func (i TokenType) MarshalText() ([]byte, error) {
+	return []byte(i.String()), nil
+}
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface for TokenType
+func (i *TokenType) UnmarshalText(text []byte) error {
+	var err error
+	*i, err = TokenTypeString(string(text))
+	return err
+}
diff --git a/types.go b/types.go
new file mode 100644
index 0000000..3d12310
--- /dev/null
+++ b/types.go
@@ -0,0 +1,340 @@
+package chroma
+
+//go:generate enumer -text -type TokenType
+
+// TokenType is the type of token to highlight.
+//
+// It is also an Emitter, emitting a single token of itself
+type TokenType int
+
+// Set of TokenTypes.
+//
+// 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 (
+	// Default background style.
+	Background TokenType = -1 - iota
+	// PreWrapper style.
+	PreWrapper
+	// Line style.
+	Line
+	// Line numbers in output.
+	LineNumbers
+	// Line numbers in output when in table.
+	LineNumbersTable
+	// Line higlight style.
+	LineHighlight
+	// Line numbers table wrapper style.
+	LineTable
+	// Line numbers table TD wrapper style.
+	LineTableTD
+	// Line number links.
+	LineLink
+	// Code line wrapper style.
+	CodeLine
+	// Input that could not be tokenised.
+	Error
+	// Other is used by the Delegate lexer to indicate which tokens should be handled by the delegate.
+	Other
+	// No highlighting.
+	None
+	// Used as an EOF marker / nil token
+	EOFType TokenType = 0
+)
+
+// Keywords.
+const (
+	Keyword TokenType = 1000 + iota
+	KeywordConstant
+	KeywordDeclaration
+	KeywordNamespace
+	KeywordPseudo
+	KeywordReserved
+	KeywordType
+)
+
+// Names.
+const (
+	Name TokenType = 2000 + iota
+	NameAttribute
+	NameBuiltin
+	NameBuiltinPseudo
+	NameClass
+	NameConstant
+	NameDecorator
+	NameEntity
+	NameException
+	NameFunction
+	NameFunctionMagic
+	NameKeyword
+	NameLabel
+	NameNamespace
+	NameOperator
+	NameOther
+	NamePseudo
+	NameProperty
+	NameTag
+	NameVariable
+	NameVariableAnonymous
+	NameVariableClass
+	NameVariableGlobal
+	NameVariableInstance
+	NameVariableMagic
+)
+
+// Literals.
+const (
+	Literal TokenType = 3000 + iota
+	LiteralDate
+	LiteralOther
+)
+
+// Strings.
+const (
+	LiteralString TokenType = 3100 + iota
+	LiteralStringAffix
+	LiteralStringAtom
+	LiteralStringBacktick
+	LiteralStringBoolean
+	LiteralStringChar
+	LiteralStringDelimiter
+	LiteralStringDoc
+	LiteralStringDouble
+	LiteralStringEscape
+	LiteralStringHeredoc
+	LiteralStringInterpol
+	LiteralStringName
+	LiteralStringOther
+	LiteralStringRegex
+	LiteralStringSingle
+	LiteralStringSymbol
+)
+
+// Literals.
+const (
+	LiteralNumber TokenType = 3200 + iota
+	LiteralNumberBin
+	LiteralNumberFloat
+	LiteralNumberHex
+	LiteralNumberInteger
+	LiteralNumberIntegerLong
+	LiteralNumberOct
+)
+
+// Operators.
+const (
+	Operator TokenType = 4000 + iota
+	OperatorWord
+)
+
+// Punctuation.
+const (
+	Punctuation TokenType = 5000 + iota
+)
+
+// Comments.
+const (
+	Comment TokenType = 6000 + iota
+	CommentHashbang
+	CommentMultiline
+	CommentSingle
+	CommentSpecial
+)
+
+// Preprocessor "comments".
+const (
+	CommentPreproc TokenType = 6100 + iota
+	CommentPreprocFile
+)
+
+// Generic tokens.
+const (
+	Generic TokenType = 7000 + iota
+	GenericDeleted
+	GenericEmph
+	GenericError
+	GenericHeading
+	GenericInserted
+	GenericOutput
+	GenericPrompt
+	GenericStrong
+	GenericSubheading
+	GenericTraceback
+	GenericUnderline
+)
+
+// Text.
+const (
+	Text TokenType = 8000 + iota
+	TextWhitespace
+	TextSymbol
+	TextPunctuation
+)
+
+// Aliases.
+const (
+	Whitespace = TextWhitespace
+
+	Date = LiteralDate
+
+	String          = LiteralString
+	StringAffix     = LiteralStringAffix
+	StringBacktick  = LiteralStringBacktick
+	StringChar      = LiteralStringChar
+	StringDelimiter = LiteralStringDelimiter
+	StringDoc       = LiteralStringDoc
+	StringDouble    = LiteralStringDouble
+	StringEscape    = LiteralStringEscape
+	StringHeredoc   = LiteralStringHeredoc
+	StringInterpol  = LiteralStringInterpol
+	StringOther     = LiteralStringOther
+	StringRegex     = LiteralStringRegex
+	StringSingle    = LiteralStringSingle
+	StringSymbol    = LiteralStringSymbol
+
+	Number            = LiteralNumber
+	NumberBin         = LiteralNumberBin
+	NumberFloat       = LiteralNumberFloat
+	NumberHex         = LiteralNumberHex
+	NumberInteger     = LiteralNumberInteger
+	NumberIntegerLong = LiteralNumberIntegerLong
+	NumberOct         = LiteralNumberOct
+)
+
+var (
+	StandardTypes = map[TokenType]string{
+		Background:       "bg",
+		PreWrapper:       "chroma",
+		Line:             "line",
+		LineNumbers:      "ln",
+		LineNumbersTable: "lnt",
+		LineHighlight:    "hl",
+		LineTable:        "lntable",
+		LineTableTD:      "lntd",
+		LineLink:         "lnlinks",
+		CodeLine:         "cl",
+		Text:             "",
+		Whitespace:       "w",
+		Error:            "err",
+		Other:            "x",
+		// I have no idea what this is used for...
+		// Escape:     "esc",
+
+		Keyword:            "k",
+		KeywordConstant:    "kc",
+		KeywordDeclaration: "kd",
+		KeywordNamespace:   "kn",
+		KeywordPseudo:      "kp",
+		KeywordReserved:    "kr",
+		KeywordType:        "kt",
+
+		Name:                 "n",
+		NameAttribute:        "na",
+		NameBuiltin:          "nb",
+		NameBuiltinPseudo:    "bp",
+		NameClass:            "nc",
+		NameConstant:         "no",
+		NameDecorator:        "nd",
+		NameEntity:           "ni",
+		NameException:        "ne",
+		NameFunction:         "nf",
+		NameFunctionMagic:    "fm",
+		NameProperty:         "py",
+		NameLabel:            "nl",
+		NameNamespace:        "nn",
+		NameOther:            "nx",
+		NameTag:              "nt",
+		NameVariable:         "nv",
+		NameVariableClass:    "vc",
+		NameVariableGlobal:   "vg",
+		NameVariableInstance: "vi",
+		NameVariableMagic:    "vm",
+
+		Literal:     "l",
+		LiteralDate: "ld",
+
+		String:          "s",
+		StringAffix:     "sa",
+		StringBacktick:  "sb",
+		StringChar:      "sc",
+		StringDelimiter: "dl",
+		StringDoc:       "sd",
+		StringDouble:    "s2",
+		StringEscape:    "se",
+		StringHeredoc:   "sh",
+		StringInterpol:  "si",
+		StringOther:     "sx",
+		StringRegex:     "sr",
+		StringSingle:    "s1",
+		StringSymbol:    "ss",
+
+		Number:            "m",
+		NumberBin:         "mb",
+		NumberFloat:       "mf",
+		NumberHex:         "mh",
+		NumberInteger:     "mi",
+		NumberIntegerLong: "il",
+		NumberOct:         "mo",
+
+		Operator:     "o",
+		OperatorWord: "ow",
+
+		Punctuation: "p",
+
+		Comment:            "c",
+		CommentHashbang:    "ch",
+		CommentMultiline:   "cm",
+		CommentPreproc:     "cp",
+		CommentPreprocFile: "cpf",
+		CommentSingle:      "c1",
+		CommentSpecial:     "cs",
+
+		Generic:           "g",
+		GenericDeleted:    "gd",
+		GenericEmph:       "ge",
+		GenericError:      "gr",
+		GenericHeading:    "gh",
+		GenericInserted:   "gi",
+		GenericOutput:     "go",
+		GenericPrompt:     "gp",
+		GenericStrong:     "gs",
+		GenericSubheading: "gu",
+		GenericTraceback:  "gt",
+		GenericUnderline:  "gl",
+	}
+)
+
+func (t TokenType) Parent() TokenType {
+	if t%100 != 0 {
+		return t / 100 * 100
+	}
+	if t%1000 != 0 {
+		return t / 1000 * 1000
+	}
+	return 0
+}
+
+func (t TokenType) Category() TokenType {
+	return t / 1000 * 1000
+}
+
+func (t TokenType) SubCategory() TokenType {
+	return t / 100 * 100
+}
+
+func (t TokenType) InCategory(other TokenType) bool {
+	return t/1000 == other/1000
+}
+
+func (t TokenType) InSubCategory(other TokenType) bool {
+	return t/100 == other/100
+}
+
+func (t TokenType) Emit(groups []string, _ *LexerState) Iterator {
+	return Literator(Token{Type: t, Value: groups[0]})
+}
+
+func (t TokenType) EmitterKind() string { return "token" }