fix: register chroma style once

don't register chroma style if it's already registered

this could cause a "concurrent map writes" fatal error when used in a
concurrent setting like a bubbletea wish app. use a package-wide mutex
to protect registering a new style.
This commit is contained in:
Ayman Bagabas
2022-07-27 20:34:16 +02:00
committed by Christian Muehlhaeuser
parent 9aceb96bb7
commit a99aac8527
+20 -2
View File
@@ -2,6 +2,7 @@ package ansi
import (
"io"
"sync"
"github.com/alecthomas/chroma"
"github.com/alecthomas/chroma/quick"
@@ -9,6 +10,17 @@ import (
"github.com/muesli/reflow/indent"
)
const (
// The chroma style theme name used for rendering.
chromaStyleTheme = "charm"
)
var (
// mutex for synchronizing access to the chroma style registry.
// Related https://github.com/alecthomas/chroma/pull/650
mutex = sync.Mutex{}
)
// A CodeBlockElement is used to render code blocks.
type CodeBlockElement struct {
Code string
@@ -64,8 +76,12 @@ func (e *CodeBlockElement) Render(w io.Writer, ctx RenderContext) error {
theme := rules.Theme
if rules.Chroma != nil && ctx.options.ColorProfile > 1 {
theme = "charm"
styles.Register(chroma.MustNewStyle("charm",
theme = chromaStyleTheme
mutex.Lock()
// Don't register the style if it's already registered.
_, ok := styles.Registry[theme]
if !ok {
styles.Register(chroma.MustNewStyle(theme,
chroma.StyleEntries{
chroma.Text: chromaStyle(rules.Chroma.Text),
chroma.Error: chromaStyle(rules.Chroma.Error),
@@ -100,6 +116,8 @@ func (e *CodeBlockElement) Render(w io.Writer, ctx RenderContext) error {
chroma.Background: chromaStyle(rules.Chroma.Background),
}))
}
mutex.Unlock()
}
iw := indent.NewWriterPipe(w, indentation+margin, func(wr io.Writer) {
renderText(w, ctx.options.ColorProfile, bs.Current().Style.StylePrimitive, " ")