Class: Potty::Theme

Inherits:
Object
  • Object
show all
Defined in:
lib/potty/theme.rb

Overview

Theme maps semantic names to colours, and speaks two dialects:

theme.style(:info)  => a Style (symbolic, render-target-agnostic) —
                       the path Surfaces resolve, for curses OR inline.
theme[:info]        => a curses attribute integer (a colour pair) —
                       back-compat for code that draws straight to a
                       Curses window. Only meaningful once curses is up.

The symbolic PALETTE is the source of truth; the curses pairs are derived from it in setup_colors, so the two dialects never drift.

Constant Summary collapse

COLORS =

Symbolic colour names -> curses colour numbers (-1 = terminal default).

{
  default: -1,
  black: ::Curses::COLOR_BLACK,   red: ::Curses::COLOR_RED,
  green: ::Curses::COLOR_GREEN,   yellow: ::Curses::COLOR_YELLOW,
  blue: ::Curses::COLOR_BLUE,     magenta: ::Curses::COLOR_MAGENTA,
  cyan: ::Curses::COLOR_CYAN,     white: ::Curses::COLOR_WHITE,
  bright_black: 8
}.freeze
PALETTE =

name -> { fg:, bg: } in symbolic colours. Body text inherits the terminal’s own colours (:default) so potty blends into any theme; only deliberate highlights carry an explicit background.

{
  normal:   { fg: :default,      bg: :default },
  selected: { fg: :black,        bg: :green },
  disabled: { fg: :bright_black, bg: :default },
  success:  { fg: :green,        bg: :default },
  error:    { fg: :red,          bg: :default },
  warning:  { fg: :yellow,       bg: :default },
  info:     { fg: :cyan,         bg: :default },
  dim:      { fg: :bright_black, bg: :default },
  header:   { fg: :white,        bg: :blue },
  status:   { fg: :black,        bg: :cyan }
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(palette = nil) ⇒ Theme

Pass a partial palette ({ name => { fg:, bg: } }) to override entries.



47
48
49
50
51
# File 'lib/potty/theme.rb', line 47

def initialize(palette = nil)
  @palette = palette ? PALETTE.merge(palette) : PALETTE
  @colors = {}
  setup_colors if ::Curses.has_colors?
end

Instance Attribute Details

#colorsObject (readonly)

Returns the value of attribute colors.



44
45
46
# File 'lib/potty/theme.rb', line 44

def colors
  @colors
end

#paletteObject (readonly)

Returns the value of attribute palette.



44
45
46
# File 'lib/potty/theme.rb', line 44

def palette
  @palette
end

Instance Method Details

#[](name) ⇒ Object

Curses attribute integer (back-compat for direct-to-window drawing).



71
72
73
# File 'lib/potty/theme.rb', line 71

def [](name)
  @colors[name] || @colors[:normal] || 0
end

#attr(name, bold: false, underline: false) ⇒ Object



75
76
77
78
79
80
# File 'lib/potty/theme.rb', line 75

def attr(name, bold: false, underline: false)
  a = self[name]
  a |= ::Curses::A_BOLD if bold
  a |= ::Curses::A_UNDERLINE if underline
  a
end

#setup_colorsObject

Allocate a curses colour pair per palette entry (curses mode only).



54
55
56
57
58
59
60
61
62
# File 'lib/potty/theme.rb', line 54

def setup_colors
  ::Curses.start_color
  ::Curses.use_default_colors
  @palette.each_with_index do |(name, c), idx|
    pair = idx + 1
    ::Curses.init_pair(pair, COLORS.fetch(c[:fg], -1), COLORS.fetch(c[:bg], -1))
    @colors[name] = ::Curses.color_pair(pair)
  end
end

#style(name, bold: false, underline: false, reverse: false) ⇒ Object

Semantic style — symbolic colours + attributes, resolved by a Surface.



65
66
67
68
# File 'lib/potty/theme.rb', line 65

def style(name, bold: false, underline: false, reverse: false)
  c = @palette[name] || @palette[:normal]
  Style.new(fg: c[:fg], bg: c[:bg], bold: bold, underline: underline, reverse: reverse)
end