Skip to content

Commit

Permalink
feat: use context to store values
Browse files Browse the repository at this point in the history
  • Loading branch information
aymanbagabas committed May 14, 2024
1 parent 43ffb64 commit e310dbe
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 22 deletions.
60 changes: 46 additions & 14 deletions context.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,44 +45,76 @@ type Context interface {
// what else?
}

type contextKey struct{ string }

var (
// ContextKeyColorProfile is the key used to store the terminal's color
// profile in the context.
ContextKeyColorProfile = contextKey{"color-profile"}

// ContextKeyKittyKeyboardFlags is the key used to store the terminal's Kitty
// Keyboard Protocol flags in the context.
ContextKeyKittyKeyboardFlags = contextKey{"kitty-keyboard-flags"}

// ContextKeyBackgroundColor is the key used to store the terminal's background
// color in the context.
ContextKeyBackgroundColor = contextKey{"background-color"}

// ContextKeyHasLightBackground is the key used to store whether the terminal
// has a light background in the context.
ContextKeyHasLightBackground = contextKey{"has-light-background"}
)

type teaContext struct {
context.Context

profile lipgloss.Profile
kittyFlags int
backgroundColor color.Color
hasLightBg bool // cached value

values map[interface{}]interface{}
mtx sync.Mutex
}

func newContext(ctx context.Context) *teaContext {
// newContext returns a new teaContext and a cancel function. It wraps the
// provided context with a new context that can be canceled.
func newContext(ctx context.Context) (*teaContext, context.CancelFunc) {
c := new(teaContext)
c.Context = ctx
c.kittyFlags = -1
var cancel context.CancelFunc
c.Context, cancel = context.WithCancel(ctx)
c.values = make(map[interface{}]interface{})
return c
c.SetValue(ContextKeyKittyKeyboardFlags, -1)
return c, cancel
}

func (c *teaContext) BackgroundColor() color.Color {
return c.backgroundColor
if bg, ok := c.Value(ContextKeyBackgroundColor).(color.Color); ok {
return bg
}
return nil
}

func (c *teaContext) HasLightBackground() bool {
return c.hasLightBg
if v, ok := c.Value(ContextKeyHasLightBackground).(bool); ok {
return v
}
return false
}

func (c *teaContext) SupportsEnhancedKeyboard() bool {
return c.kittyFlags >= 0
if v, ok := c.Value(ContextKeyKittyKeyboardFlags).(int); ok {
return v >= 0
}
return false
}

func (c *teaContext) NewStyle() lipgloss.Style {
return lipgloss.NewStyle().ColorProfile(c.profile).HasLightBackground(c.hasLightBg)
return lipgloss.NewStyle().
ColorProfile(c.ColorProfile()).
HasLightBackground(c.HasLightBackground())
}

func (c *teaContext) ColorProfile() lipgloss.Profile {
return c.profile
if v, ok := c.Value(ContextKeyColorProfile).(lipgloss.Profile); ok {
return v
}
return lipgloss.TrueColor
}

func (ctx *teaContext) Value(key interface{}) interface{} {
Expand Down
2 changes: 1 addition & 1 deletion options.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type ProgramOption func(*Program)
// cancelled it will exit with an error ErrProgramKilled.
func WithContext(ctx context.Context) ProgramOption {
return func(p *Program) {
p.ctx = newContext(ctx)
p.ctx, p.cancel = newContext(ctx)
}
}

Expand Down
12 changes: 5 additions & 7 deletions tea.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ type Program struct {

inputType inputType

ctx *teaContext
ctx Context
cancel context.CancelFunc

msgs chan Msg
Expand Down Expand Up @@ -202,10 +202,8 @@ func NewProgram(model Model, opts ...ProgramOption) *Program {
// A context can be provided with a ProgramOption, but if none was provided
// we'll use the default background context.
if p.ctx == nil {
p.ctx = newContext(context.Background())
p.ctx, p.cancel = newContext(context.Background())
}
// Initialize context and teardown channel.
p.ctx.Context, p.cancel = context.WithCancel(p.ctx)

// if no output was set, set it to stdout
if p.output == nil {
Expand Down Expand Up @@ -431,11 +429,11 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) {
func (p *Program) handleContextMessages(msg Msg) {
switch msg := msg.(type) {
case BackgroundColorMsg:
p.ctx.backgroundColor = msg.Color
p.ctx.SetValue(ContextKeyBackgroundColor, msg.Color)
col, ok := colorful.MakeColor(msg.Color)
if ok {
_, _, l := col.Hsl()
p.ctx.hasLightBg = l > 0.5
p.ctx.SetValue(ContextKeyHasLightBackground, l > 0.5)

Check failure on line 436 in tea.go

View workflow job for this annotation

GitHub Actions / lint-soft

Magic number: 0.5, in <argument> detected (gomnd)
}
}
}
Expand All @@ -450,7 +448,7 @@ func (p *Program) Run() (Model, error) {
p.finished = make(chan struct{}, 1)

// Detect color profile.
p.ctx.profile = lipgloss.DetectColorProfile(p.output, p.environ)
p.ctx.SetValue(ContextKeyColorProfile, lipgloss.DetectColorProfile(p.output, p.environ))

defer p.cancel()

Expand Down

0 comments on commit e310dbe

Please sign in to comment.