tuile 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/README.md +151 -5
- data/examples/file_commander.rb +4 -3
- data/examples/sampler.rb +4 -3
- data/lib/tuile/ansi.rb +4 -3
- data/lib/tuile/color.rb +122 -0
- data/lib/tuile/component/button.rb +9 -5
- data/lib/tuile/component/label.rb +13 -15
- data/lib/tuile/component/layout.rb +1 -1
- data/lib/tuile/component/list.rb +64 -31
- data/lib/tuile/component/log_window.rb +1 -0
- data/lib/tuile/component/picker_window.rb +4 -4
- data/lib/tuile/component/popup.rb +34 -3
- data/lib/tuile/component/text_area.rb +1 -2
- data/lib/tuile/component/text_field.rb +1 -2
- data/lib/tuile/component/text_input.rb +10 -15
- data/lib/tuile/component/text_view.rb +33 -13
- data/lib/tuile/component/window.rb +70 -16
- data/lib/tuile/component.rb +75 -6
- data/lib/tuile/event_queue.rb +26 -2
- data/lib/tuile/fake_screen.rb +8 -0
- data/lib/tuile/keys.rb +9 -3
- data/lib/tuile/rect.rb +12 -0
- data/lib/tuile/screen.rb +118 -20
- data/lib/tuile/screen_pane.rb +1 -1
- data/lib/tuile/sizing.rb +59 -0
- data/lib/tuile/styled_string.rb +125 -30
- data/lib/tuile/terminal_background.rb +137 -0
- data/lib/tuile/theme.rb +202 -0
- data/lib/tuile/theme_def.rb +85 -0
- data/lib/tuile/version.rb +1 -1
- data/lib/tuile.rb +0 -1
- data/mise.toml +2 -0
- data/sig/tuile.rbs +755 -62
- metadata +12 -18
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tuile
|
|
4
|
+
# An app's theme definition: the {Theme} pair covering both terminal
|
|
5
|
+
# appearances. {Screen} keeps one at {Screen#theme_def} (defaulting to
|
|
6
|
+
# {DEFAULT}) and picks the member matching the detected background at
|
|
7
|
+
# startup and on every OS appearance flip (mode 2031) — so a custom
|
|
8
|
+
# definition survives the user toggling light/dark, where a bare
|
|
9
|
+
# {Screen#theme=} assignment would be replaced.
|
|
10
|
+
#
|
|
11
|
+
# APP_THEME = Tuile::ThemeDef.new(
|
|
12
|
+
# dark: Tuile::Theme::DARK.with(custom: { accent: Color::DARK_ORANGE }),
|
|
13
|
+
# light: Tuile::Theme::LIGHT.with(custom: { accent: Color::DARK_ORANGE3 })
|
|
14
|
+
# )
|
|
15
|
+
# screen.theme_def = APP_THEME
|
|
16
|
+
#
|
|
17
|
+
# Both members must declare the same {Theme#custom} key set. Without
|
|
18
|
+
# that, a token present only in one member would raise `KeyError` at
|
|
19
|
+
# the unpredictable moment the user flips OS appearance; checking here
|
|
20
|
+
# turns it into an immediate construction-time failure.
|
|
21
|
+
#
|
|
22
|
+
# @!attribute [r] dark
|
|
23
|
+
# The theme applied on dark terminal backgrounds.
|
|
24
|
+
# @return [Theme]
|
|
25
|
+
# @!attribute [r] light
|
|
26
|
+
# The theme applied on light terminal backgrounds.
|
|
27
|
+
# @return [Theme]
|
|
28
|
+
class ThemeDef < Data.define(:dark, :light)
|
|
29
|
+
# @param dark [Theme]
|
|
30
|
+
# @param light [Theme]
|
|
31
|
+
# @raise [TypeError] when a member is not a {Theme}.
|
|
32
|
+
# @raise [ArgumentError] when the members' {Theme#custom} key sets differ.
|
|
33
|
+
def initialize(dark:, light:)
|
|
34
|
+
raise TypeError, "dark must be a Tuile::Theme, got #{dark.inspect}" unless dark.is_a?(Theme)
|
|
35
|
+
raise TypeError, "light must be a Tuile::Theme, got #{light.inspect}" unless light.is_a?(Theme)
|
|
36
|
+
|
|
37
|
+
if dark.custom.keys.sort != light.custom.keys.sort
|
|
38
|
+
raise ArgumentError,
|
|
39
|
+
"dark and light must declare the same custom tokens; " \
|
|
40
|
+
"dark has #{dark.custom.keys.sort.inspect}, light has #{light.custom.keys.sort.inspect}"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
super
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# The member for the given color scheme. Anything other than `:light`
|
|
47
|
+
# selects {#dark}, matching {TerminalBackground.detect}'s
|
|
48
|
+
# inconclusive-means-dark policy.
|
|
49
|
+
# @param scheme [Symbol] `:dark` or `:light`.
|
|
50
|
+
# @return [Theme]
|
|
51
|
+
def for(scheme) = scheme == :light ? light : dark
|
|
52
|
+
|
|
53
|
+
# The built-in pair: {Theme::DARK} / {Theme::LIGHT}.
|
|
54
|
+
# @return [ThemeDef]
|
|
55
|
+
DEFAULT = new(dark: Theme::DARK, light: Theme::LIGHT)
|
|
56
|
+
|
|
57
|
+
class << self
|
|
58
|
+
# The definition newly-constructed {Screen}s start from (see
|
|
59
|
+
# {Screen#theme_def}); initially {DEFAULT}. Reassigning affects
|
|
60
|
+
# future screens only — an already-constructed screen keeps its
|
|
61
|
+
# definition until {Screen#theme_def=}.
|
|
62
|
+
#
|
|
63
|
+
# Intended for test suites: production apps assign
|
|
64
|
+
# {Screen#theme_def=} once at startup, but component specs build a
|
|
65
|
+
# fresh {FakeScreen} per example, and a component reading a custom
|
|
66
|
+
# token (`theme[:accent]`) would `KeyError` against the built-in
|
|
67
|
+
# default. Point this at the app's definition once and every
|
|
68
|
+
# {Screen.fake} carries it:
|
|
69
|
+
#
|
|
70
|
+
# Tuile::ThemeDef.default = APP_THEME # spec_helper.rb, once
|
|
71
|
+
# before { Screen.fake } # theme[:accent] resolves
|
|
72
|
+
# @return [ThemeDef]
|
|
73
|
+
attr_reader :default
|
|
74
|
+
|
|
75
|
+
# @param theme_def [ThemeDef]
|
|
76
|
+
# @raise [TypeError] when not a {ThemeDef}.
|
|
77
|
+
def default=(theme_def)
|
|
78
|
+
raise TypeError, "expected ThemeDef, got #{theme_def.inspect}" unless theme_def.is_a?(ThemeDef)
|
|
79
|
+
|
|
80
|
+
@default = theme_def
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
@default = DEFAULT
|
|
84
|
+
end
|
|
85
|
+
end
|
data/lib/tuile/version.rb
CHANGED
data/lib/tuile.rb
CHANGED
data/mise.toml
ADDED