feat: syntax highlighting powered by chroma.
This is sick! It is not perfect, highlight groups would be cool, but for now this works!
This commit is contained in:
parent
c70cbeaedf
commit
76fa55440e
@ -4,12 +4,17 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.gophernest.net/azpect/TextEditor/internal/program"
|
"git.gophernest.net/azpect/TextEditor/internal/program"
|
||||||
|
"git.gophernest.net/azpect/TextEditor/internal/theme"
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
)
|
)
|
||||||
|
|
||||||
// main: Entry point for the Gim text editor. Creates a buffer and window,
|
// main: Entry point for the Gim text editor. Creates a buffer and window,
|
||||||
// initializes the editor model, and runs the BubbleTea TUI program.
|
// initializes the editor model, and runs the BubbleTea TUI program.
|
||||||
func main() {
|
func main() {
|
||||||
|
if err := theme.RegisterAll(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
// <exe> <filename>
|
// <exe> <filename>
|
||||||
args := os.Args[1:]
|
args := os.Args[1:]
|
||||||
|
|
||||||
|
|||||||
2
go.mod
2
go.mod
@ -3,6 +3,7 @@ module git.gophernest.net/azpect/TextEditor
|
|||||||
go 1.25.5
|
go 1.25.5
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/alecthomas/chroma/v2 v2.23.1
|
||||||
github.com/charmbracelet/bubbletea v1.3.10
|
github.com/charmbracelet/bubbletea v1.3.10
|
||||||
github.com/charmbracelet/lipgloss v1.1.0
|
github.com/charmbracelet/lipgloss v1.1.0
|
||||||
github.com/charmbracelet/x/exp/teatest v0.0.0-20260209132835-6b065b8ba62c
|
github.com/charmbracelet/x/exp/teatest v0.0.0-20260209132835-6b065b8ba62c
|
||||||
@ -19,6 +20,7 @@ require (
|
|||||||
github.com/clipperhouse/displaywidth v0.9.0 // indirect
|
github.com/clipperhouse/displaywidth v0.9.0 // indirect
|
||||||
github.com/clipperhouse/stringish v0.1.1 // indirect
|
github.com/clipperhouse/stringish v0.1.1 // indirect
|
||||||
github.com/clipperhouse/uax29/v2 v2.5.0 // indirect
|
github.com/clipperhouse/uax29/v2 v2.5.0 // indirect
|
||||||
|
github.com/dlclark/regexp2 v1.11.5 // indirect
|
||||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
|
||||||
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
|
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
|||||||
10
go.sum
10
go.sum
@ -1,3 +1,9 @@
|
|||||||
|
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
|
||||||
|
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||||
|
github.com/alecthomas/chroma/v2 v2.23.1 h1:nv2AVZdTyClGbVQkIzlDm/rnhk1E9bU9nXwmZ/Vk/iY=
|
||||||
|
github.com/alecthomas/chroma/v2 v2.23.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o=
|
||||||
|
github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs=
|
||||||
|
github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||||
github.com/aymanbagabas/go-udiff v0.3.1 h1:LV+qyBQ2pqe0u42ZsUEtPiCaUoqgA9gYRDs3vj1nolY=
|
github.com/aymanbagabas/go-udiff v0.3.1 h1:LV+qyBQ2pqe0u42ZsUEtPiCaUoqgA9gYRDs3vj1nolY=
|
||||||
@ -24,8 +30,12 @@ github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfa
|
|||||||
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
|
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
|
||||||
github.com/clipperhouse/uax29/v2 v2.5.0 h1:x7T0T4eTHDONxFJsL94uKNKPHrclyFI0lm7+w94cO8U=
|
github.com/clipperhouse/uax29/v2 v2.5.0 h1:x7T0T4eTHDONxFJsL94uKNKPHrclyFI0lm7+w94cO8U=
|
||||||
github.com/clipperhouse/uax29/v2 v2.5.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
|
github.com/clipperhouse/uax29/v2 v2.5.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
|
||||||
|
github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ=
|
||||||
|
github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
||||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
||||||
|
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
||||||
|
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
||||||
github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
|
github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
|
||||||
github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
|||||||
@ -4,13 +4,86 @@ import (
|
|||||||
"git.gophernest.net/azpect/TextEditor/internal/core"
|
"git.gophernest.net/azpect/TextEditor/internal/core"
|
||||||
"git.gophernest.net/azpect/TextEditor/internal/input"
|
"git.gophernest.net/azpect/TextEditor/internal/input"
|
||||||
"git.gophernest.net/azpect/TextEditor/internal/style"
|
"git.gophernest.net/azpect/TextEditor/internal/style"
|
||||||
|
"github.com/alecthomas/chroma/v2/styles"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ModelBuilder struct {
|
type ModelBuilder struct {
|
||||||
model Model
|
model Model
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RPGLE
|
||||||
|
// abap
|
||||||
|
// algol
|
||||||
|
// algol_nu
|
||||||
|
// arduino
|
||||||
|
// ashen
|
||||||
|
// aura-theme-dark
|
||||||
|
// aura-theme-dark-soft
|
||||||
|
// autumn
|
||||||
|
// average
|
||||||
|
// base16-snazzy
|
||||||
|
// borland
|
||||||
|
// bw
|
||||||
|
// catppuccin-frappe
|
||||||
|
// catppuccin-latte
|
||||||
|
// catppuccin-macchiato
|
||||||
|
// catppuccin-mocha
|
||||||
|
// colorful
|
||||||
|
// doom-one
|
||||||
|
// doom-one2
|
||||||
|
// dracula
|
||||||
|
// emacs
|
||||||
|
// evergarden
|
||||||
|
// friendly
|
||||||
|
// fruity
|
||||||
|
// github
|
||||||
|
// github-dark
|
||||||
|
// gruvbox
|
||||||
|
// gruvbox-light
|
||||||
|
// hr_high_contrast
|
||||||
|
// hrdark
|
||||||
|
// igor
|
||||||
|
// lovelace
|
||||||
|
// manni
|
||||||
|
// modus-operandi
|
||||||
|
// modus-vivendi
|
||||||
|
// monokai
|
||||||
|
// monokailight
|
||||||
|
// murphy
|
||||||
|
// native
|
||||||
|
// nord
|
||||||
|
// nordic
|
||||||
|
// onedark
|
||||||
|
// onesenterprise
|
||||||
|
// paraiso-dark
|
||||||
|
// paraiso-light
|
||||||
|
// pastie
|
||||||
|
// perldoc
|
||||||
|
// pygments
|
||||||
|
// rainbow_dash
|
||||||
|
// rose-pine
|
||||||
|
// rose-pine-dawn
|
||||||
|
// rose-pine-moon
|
||||||
|
// rrt
|
||||||
|
// solarized-dark
|
||||||
|
// solarized-dark256
|
||||||
|
// solarized-light
|
||||||
|
// swapoff
|
||||||
|
// tango
|
||||||
|
// tokyonight-day
|
||||||
|
// tokyonight-moon
|
||||||
|
// tokyonight-night
|
||||||
|
// tokyonight-storm
|
||||||
|
// trac
|
||||||
|
// vim
|
||||||
|
// vs
|
||||||
|
// vulcan
|
||||||
|
// witchhazel
|
||||||
|
// xcode
|
||||||
|
// xcode-dark
|
||||||
func NewModelBuilder() *ModelBuilder {
|
func NewModelBuilder() *ModelBuilder {
|
||||||
|
chromaStyle := styles.Get("kanagawa-wave")
|
||||||
|
|
||||||
return &ModelBuilder{
|
return &ModelBuilder{
|
||||||
model: Model{
|
model: Model{
|
||||||
buffers: []*core.Buffer{},
|
buffers: []*core.Buffer{},
|
||||||
@ -28,7 +101,7 @@ func NewModelBuilder() *ModelBuilder {
|
|||||||
commandOutput: nil,
|
commandOutput: nil,
|
||||||
settings: core.NewDefaultSettings(),
|
settings: core.NewDefaultSettings(),
|
||||||
registers: core.DefaultRegisters(),
|
registers: core.DefaultRegisters(),
|
||||||
styles: style.DefaultStyles(),
|
styles: style.ChromaStyles(chromaStyle),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,8 @@ import (
|
|||||||
|
|
||||||
"git.gophernest.net/azpect/TextEditor/internal/core"
|
"git.gophernest.net/azpect/TextEditor/internal/core"
|
||||||
"git.gophernest.net/azpect/TextEditor/internal/style"
|
"git.gophernest.net/azpect/TextEditor/internal/style"
|
||||||
|
"github.com/alecthomas/chroma/v2"
|
||||||
|
"github.com/alecthomas/chroma/v2/lexers"
|
||||||
"github.com/charmbracelet/lipgloss"
|
"github.com/charmbracelet/lipgloss"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -49,17 +51,25 @@ func viewWindow(w *core.Window, styles style.Styles, options core.WinOptions, mo
|
|||||||
start := w.ScrollY
|
start := w.ScrollY
|
||||||
end := w.ScrollY + w.ViewportHeight()
|
end := w.ScrollY + w.ViewportHeight()
|
||||||
|
|
||||||
|
// Chroma stuff
|
||||||
|
name := strings.ReplaceAll(buf.Filetype, ".", "")
|
||||||
|
lexer := lexers.Get(name)
|
||||||
|
lexer = chroma.Coalesce(lexer) // Merge tokens together
|
||||||
|
|
||||||
// Draw buffer lines
|
// Draw buffer lines
|
||||||
for lineNum := start; lineNum < end; lineNum++ {
|
for lineNum := start; lineNum < end; lineNum++ {
|
||||||
if lineNum < buf.LineCount() {
|
if lineNum < buf.LineCount() {
|
||||||
line := drawLine(w, styles, options, mode, buf.Line(lineNum), lineNum)
|
styleMap := styles.MakeStyleMap(lexer, buf.Line(lineNum))
|
||||||
|
line := drawLine(w, styles, options, mode, buf.Line(lineNum), lineNum, styleMap)
|
||||||
view.WriteString(line)
|
view.WriteString(line)
|
||||||
|
} else {
|
||||||
|
view.WriteString(strings.Repeat(styles.BackgroundStyle.Render(" "), w.Width))
|
||||||
}
|
}
|
||||||
view.WriteRune('\n')
|
view.WriteRune('\n')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw status line
|
// Draw status line
|
||||||
statusBar := drawStatusBar(w, mode)
|
statusBar := drawStatusBar(w, mode, styles)
|
||||||
view.WriteString(statusBar + "\n")
|
view.WriteString(statusBar + "\n")
|
||||||
|
|
||||||
return view.String()
|
return view.String()
|
||||||
@ -67,13 +77,9 @@ func viewWindow(w *core.Window, styles style.Styles, options core.WinOptions, mo
|
|||||||
|
|
||||||
// drawLine: Renders a single line with syntax highlighting, cursor, and visual selection.
|
// drawLine: Renders a single line with syntax highlighting, cursor, and visual selection.
|
||||||
// Handles gutter, cursor rendering, and visual mode highlighting.
|
// Handles gutter, cursor rendering, and visual mode highlighting.
|
||||||
func drawLine(w *core.Window, styles style.Styles, options core.WinOptions, mode core.Mode, line string, lineNumber int) string {
|
func drawLine(w *core.Window, styles style.Styles, options core.WinOptions, mode core.Mode, line string, lineNumber int, styleMap []lipgloss.Style) string {
|
||||||
runes := []rune(line)
|
|
||||||
|
|
||||||
curStyle := styles.CursorStyle(mode)
|
|
||||||
visStyle := styles.VisualHighlight
|
|
||||||
|
|
||||||
var view strings.Builder
|
var view strings.Builder
|
||||||
|
runes := []rune(line)
|
||||||
|
|
||||||
// Draw gutter first
|
// Draw gutter first
|
||||||
gutter := drawGutter(w, styles, options, lineNumber)
|
gutter := drawGutter(w, styles, options, lineNumber)
|
||||||
@ -84,24 +90,31 @@ func drawLine(w *core.Window, styles style.Styles, options core.WinOptions, mode
|
|||||||
// Current char is cursor
|
// Current char is cursor
|
||||||
if col == w.Cursor.Col && lineNumber == w.Cursor.Line {
|
if col == w.Cursor.Col && lineNumber == w.Cursor.Line {
|
||||||
if col < len(runes) {
|
if col < len(runes) {
|
||||||
view.WriteString(curStyle.Render(string(runes[col])))
|
cur := styles.CursorStyle(mode, styleMap[col])
|
||||||
|
view.WriteString(cur.Render(string(runes[col])))
|
||||||
} else {
|
} else {
|
||||||
view.WriteString(curStyle.Render(" "))
|
view.WriteString(styles.DefaultCursorStyle(mode).Render(" "))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not cursor, but not end
|
// Not cursor, but not end
|
||||||
} else if col < len(runes) {
|
} else if col < len(runes) {
|
||||||
|
s := styleMap[col]
|
||||||
if mode.IsVisualMode() && posInsideSelection(w, mode, col, lineNumber) {
|
if mode.IsVisualMode() && posInsideSelection(w, mode, col, lineNumber) {
|
||||||
view.WriteString(visStyle.Render(string(runes[col])))
|
vis := styles.VisualHighlightWithTextColor(s)
|
||||||
|
view.WriteString(vis.Render(string(runes[col])))
|
||||||
} else {
|
} else {
|
||||||
view.WriteRune(runes[col])
|
view.WriteString(s.Render(string(runes[col])))
|
||||||
}
|
}
|
||||||
// Allow highlight on blank lines or chars
|
// Allow highlight on blank lines or chars
|
||||||
} else if mode.IsVisualMode() && posInsideSelection(w, mode, col, lineNumber) {
|
} else if mode.IsVisualMode() && posInsideSelection(w, mode, col, lineNumber) {
|
||||||
view.WriteString(visStyle.Render(" "))
|
view.WriteString(styles.VisualHighlight.Render(" "))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Color the overflow
|
||||||
|
dif := w.Width - lipgloss.Width(line)
|
||||||
|
view.WriteString(strings.Repeat(styles.BackgroundStyle.Render(" "), dif))
|
||||||
|
|
||||||
return view.String()
|
return view.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,9 +166,9 @@ func drawGutter(w *core.Window, styles style.Styles, options core.WinOptions, cu
|
|||||||
|
|
||||||
// drawStatusBar: Renders the status bar with mode and cursor position,
|
// drawStatusBar: Renders the status bar with mode and cursor position,
|
||||||
// padding the middle with spaces to fill the terminal width.
|
// padding the middle with spaces to fill the terminal width.
|
||||||
func drawStatusBar(w *core.Window, mode core.Mode) string {
|
func drawStatusBar(w *core.Window, mode core.Mode, styles style.Styles) string {
|
||||||
left := leftBar(w, mode)
|
left := leftBar(w, mode, styles)
|
||||||
right := rightBar(w, mode)
|
right := rightBar(w, mode, styles)
|
||||||
|
|
||||||
diff := w.Width - (lipgloss.Width(left) + lipgloss.Width(right))
|
diff := w.Width - (lipgloss.Width(left) + lipgloss.Width(right))
|
||||||
|
|
||||||
@ -164,12 +177,12 @@ func drawStatusBar(w *core.Window, mode core.Mode) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
middle := strings.Repeat(" ", diff)
|
middle := strings.Repeat(styles.BackgroundStyle.Render(" "), diff)
|
||||||
return left + middle + right
|
return left + middle + right
|
||||||
}
|
}
|
||||||
|
|
||||||
// leftBar: Returns the left side of the status bar showing the current mode.
|
// leftBar: Returns the left side of the status bar showing the current mode.
|
||||||
func leftBar(w *core.Window, mode core.Mode) string {
|
func leftBar(w *core.Window, mode core.Mode, styles style.Styles) string {
|
||||||
buf := w.Buffer
|
buf := w.Buffer
|
||||||
|
|
||||||
var flags []string
|
var flags []string
|
||||||
@ -185,12 +198,13 @@ func leftBar(w *core.Window, mode core.Mode) string {
|
|||||||
flagStr = "(" + strings.Join(flags, "") + ")"
|
flagStr = "(" + strings.Join(flags, "") + ")"
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf(" %s %s %s", mode.ToString(), buf.Filename, flagStr)
|
bar := fmt.Sprintf(" %s %s %s", mode.ToString(), buf.Filename, flagStr)
|
||||||
|
return styles.LineStyle.Render(bar)
|
||||||
}
|
}
|
||||||
|
|
||||||
// rightBar: Returns the right side of the status bar showing cursor position
|
// rightBar: Returns the right side of the status bar showing cursor position
|
||||||
// and selection count in visual mode.
|
// and selection count in visual mode.
|
||||||
func rightBar(w *core.Window, mode core.Mode) (bar string) {
|
func rightBar(w *core.Window, mode core.Mode, styles style.Styles) (bar string) {
|
||||||
if mode.IsVisualMode() {
|
if mode.IsVisualMode() {
|
||||||
lineCount := max(w.Anchor.Line, w.Cursor.Line) - min(w.Anchor.Line, w.Cursor.Line) + 1
|
lineCount := max(w.Anchor.Line, w.Cursor.Line) - min(w.Anchor.Line, w.Cursor.Line) + 1
|
||||||
bar = fmt.Sprintf("%d:%d <%d>", w.Cursor.Line+1, w.Cursor.Col+1, lineCount)
|
bar = fmt.Sprintf("%d:%d <%d>", w.Cursor.Line+1, w.Cursor.Col+1, lineCount)
|
||||||
@ -198,41 +212,44 @@ func rightBar(w *core.Window, mode core.Mode) (bar string) {
|
|||||||
bar = fmt.Sprintf("%d:%d ", w.Cursor.Line+1, w.Cursor.Col+1)
|
bar = fmt.Sprintf("%d:%d ", w.Cursor.Line+1, w.Cursor.Col+1)
|
||||||
}
|
}
|
||||||
buf := w.Buffer
|
buf := w.Buffer
|
||||||
bar = fmt.Sprintf("%s %s", buf.Filetype, bar)
|
bar = styles.LineStyle.Render(fmt.Sprintf("%s %s", buf.Filetype, bar))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// drawCommandBar: Renders the command line showing command input, errors, or
|
// drawCommandBar: Renders the command line showing command input, errors, or
|
||||||
// output depending on the current mode and state.
|
// output depending on the current mode and state.
|
||||||
func drawCommandBar(m Model) string {
|
func drawCommandBar(m Model) string {
|
||||||
|
styles := m.Styles()
|
||||||
|
|
||||||
// Compute left bar (command side)
|
// Compute left bar (command side)
|
||||||
var leftBar string
|
var leftBar string
|
||||||
if m.Mode() == core.CommandMode {
|
if m.Mode() == core.CommandMode {
|
||||||
leftBar = ":"
|
leftBar = styles.LineStyle.Render(":")
|
||||||
cmd := []rune(m.Command())
|
cmd := []rune(m.Command())
|
||||||
cur := m.CommandCursor()
|
cur := m.CommandCursor()
|
||||||
for i, r := range cmd {
|
for i, r := range cmd {
|
||||||
if i == cur {
|
if i == cur {
|
||||||
leftBar += m.Styles().CursorStyle(m.Mode()).Render(string(r))
|
leftBar += styles.DefaultCursorStyle(m.Mode()).Render(string(r))
|
||||||
} else {
|
} else {
|
||||||
leftBar += string(r)
|
leftBar += styles.LineStyle.Render(string(r))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Cursor at end of command
|
// Cursor at end of command
|
||||||
if cur >= len(cmd) {
|
if cur >= len(cmd) {
|
||||||
leftBar += m.Styles().CursorStyle(m.Mode()).Render(" ")
|
leftBar += styles.DefaultCursorStyle(m.Mode()).Render(" ")
|
||||||
}
|
}
|
||||||
// bar = fmt.Sprintf("%s %d", bar, cur)
|
// bar = fmt.Sprintf("%s %d", bar, cur)
|
||||||
} else if out := m.CommandOutput(); out != nil && len(out.Lines) > 0 && out.Inline {
|
} else if out := m.CommandOutput(); out != nil && len(out.Lines) > 0 && out.Inline {
|
||||||
// TODO: This is not perfect, temporary
|
// TODO: This is not perfect, temporary
|
||||||
text := strings.Join(out.Lines, " ")
|
text := strings.Join(out.Lines, " ")
|
||||||
if out.IsError {
|
if out.IsError {
|
||||||
leftBar = m.Styles().CommandError.Render(text)
|
leftBar = styles.CommandError.Render(text)
|
||||||
} else {
|
} else {
|
||||||
leftBar = text
|
leftBar = styles.LineStyle.Render(text)
|
||||||
}
|
}
|
||||||
} else if strings.TrimSpace(m.Command()) != "" {
|
} else if strings.TrimSpace(m.Command()) != "" {
|
||||||
leftBar = fmt.Sprintf(":%s", m.Command())
|
content := fmt.Sprintf(":%s", m.Command())
|
||||||
|
leftBar = styles.LineStyle.Render(content) //
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute right bar
|
// Compute right bar
|
||||||
@ -240,12 +257,13 @@ func drawCommandBar(m Model) string {
|
|||||||
var rightBar string
|
var rightBar string
|
||||||
if len(m.input.Pending()) > 0 {
|
if len(m.input.Pending()) > 0 {
|
||||||
width := 10 // Size of the block to display
|
width := 10 // Size of the block to display
|
||||||
rightBar = fmt.Sprintf("%-*s", width, m.input.Pending())
|
content := fmt.Sprintf("%-*s", width, m.input.Pending())
|
||||||
|
rightBar = styles.LineStyle.Render(content)
|
||||||
}
|
}
|
||||||
|
|
||||||
dif := m.termWidth - (lipgloss.Width(leftBar) + lipgloss.Width(rightBar))
|
dif := m.termWidth - (lipgloss.Width(leftBar) + lipgloss.Width(rightBar))
|
||||||
|
|
||||||
bar := leftBar + strings.Repeat(" ", max(0, dif)) + rightBar
|
bar := leftBar + strings.Repeat(styles.BackgroundStyle.Render(" "), max(0, dif)) + rightBar
|
||||||
return bar
|
return bar
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,10 +328,12 @@ func overlayCommandOutputWindow(view string, cmd *core.CommandOutput, styles sty
|
|||||||
overlay = append(overlay, styles.CommandOutputBorder.Render(strings.Repeat(" ", termWidth)))
|
overlay = append(overlay, styles.CommandOutputBorder.Render(strings.Repeat(" ", termWidth)))
|
||||||
|
|
||||||
if strings.TrimSpace(cmd.Title) != "" {
|
if strings.TrimSpace(cmd.Title) != "" {
|
||||||
overlay = append(overlay, cmd.Title)
|
title := styles.LineStyle.Render(cmd.Title)
|
||||||
|
overlay = append(overlay, title)
|
||||||
}
|
}
|
||||||
for _, l := range cmd.Lines {
|
for _, l := range cmd.Lines {
|
||||||
overlay = append(overlay, strings.ReplaceAll(l, "\n", "\\n"))
|
content := styles.LineStyle.Render(strings.ReplaceAll(l, "\n", "\\n"))
|
||||||
|
overlay = append(overlay, content)
|
||||||
}
|
}
|
||||||
overlay = append(overlay, styles.CommandContinueMessage.Render(core.CommandOutputExitMessage))
|
overlay = append(overlay, styles.CommandContinueMessage.Render(core.CommandOutputExitMessage))
|
||||||
|
|
||||||
@ -321,6 +341,12 @@ func overlayCommandOutputWindow(view string, cmd *core.CommandOutput, styles sty
|
|||||||
// which would cause Lipgloss to embed newlines internally and corrupt the line count.
|
// which would cause Lipgloss to embed newlines internally and corrupt the line count.
|
||||||
// If block-level styles are ever added, this approach must be replaced.
|
// If block-level styles are ever added, this approach must be replaced.
|
||||||
|
|
||||||
|
// Add background color to end of each line
|
||||||
|
for i, l := range overlay {
|
||||||
|
dif := termWidth - lipgloss.Width(l)
|
||||||
|
overlay[i] += styles.BackgroundStyle.Render(strings.Repeat(" ", dif))
|
||||||
|
}
|
||||||
|
|
||||||
// Remove 'h' lines from back of view and append overlay
|
// Remove 'h' lines from back of view and append overlay
|
||||||
h := len(overlay)
|
h := len(overlay)
|
||||||
final := lines[:max(0, len(lines)-h)]
|
final := lines[:max(0, len(lines)-h)]
|
||||||
|
|||||||
@ -46,6 +46,7 @@ func (p *ProgramBuilder) FileProgram(filename string) *ProgramBuilder {
|
|||||||
WithType(core.FileBuffer).
|
WithType(core.FileBuffer).
|
||||||
WithFilename(filename).
|
WithFilename(filename).
|
||||||
WithFiletype(ext).
|
WithFiletype(ext).
|
||||||
|
Listed().
|
||||||
Build()
|
Build()
|
||||||
|
|
||||||
win := core.NewWindowBuilder().
|
win := core.NewWindowBuilder().
|
||||||
|
|||||||
154
internal/style/style.go
Normal file → Executable file
154
internal/style/style.go
Normal file → Executable file
@ -2,6 +2,7 @@ package style
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git.gophernest.net/azpect/TextEditor/internal/core"
|
"git.gophernest.net/azpect/TextEditor/internal/core"
|
||||||
|
"github.com/alecthomas/chroma/v2"
|
||||||
"github.com/charmbracelet/lipgloss"
|
"github.com/charmbracelet/lipgloss"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -28,9 +29,16 @@ type Styles struct {
|
|||||||
CommandError lipgloss.Style
|
CommandError lipgloss.Style
|
||||||
CommandOutputBorder lipgloss.Style
|
CommandOutputBorder lipgloss.Style
|
||||||
CommandContinueMessage lipgloss.Style
|
CommandContinueMessage lipgloss.Style
|
||||||
|
|
||||||
|
// General Styles
|
||||||
|
LineStyle lipgloss.Style // This is a simple background with no text coloring
|
||||||
|
BackgroundStyle lipgloss.Style // This is just the background
|
||||||
|
|
||||||
|
// Chroma data
|
||||||
|
chromaStyle *chroma.Style
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultStyles returns the default editor color scheme.
|
// DefaultStyles: Returns the default editor color scheme.
|
||||||
func DefaultStyles() Styles {
|
func DefaultStyles() Styles {
|
||||||
return Styles{
|
return Styles{
|
||||||
CursorNormal: lipgloss.NewStyle().Reverse(true),
|
CursorNormal: lipgloss.NewStyle().Reverse(true),
|
||||||
@ -67,11 +75,86 @@ func DefaultStyles() Styles {
|
|||||||
|
|
||||||
CommandContinueMessage: lipgloss.NewStyle().
|
CommandContinueMessage: lipgloss.NewStyle().
|
||||||
Foreground(lipgloss.Color("#546fba")),
|
Foreground(lipgloss.Color("#546fba")),
|
||||||
|
|
||||||
|
chromaStyle: nil,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CursorStyle returns the appropriate cursor style for the given mode.
|
func ChromaStyles(chromaStyle *chroma.Style) Styles {
|
||||||
func (s Styles) CursorStyle(mode core.Mode) lipgloss.Style {
|
bgString := chromaStyle.Get(chroma.Background).Background.String()
|
||||||
|
lineNumbers := chromaStyle.Get(chroma.LineTableTD)
|
||||||
|
lineHighlight := chromaStyle.Get(chroma.LineHighlight)
|
||||||
|
|
||||||
|
return Styles{
|
||||||
|
CursorNormal: lipgloss.NewStyle().
|
||||||
|
Background(lipgloss.Color(bgString)).
|
||||||
|
Reverse(true),
|
||||||
|
|
||||||
|
CursorInsert: lipgloss.NewStyle().
|
||||||
|
Background(lipgloss.Color(bgString)).
|
||||||
|
Underline(true),
|
||||||
|
|
||||||
|
CursorCommand: lipgloss.NewStyle().
|
||||||
|
Background(lipgloss.Color(bgString)).
|
||||||
|
Reverse(true),
|
||||||
|
|
||||||
|
Gutter: lipgloss.NewStyle().
|
||||||
|
Background(lipgloss.Color(
|
||||||
|
darkenColor(lineNumbers.Background, 0.9).String()),
|
||||||
|
).
|
||||||
|
Foreground(lipgloss.Color(lineNumbers.Colour.String())),
|
||||||
|
|
||||||
|
GutterCurrentLine: lipgloss.NewStyle().
|
||||||
|
Background(lipgloss.Color(
|
||||||
|
darkenColor(lineNumbers.Background, 0.9).String()),
|
||||||
|
).
|
||||||
|
Foreground(lipgloss.Color(lineNumbers.Colour.String())),
|
||||||
|
|
||||||
|
VisualHighlight: lipgloss.NewStyle().
|
||||||
|
Background(lipgloss.Color(lineHighlight.Background.String())).
|
||||||
|
Foreground(lipgloss.Color(lineHighlight.Colour.String())),
|
||||||
|
|
||||||
|
VisualAnchor: lipgloss.NewStyle().
|
||||||
|
Background(lipgloss.Color(lineHighlight.Background.String())).
|
||||||
|
Foreground(lipgloss.Color(lineHighlight.Colour.String())),
|
||||||
|
|
||||||
|
StatusBar: lipgloss.NewStyle().
|
||||||
|
Background(lipgloss.Color(bgString)).
|
||||||
|
Foreground(lipgloss.Color("243")),
|
||||||
|
|
||||||
|
StatusBarActive: lipgloss.NewStyle().
|
||||||
|
Background(lipgloss.Color(bgString)).
|
||||||
|
Foreground(lipgloss.Color("230")),
|
||||||
|
|
||||||
|
CommandError: lipgloss.NewStyle().
|
||||||
|
Background(lipgloss.Color(bgString)).
|
||||||
|
Foreground(lipgloss.Color("#e3203a")),
|
||||||
|
|
||||||
|
CommandOutputBorder: lipgloss.NewStyle().
|
||||||
|
Background(
|
||||||
|
lipgloss.Color(
|
||||||
|
darkenColor(
|
||||||
|
chromaStyle.Get(chroma.Background).Background, 0.5).
|
||||||
|
String(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
CommandContinueMessage: lipgloss.NewStyle().
|
||||||
|
Background(lipgloss.Color(bgString)).
|
||||||
|
Foreground(lipgloss.Color("#546fba")),
|
||||||
|
|
||||||
|
LineStyle: lipgloss.NewStyle().
|
||||||
|
Foreground(lipgloss.Color(chromaStyle.Get(chroma.Line).Colour.String())).
|
||||||
|
Background(lipgloss.Color(bgString)),
|
||||||
|
|
||||||
|
BackgroundStyle: lipgloss.NewStyle().Background(lipgloss.Color(bgString)),
|
||||||
|
|
||||||
|
chromaStyle: chromaStyle,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Styles.DefaultCursorStyle: Returns the appropriate cursor style for the given mode.
|
||||||
|
func (s Styles) DefaultCursorStyle(mode core.Mode) lipgloss.Style {
|
||||||
switch mode {
|
switch mode {
|
||||||
case core.InsertMode:
|
case core.InsertMode:
|
||||||
return s.CursorInsert
|
return s.CursorInsert
|
||||||
@ -81,3 +164,68 @@ func (s Styles) CursorStyle(mode core.Mode) lipgloss.Style {
|
|||||||
return s.CursorNormal
|
return s.CursorNormal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Styles.CursorStyle: Returns a cursor style derived from a chroma style. This function should preferred
|
||||||
|
// over the DefaultCursorStyle, but in cases where there is no style to apply, the DefaultCursorStyle
|
||||||
|
// will always work.
|
||||||
|
func (s Styles) CursorStyle(mode core.Mode, style lipgloss.Style) lipgloss.Style {
|
||||||
|
switch mode {
|
||||||
|
case core.NormalMode, core.VisualLineMode, core.VisualBlockMode, core.VisualMode:
|
||||||
|
return lipgloss.NewStyle().
|
||||||
|
Background(style.GetForeground()).
|
||||||
|
Foreground(style.GetBackground())
|
||||||
|
default:
|
||||||
|
return lipgloss.NewStyle().
|
||||||
|
Background(s.BackgroundStyle.GetBackground()).
|
||||||
|
Foreground(style.GetForeground()).
|
||||||
|
Underline(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Styles.VisualHighlightWithTextColor: Works analogously to CursorStyle vs DefaultCursorStyle. When a
|
||||||
|
// style is available, this function should be used, so the text color will be rendered in front
|
||||||
|
// of the background. Otherwise, the VisualHighlight property will always work.
|
||||||
|
func (s Styles) VisualHighlightWithTextColor(style lipgloss.Style) lipgloss.Style {
|
||||||
|
return lipgloss.NewStyle().
|
||||||
|
Background(s.VisualHighlight.GetBackground()).
|
||||||
|
Foreground(style.GetForeground())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Styles.MakeStyleMap: Generates a style map for a single line. A style map is a mapping from
|
||||||
|
// column a lipgloss style. Cursor styles are not handled by this map, but they can be derived
|
||||||
|
// by inverting the background and foreground (and rolling back to the default).
|
||||||
|
func (s Styles) MakeStyleMap(lexer chroma.Lexer, line string) []lipgloss.Style {
|
||||||
|
m := make([]lipgloss.Style, len(line))
|
||||||
|
|
||||||
|
iter, err := lexer.Tokenise(nil, line)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
col := 0
|
||||||
|
for _, token := range iter.Tokens() {
|
||||||
|
entry := s.chromaStyle.Get(token.Type)
|
||||||
|
s := lipgloss.NewStyle().
|
||||||
|
Background(lipgloss.Color(entry.Background.String())).
|
||||||
|
Foreground(lipgloss.Color(entry.Colour.String()))
|
||||||
|
for _, char := range token.Value {
|
||||||
|
if char == '\n' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if col < len(m) {
|
||||||
|
m[col] = s
|
||||||
|
}
|
||||||
|
col++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
// darkenColor: Uses a factor (0.0 to 1.0) to darken a color using its opacity.
|
||||||
|
func darkenColor(c chroma.Colour, factor float64) chroma.Colour {
|
||||||
|
r := uint8(float64(c.Red()) * factor)
|
||||||
|
g := uint8(float64(c.Green()) * factor)
|
||||||
|
b := uint8(float64(c.Blue()) * factor)
|
||||||
|
return chroma.NewColour(r, g, b)
|
||||||
|
}
|
||||||
|
|||||||
43
internal/theme/theme.go
Normal file
43
internal/theme/theme.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package theme
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/alecthomas/chroma/v2"
|
||||||
|
"github.com/alecthomas/chroma/v2/styles"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed themes/*
|
||||||
|
var themeFS embed.FS
|
||||||
|
|
||||||
|
// RegisterAll: Registers all XML theme files embedded in the themes/ directory
|
||||||
|
// with chroma's style registry. After calling this, styles.Get() will recognize
|
||||||
|
// any theme defined in those files.
|
||||||
|
func RegisterAll() error {
|
||||||
|
entries, err := themeFS.ReadDir("themes")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to read embedded themes directory: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, entry := range entries {
|
||||||
|
if entry.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := themeFS.Open("themes/" + entry.Name())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to open theme %s: %w", entry.Name(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
style, err := chroma.NewXMLStyle(f)
|
||||||
|
f.Close()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to parse theme %s: %w", entry.Name(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
styles.Register(style)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
83
internal/theme/themes/kanagawa-dragon.xml
Normal file
83
internal/theme/themes/kanagawa-dragon.xml
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
<style name="kanagawa-dragon">
|
||||||
|
<entry type="Background" style="bg:#181616 #c5c9c5" />
|
||||||
|
<entry type="CodeLine" style="#c5c9c5" />
|
||||||
|
<entry type="Error" style="#e82424" />
|
||||||
|
<entry type="Other" style="#c5c9c5" />
|
||||||
|
<entry type="LineTableTD" style="" />
|
||||||
|
<entry type="LineTable" style="" />
|
||||||
|
<entry type="LineHighlight" style="bg:#393836" />
|
||||||
|
<entry type="LineNumbersTable" style="#625e5a" />
|
||||||
|
<entry type="LineNumbers" style="#625e5a" />
|
||||||
|
<entry type="Keyword" style="#8992a7" />
|
||||||
|
<entry type="KeywordReserved" style="#8992a7" />
|
||||||
|
<entry type="KeywordPseudo" style="#8992a7" />
|
||||||
|
<entry type="KeywordConstant" style="#b6927b" />
|
||||||
|
<entry type="KeywordDeclaration" style="#8992a7" />
|
||||||
|
<entry type="KeywordNamespace" style="#c4b28a" />
|
||||||
|
<entry type="KeywordType" style="#8ea4a2" />
|
||||||
|
<entry type="Name" style="#c5c9c5" />
|
||||||
|
<entry type="NameClass" style="#8ea4a2" />
|
||||||
|
<entry type="NameConstant" style="#b6927b" />
|
||||||
|
<entry type="NameDecorator" style="bold #b6927b" />
|
||||||
|
<entry type="NameEntity" style="#c4b28a" />
|
||||||
|
<entry type="NameException" style="#b6927b" />
|
||||||
|
<entry type="NameFunction" style="#8ba4b0" />
|
||||||
|
<entry type="NameFunctionMagic" style="#8ba4b0" />
|
||||||
|
<entry type="NameLabel" style="#949fb5" />
|
||||||
|
<entry type="NameNamespace" style="#c4b28a" />
|
||||||
|
<entry type="NameProperty" style="#c4b28a" />
|
||||||
|
<entry type="NameTag" style="#8ba4b0" />
|
||||||
|
<entry type="NameVariable" style="#c5c9c5" />
|
||||||
|
<entry type="NameVariableClass" style="#c5c9c5" />
|
||||||
|
<entry type="NameVariableGlobal" style="#c5c9c5" />
|
||||||
|
<entry type="NameVariableInstance" style="#c5c9c5" />
|
||||||
|
<entry type="NameVariableMagic" style="#c5c9c5" />
|
||||||
|
<entry type="NameAttribute" style="#c4b28a" />
|
||||||
|
<entry type="NameBuiltin" style="#c4746e" />
|
||||||
|
<entry type="NameBuiltinPseudo" style="#c4746e" />
|
||||||
|
<entry type="NameOther" style="#c5c9c5" />
|
||||||
|
<entry type="Literal" style="#c5c9c5" />
|
||||||
|
<entry type="LiteralDate" style="#c5c9c5" />
|
||||||
|
<entry type="LiteralString" style="#8a9a7b" />
|
||||||
|
<entry type="LiteralStringChar" style="#8a9a7b" />
|
||||||
|
<entry type="LiteralStringSingle" style="#8a9a7b" />
|
||||||
|
<entry type="LiteralStringDouble" style="#8a9a7b" />
|
||||||
|
<entry type="LiteralStringBacktick" style="#8a9a7b" />
|
||||||
|
<entry type="LiteralStringOther" style="#8a9a7b" />
|
||||||
|
<entry type="LiteralStringSymbol" style="#8a9a7b" />
|
||||||
|
<entry type="LiteralStringInterpol" style="#949fb5" />
|
||||||
|
<entry type="LiteralStringAffix" style="#c4746e" />
|
||||||
|
<entry type="LiteralStringDelimiter" style="#949fb5" />
|
||||||
|
<entry type="LiteralStringEscape" style="#c4746e" />
|
||||||
|
<entry type="LiteralStringRegex" style="#c4746e" />
|
||||||
|
<entry type="LiteralStringDoc" style="#737c73" />
|
||||||
|
<entry type="LiteralStringHeredoc" style="#737c73" />
|
||||||
|
<entry type="LiteralNumber" style="#a292a3" />
|
||||||
|
<entry type="LiteralNumberBin" style="#a292a3" />
|
||||||
|
<entry type="LiteralNumberHex" style="#a292a3" />
|
||||||
|
<entry type="LiteralNumberInteger" style="#a292a3" />
|
||||||
|
<entry type="LiteralNumberFloat" style="#a292a3" />
|
||||||
|
<entry type="LiteralNumberIntegerLong" style="#a292a3" />
|
||||||
|
<entry type="LiteralNumberOct" style="#a292a3" />
|
||||||
|
<entry type="Operator" style="bold #c4746e" />
|
||||||
|
<entry type="OperatorWord" style="bold #c4746e" />
|
||||||
|
<entry type="Comment" style="italic #737c73" />
|
||||||
|
<entry type="CommentSingle" style="italic #737c73" />
|
||||||
|
<entry type="CommentMultiline" style="italic #737c73" />
|
||||||
|
<entry type="CommentSpecial" style="italic #737c73" />
|
||||||
|
<entry type="CommentHashbang" style="italic #737c73" />
|
||||||
|
<entry type="CommentPreproc" style="italic #c4746e" />
|
||||||
|
<entry type="CommentPreprocFile" style="bold #c4746e" />
|
||||||
|
<entry type="Generic" style="#c5c9c5" />
|
||||||
|
<entry type="GenericInserted" style="bg:#2b3328 #76946a" />
|
||||||
|
<entry type="GenericDeleted" style="bg:#43242b #c34043" />
|
||||||
|
<entry type="GenericEmph" style="italic #c5c9c5" />
|
||||||
|
<entry type="GenericStrong" style="bold #c5c9c5" />
|
||||||
|
<entry type="GenericUnderline" style="underline #c5c9c5" />
|
||||||
|
<entry type="GenericHeading" style="bold #8ba4b0" />
|
||||||
|
<entry type="GenericSubheading" style="bold #8ba4b0" />
|
||||||
|
<entry type="GenericOutput" style="#c5c9c5" />
|
||||||
|
<entry type="GenericPrompt" style="#c5c9c5" />
|
||||||
|
<entry type="GenericError" style="#e82424" />
|
||||||
|
<entry type="GenericTraceback" style="#e82424" />
|
||||||
|
</style>
|
||||||
83
internal/theme/themes/kanagawa-lotus.xml
Normal file
83
internal/theme/themes/kanagawa-lotus.xml
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
<style name="kanagawa-lotus">
|
||||||
|
<entry type="Background" style="bg:#f2ecbc #545464" />
|
||||||
|
<entry type="CodeLine" style="#545464" />
|
||||||
|
<entry type="Error" style="#e82424" />
|
||||||
|
<entry type="Other" style="#545464" />
|
||||||
|
<entry type="LineTableTD" style="" />
|
||||||
|
<entry type="LineTable" style="" />
|
||||||
|
<entry type="LineHighlight" style="bg:#e4d794" />
|
||||||
|
<entry type="LineNumbersTable" style="#a09cac" />
|
||||||
|
<entry type="LineNumbers" style="#a09cac" />
|
||||||
|
<entry type="Keyword" style="#624c83" />
|
||||||
|
<entry type="KeywordReserved" style="#624c83" />
|
||||||
|
<entry type="KeywordPseudo" style="#624c83" />
|
||||||
|
<entry type="KeywordConstant" style="#cc6d00" />
|
||||||
|
<entry type="KeywordDeclaration" style="#624c83" />
|
||||||
|
<entry type="KeywordNamespace" style="#77713f" />
|
||||||
|
<entry type="KeywordType" style="#597b75" />
|
||||||
|
<entry type="Name" style="#545464" />
|
||||||
|
<entry type="NameClass" style="#597b75" />
|
||||||
|
<entry type="NameConstant" style="#cc6d00" />
|
||||||
|
<entry type="NameDecorator" style="bold #cc6d00" />
|
||||||
|
<entry type="NameEntity" style="#77713f" />
|
||||||
|
<entry type="NameException" style="#cc6d00" />
|
||||||
|
<entry type="NameFunction" style="#4d699b" />
|
||||||
|
<entry type="NameFunctionMagic" style="#4d699b" />
|
||||||
|
<entry type="NameLabel" style="#6693bf" />
|
||||||
|
<entry type="NameNamespace" style="#77713f" />
|
||||||
|
<entry type="NameProperty" style="#77713f" />
|
||||||
|
<entry type="NameTag" style="#4d699b" />
|
||||||
|
<entry type="NameVariable" style="#545464" />
|
||||||
|
<entry type="NameVariableClass" style="#545464" />
|
||||||
|
<entry type="NameVariableGlobal" style="#545464" />
|
||||||
|
<entry type="NameVariableInstance" style="#545464" />
|
||||||
|
<entry type="NameVariableMagic" style="#545464" />
|
||||||
|
<entry type="NameAttribute" style="#77713f" />
|
||||||
|
<entry type="NameBuiltin" style="#c84053" />
|
||||||
|
<entry type="NameBuiltinPseudo" style="#c84053" />
|
||||||
|
<entry type="NameOther" style="#545464" />
|
||||||
|
<entry type="Literal" style="#545464" />
|
||||||
|
<entry type="LiteralDate" style="#545464" />
|
||||||
|
<entry type="LiteralString" style="#6f894e" />
|
||||||
|
<entry type="LiteralStringChar" style="#6f894e" />
|
||||||
|
<entry type="LiteralStringSingle" style="#6f894e" />
|
||||||
|
<entry type="LiteralStringDouble" style="#6f894e" />
|
||||||
|
<entry type="LiteralStringBacktick" style="#6f894e" />
|
||||||
|
<entry type="LiteralStringOther" style="#6f894e" />
|
||||||
|
<entry type="LiteralStringSymbol" style="#6f894e" />
|
||||||
|
<entry type="LiteralStringInterpol" style="#6693bf" />
|
||||||
|
<entry type="LiteralStringAffix" style="#c84053" />
|
||||||
|
<entry type="LiteralStringDelimiter" style="#6693bf" />
|
||||||
|
<entry type="LiteralStringEscape" style="#836f4a" />
|
||||||
|
<entry type="LiteralStringRegex" style="#836f4a" />
|
||||||
|
<entry type="LiteralStringDoc" style="#8a8980" />
|
||||||
|
<entry type="LiteralStringHeredoc" style="#8a8980" />
|
||||||
|
<entry type="LiteralNumber" style="#b35b79" />
|
||||||
|
<entry type="LiteralNumberBin" style="#b35b79" />
|
||||||
|
<entry type="LiteralNumberHex" style="#b35b79" />
|
||||||
|
<entry type="LiteralNumberInteger" style="#b35b79" />
|
||||||
|
<entry type="LiteralNumberFloat" style="#b35b79" />
|
||||||
|
<entry type="LiteralNumberIntegerLong" style="#b35b79" />
|
||||||
|
<entry type="LiteralNumberOct" style="#b35b79" />
|
||||||
|
<entry type="Operator" style="bold #836f4a" />
|
||||||
|
<entry type="OperatorWord" style="bold #836f4a" />
|
||||||
|
<entry type="Comment" style="italic #8a8980" />
|
||||||
|
<entry type="CommentSingle" style="italic #8a8980" />
|
||||||
|
<entry type="CommentMultiline" style="italic #8a8980" />
|
||||||
|
<entry type="CommentSpecial" style="italic #8a8980" />
|
||||||
|
<entry type="CommentHashbang" style="italic #8a8980" />
|
||||||
|
<entry type="CommentPreproc" style="italic #c84053" />
|
||||||
|
<entry type="CommentPreprocFile" style="bold #c84053" />
|
||||||
|
<entry type="Generic" style="#545464" />
|
||||||
|
<entry type="GenericInserted" style="bg:#b7d0ae #6e915f" />
|
||||||
|
<entry type="GenericDeleted" style="bg:#d9a594 #d7474b" />
|
||||||
|
<entry type="GenericEmph" style="italic #545464" />
|
||||||
|
<entry type="GenericStrong" style="bold #545464" />
|
||||||
|
<entry type="GenericUnderline" style="underline #545464" />
|
||||||
|
<entry type="GenericHeading" style="bold #4d699b" />
|
||||||
|
<entry type="GenericSubheading" style="bold #4d699b" />
|
||||||
|
<entry type="GenericOutput" style="#545464" />
|
||||||
|
<entry type="GenericPrompt" style="#545464" />
|
||||||
|
<entry type="GenericError" style="#e82424" />
|
||||||
|
<entry type="GenericTraceback" style="#e82424" />
|
||||||
|
</style>
|
||||||
83
internal/theme/themes/kanagawa-wave.xml
Normal file
83
internal/theme/themes/kanagawa-wave.xml
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
<style name="kanagawa-wave">
|
||||||
|
<entry type="Background" style="bg:#1f1f28 #dcd7ba" />
|
||||||
|
<entry type="CodeLine" style="#dcd7ba" />
|
||||||
|
<entry type="Error" style="#e82424" />
|
||||||
|
<entry type="Other" style="#dcd7ba" />
|
||||||
|
<entry type="LineTableTD" style="" />
|
||||||
|
<entry type="LineTable" style="" />
|
||||||
|
<entry type="LineHighlight" style="bg:#363646" />
|
||||||
|
<entry type="LineNumbersTable" style="#54546d" />
|
||||||
|
<entry type="LineNumbers" style="#54546d" />
|
||||||
|
<entry type="Keyword" style="#957fb8" />
|
||||||
|
<entry type="KeywordReserved" style="#957fb8" />
|
||||||
|
<entry type="KeywordPseudo" style="#957fb8" />
|
||||||
|
<entry type="KeywordConstant" style="#ffa066" />
|
||||||
|
<entry type="KeywordDeclaration" style="#957fb8" />
|
||||||
|
<entry type="KeywordNamespace" style="#e6c384" />
|
||||||
|
<entry type="KeywordType" style="#7aa89f" />
|
||||||
|
<entry type="Name" style="#dcd7ba" />
|
||||||
|
<entry type="NameClass" style="#7aa89f" />
|
||||||
|
<entry type="NameConstant" style="#ffa066" />
|
||||||
|
<entry type="NameDecorator" style="bold #ffa066" />
|
||||||
|
<entry type="NameEntity" style="#e6c384" />
|
||||||
|
<entry type="NameException" style="#ffa066" />
|
||||||
|
<entry type="NameFunction" style="#7e9cd8" />
|
||||||
|
<entry type="NameFunctionMagic" style="#7e9cd8" />
|
||||||
|
<entry type="NameLabel" style="#7fb4ca" />
|
||||||
|
<entry type="NameNamespace" style="#e6c384" />
|
||||||
|
<entry type="NameProperty" style="#e6c384" />
|
||||||
|
<entry type="NameTag" style="#7e9cd8" />
|
||||||
|
<entry type="NameVariable" style="#dcd7ba" />
|
||||||
|
<entry type="NameVariableClass" style="#dcd7ba" />
|
||||||
|
<entry type="NameVariableGlobal" style="#dcd7ba" />
|
||||||
|
<entry type="NameVariableInstance" style="#dcd7ba" />
|
||||||
|
<entry type="NameVariableMagic" style="#dcd7ba" />
|
||||||
|
<entry type="NameAttribute" style="#e6c384" />
|
||||||
|
<entry type="NameBuiltin" style="#e46876" />
|
||||||
|
<entry type="NameBuiltinPseudo" style="#e46876" />
|
||||||
|
<entry type="NameOther" style="#dcd7ba" />
|
||||||
|
<entry type="Literal" style="#dcd7ba" />
|
||||||
|
<entry type="LiteralDate" style="#dcd7ba" />
|
||||||
|
<entry type="LiteralString" style="#98bb6c" />
|
||||||
|
<entry type="LiteralStringChar" style="#98bb6c" />
|
||||||
|
<entry type="LiteralStringSingle" style="#98bb6c" />
|
||||||
|
<entry type="LiteralStringDouble" style="#98bb6c" />
|
||||||
|
<entry type="LiteralStringBacktick" style="#98bb6c" />
|
||||||
|
<entry type="LiteralStringOther" style="#98bb6c" />
|
||||||
|
<entry type="LiteralStringSymbol" style="#98bb6c" />
|
||||||
|
<entry type="LiteralStringInterpol" style="#7fb4ca" />
|
||||||
|
<entry type="LiteralStringAffix" style="#ff5d62" />
|
||||||
|
<entry type="LiteralStringDelimiter" style="#7fb4ca" />
|
||||||
|
<entry type="LiteralStringEscape" style="#c0a36e" />
|
||||||
|
<entry type="LiteralStringRegex" style="#c0a36e" />
|
||||||
|
<entry type="LiteralStringDoc" style="#727169" />
|
||||||
|
<entry type="LiteralStringHeredoc" style="#727169" />
|
||||||
|
<entry type="LiteralNumber" style="#d27e99" />
|
||||||
|
<entry type="LiteralNumberBin" style="#d27e99" />
|
||||||
|
<entry type="LiteralNumberHex" style="#d27e99" />
|
||||||
|
<entry type="LiteralNumberInteger" style="#d27e99" />
|
||||||
|
<entry type="LiteralNumberFloat" style="#d27e99" />
|
||||||
|
<entry type="LiteralNumberIntegerLong" style="#d27e99" />
|
||||||
|
<entry type="LiteralNumberOct" style="#d27e99" />
|
||||||
|
<entry type="Operator" style="bold #c0a36e" />
|
||||||
|
<entry type="OperatorWord" style="bold #c0a36e" />
|
||||||
|
<entry type="Comment" style="italic #727169" />
|
||||||
|
<entry type="CommentSingle" style="italic #727169" />
|
||||||
|
<entry type="CommentMultiline" style="italic #727169" />
|
||||||
|
<entry type="CommentSpecial" style="italic #727169" />
|
||||||
|
<entry type="CommentHashbang" style="italic #727169" />
|
||||||
|
<entry type="CommentPreproc" style="italic #e46876" />
|
||||||
|
<entry type="CommentPreprocFile" style="bold #e46876" />
|
||||||
|
<entry type="Generic" style="#dcd7ba" />
|
||||||
|
<entry type="GenericInserted" style="bg:#2b3328 #76946a" />
|
||||||
|
<entry type="GenericDeleted" style="bg:#43242b #c34043" />
|
||||||
|
<entry type="GenericEmph" style="italic #dcd7ba" />
|
||||||
|
<entry type="GenericStrong" style="bold #dcd7ba" />
|
||||||
|
<entry type="GenericUnderline" style="underline #dcd7ba" />
|
||||||
|
<entry type="GenericHeading" style="bold #7e9cd8" />
|
||||||
|
<entry type="GenericSubheading" style="bold #7e9cd8" />
|
||||||
|
<entry type="GenericOutput" style="#dcd7ba" />
|
||||||
|
<entry type="GenericPrompt" style="#dcd7ba" />
|
||||||
|
<entry type="GenericError" style="#e82424" />
|
||||||
|
<entry type="GenericTraceback" style="#e82424" />
|
||||||
|
</style>
|
||||||
Loading…
x
Reference in New Issue
Block a user