Class: TuiTui::Theme

Inherits:
Data
  • Object
show all
Defined in:
lib/tui_tui/theme.rb,
lib/tui_tui/theme.rb,
lib/tui_tui/theme.rb

Overview

Semantic Style roles shared by the built-in widgets. Themes combine a background surface with an accent hue.

Constant Summary collapse

SURFACES =

Background-dependent neutral roles.

{
  dark: {
    text: Style.new,
    muted: Style.new(fg: 245),
    bar: Style.new(fg: 252, bg: 238),
    selection_dim: Style.new(fg: 247, bg: 238)
  },
  light: {
    text: Style.new,
    muted: Style.new(fg: 240),
    bar: Style.new(fg: 16, bg: 252),
    selection_dim: Style.new(fg: 240, bg: 252)
  }
}.freeze
ACCENTS =

Accent roles per hue and background.

{
  cool: {
    dark: {line: 66, title: 109, accent: 73, sel: [231, 60]},
    light: {line: 30, title: 25, accent: 30, sel: [16, 152]}
  },
  warm: {
    dark: {line: 95, title: 137, accent: 173, sel: [231, 95]},
    light: {line: 95, title: 94, accent: 130, sel: [16, 180]}
  },
  mono: {
    dark: {line: 240, title: 252, accent: 252, sel: [16, 250]},
    light: {line: 240, title: 236, accent: 236, sel: [16, 250]}
  }
}.freeze
LIGHT_FGBG =

COLORFGBG background values meaning “light”.

%w[7 15].freeze
TABLE =

Shared palettes for every surface/hue pair.

SURFACES.keys.product(ACCENTS.keys).to_h { |bg, hue| [[bg, hue], compose(bg, hue)] }.freeze
DARK =
Theme.build(background: :dark, hue: :cool)
LIGHT =
Theme.build(background: :light, hue: :cool)
DEFAULT =
Theme::DARK
WARM =
Theme.build(background: :dark, hue: :warm)
MONO =
Theme.build(background: :dark, hue: :mono)
PRESETS =
{
  default: DEFAULT,
  cool: DEFAULT,
  dark: DARK,
  light: LIGHT,
  warm: WARM,
  mono: MONO
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Attribute Details

#accentObject (readonly)

Returns the value of attribute accent

Returns:

  • (Object)

    the current value of accent



8
9
10
# File 'lib/tui_tui/theme.rb', line 8

def accent
  @accent
end

#barObject (readonly)

Returns the value of attribute bar

Returns:

  • (Object)

    the current value of bar



8
9
10
# File 'lib/tui_tui/theme.rb', line 8

def bar
  @bar
end

#cursorObject (readonly)

Returns the value of attribute cursor

Returns:

  • (Object)

    the current value of cursor



8
9
10
# File 'lib/tui_tui/theme.rb', line 8

def cursor
  @cursor
end

#frameObject (readonly)

Returns the value of attribute frame

Returns:

  • (Object)

    the current value of frame



8
9
10
# File 'lib/tui_tui/theme.rb', line 8

def frame
  @frame
end

#mutedObject (readonly)

Returns the value of attribute muted

Returns:

  • (Object)

    the current value of muted



8
9
10
# File 'lib/tui_tui/theme.rb', line 8

def muted
  @muted
end

#scroll_thumbObject (readonly)

Returns the value of attribute scroll_thumb

Returns:

  • (Object)

    the current value of scroll_thumb



8
9
10
# File 'lib/tui_tui/theme.rb', line 8

def scroll_thumb
  @scroll_thumb
end

#scroll_trackObject (readonly)

Returns the value of attribute scroll_track

Returns:

  • (Object)

    the current value of scroll_track



8
9
10
# File 'lib/tui_tui/theme.rb', line 8

def scroll_track
  @scroll_track
end

#selectionObject (readonly)

Returns the value of attribute selection

Returns:

  • (Object)

    the current value of selection



8
9
10
# File 'lib/tui_tui/theme.rb', line 8

def selection
  @selection
end

#selection_dimObject (readonly)

Returns the value of attribute selection_dim

Returns:

  • (Object)

    the current value of selection_dim



8
9
10
# File 'lib/tui_tui/theme.rb', line 8

def selection_dim
  @selection_dim
end

#textObject (readonly)

Returns the value of attribute text

Returns:

  • (Object)

    the current value of text



8
9
10
# File 'lib/tui_tui/theme.rb', line 8

def text
  @text
end

#titleObject (readonly)

Returns the value of attribute title

Returns:

  • (Object)

    the current value of title



8
9
10
# File 'lib/tui_tui/theme.rb', line 8

def title
  @title
end

Class Method Details

.auto(hue: :cool, env: ENV) ⇒ Object

The hue palette tuned for the detected background.



105
# File 'lib/tui_tui/theme.rb', line 105

def self.auto(hue: :cool, env: ENV) = build(background: detect_background(env: env), hue: hue)

.bold(fg) ⇒ Object



64
# File 'lib/tui_tui/theme.rb', line 64

def self.bold(fg) = Style.new(fg: fg, attrs: [:bold])

.build(background: :dark, hue: :cool) ⇒ Object



89
# File 'lib/tui_tui/theme.rb', line 89

def self.build(background: :dark, hue: :cool) = TABLE.fetch([background, hue])

.compose(background, hue) ⇒ Object

Build the palette for a (background, hue) pair.



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/tui_tui/theme.rb', line 67

def self.compose(background, hue)
  surface = SURFACES.fetch(background)
  a = ACCENTS.fetch(hue).fetch(background)
  selection = Style.new(fg: a[:sel][0], bg: a[:sel][1])
  new(
    frame: Style.new(fg: a[:line]),
    title: bold(a[:title]),
    text: surface[:text],
    muted: surface[:muted],
    accent: bold(a[:accent]),
    selection: selection,
    selection_dim: surface[:selection_dim],
    bar: surface[:bar],
    cursor: selection,
    scroll_track: Style.new(fg: a[:line]),
    scroll_thumb: Style.new(bg: a[:sel][1])
  )
end

.detect_background(env: ENV) ⇒ Object

Best-effort terminal background (:light/:dark).



92
93
94
95
96
97
98
99
100
101
102
# File 'lib/tui_tui/theme.rb', line 92

def self.detect_background(env: ENV)
  case env["TUITUI_BACKGROUND"]&.downcase
  when "light"
    :light
  when "dark"
    :dark
  else
    bg = env["COLORFGBG"]&.split(";")&.last
    bg && LIGHT_FGBG.include?(bg) ? :light : :dark
  end
end

.named(name) ⇒ Object

Fetch a preset by name (Symbol/String); unknown names fall back to DEFAULT.



108
# File 'lib/tui_tui/theme.rb', line 108

def self.named(name) = PRESETS.fetch(name&.to_sym, DEFAULT)