asciinema_win 0.1.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 +7 -0
- data/README.md +575 -0
- data/exe/asciinema_win +17 -0
- data/lib/asciinema_win/ansi_parser.rb +437 -0
- data/lib/asciinema_win/asciicast.rb +537 -0
- data/lib/asciinema_win/cli.rb +591 -0
- data/lib/asciinema_win/export.rb +780 -0
- data/lib/asciinema_win/output_organizer.rb +276 -0
- data/lib/asciinema_win/player.rb +348 -0
- data/lib/asciinema_win/recorder.rb +480 -0
- data/lib/asciinema_win/screen_buffer.rb +375 -0
- data/lib/asciinema_win/themes.rb +334 -0
- data/lib/asciinema_win/version.rb +6 -0
- data/lib/asciinema_win.rb +153 -0
- data/lib/rich/_palettes.rb +148 -0
- data/lib/rich/box.rb +342 -0
- data/lib/rich/cells.rb +512 -0
- data/lib/rich/color.rb +628 -0
- data/lib/rich/color_triplet.rb +220 -0
- data/lib/rich/console.rb +549 -0
- data/lib/rich/control.rb +332 -0
- data/lib/rich/json.rb +254 -0
- data/lib/rich/layout.rb +314 -0
- data/lib/rich/markdown.rb +509 -0
- data/lib/rich/markup.rb +175 -0
- data/lib/rich/panel.rb +311 -0
- data/lib/rich/progress.rb +430 -0
- data/lib/rich/segment.rb +387 -0
- data/lib/rich/style.rb +433 -0
- data/lib/rich/syntax.rb +1145 -0
- data/lib/rich/table.rb +525 -0
- data/lib/rich/terminal_theme.rb +126 -0
- data/lib/rich/text.rb +433 -0
- data/lib/rich/tree.rb +220 -0
- data/lib/rich/version.rb +5 -0
- data/lib/rich/win32_console.rb +859 -0
- data/lib/rich.rb +108 -0
- metadata +123 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rich
|
|
4
|
+
# Represents an RGB color triplet with values from 0-255.
|
|
5
|
+
# This is an immutable value object used for true color representation.
|
|
6
|
+
class ColorTriplet
|
|
7
|
+
# @return [Integer] Red component (0-255)
|
|
8
|
+
attr_reader :red
|
|
9
|
+
|
|
10
|
+
# @return [Integer] Green component (0-255)
|
|
11
|
+
attr_reader :green
|
|
12
|
+
|
|
13
|
+
# @return [Integer] Blue component (0-255)
|
|
14
|
+
attr_reader :blue
|
|
15
|
+
|
|
16
|
+
# Create a new color triplet
|
|
17
|
+
# @param red [Integer] Red component (0-255)
|
|
18
|
+
# @param green [Integer] Green component (0-255)
|
|
19
|
+
# @param blue [Integer] Blue component (0-255)
|
|
20
|
+
def initialize(red, green, blue)
|
|
21
|
+
@red = clamp_component(red)
|
|
22
|
+
@green = clamp_component(green)
|
|
23
|
+
@blue = clamp_component(blue)
|
|
24
|
+
freeze
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @return [String] Hexadecimal representation (e.g., "#ff0000")
|
|
28
|
+
def hex
|
|
29
|
+
format("%02x%02x%02x", @red, @green, @blue)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# @return [String] RGB string representation (e.g., "rgb(255, 0, 0)")
|
|
33
|
+
def rgb
|
|
34
|
+
"rgb(#{@red}, #{@green}, #{@blue})"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# @return [Array<Float>] Normalized components (0.0-1.0)
|
|
38
|
+
def normalized
|
|
39
|
+
[@red / 255.0, @green / 255.0, @blue / 255.0]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @return [Array<Integer>] Components as array [red, green, blue]
|
|
43
|
+
def to_a
|
|
44
|
+
[@red, @green, @blue]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# @return [Hash] Components as hash
|
|
48
|
+
def to_h
|
|
49
|
+
{ red: @red, green: @green, blue: @blue }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Check equality with another triplet
|
|
53
|
+
# @param other [ColorTriplet, Object] Object to compare
|
|
54
|
+
# @return [Boolean]
|
|
55
|
+
def ==(other)
|
|
56
|
+
return false unless other.is_a?(ColorTriplet)
|
|
57
|
+
|
|
58
|
+
@red == other.red && @green == other.green && @blue == other.blue
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
alias eql? ==
|
|
62
|
+
|
|
63
|
+
# @return [Integer] Hash code for use in hash tables
|
|
64
|
+
def hash
|
|
65
|
+
[@red, @green, @blue].hash
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# @return [String] String representation
|
|
69
|
+
def to_s
|
|
70
|
+
hex
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# @return [String] Inspect representation
|
|
74
|
+
def inspect
|
|
75
|
+
"#<Rich::ColorTriplet #{hex} (#{@red}, #{@green}, #{@blue})>"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Deconstruct for pattern matching
|
|
79
|
+
# @return [Array<Integer>]
|
|
80
|
+
def deconstruct
|
|
81
|
+
to_a
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Deconstruct for pattern matching with keys
|
|
85
|
+
# @param keys [Array<Symbol>]
|
|
86
|
+
# @return [Hash]
|
|
87
|
+
def deconstruct_keys(keys)
|
|
88
|
+
to_h.slice(*(keys || [:red, :green, :blue]))
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Calculate the perceived luminance of the color
|
|
92
|
+
# Uses the formula for relative luminance from WCAG 2.0
|
|
93
|
+
# @return [Float] Luminance value (0.0-1.0)
|
|
94
|
+
def luminance
|
|
95
|
+
r, g, b = normalized.map do |c|
|
|
96
|
+
c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055)**2.4
|
|
97
|
+
end
|
|
98
|
+
0.2126 * r + 0.7152 * g + 0.0722 * b
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Check if this is a "dark" color based on luminance
|
|
102
|
+
# @return [Boolean]
|
|
103
|
+
def dark?
|
|
104
|
+
luminance < 0.5
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Check if this is a "light" color based on luminance
|
|
108
|
+
# @return [Boolean]
|
|
109
|
+
def light?
|
|
110
|
+
!dark?
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Blend this color with another
|
|
114
|
+
# @param other [ColorTriplet] Color to blend with
|
|
115
|
+
# @param factor [Float] Blend factor (0.0 = this color, 1.0 = other color)
|
|
116
|
+
# @return [ColorTriplet] Blended color
|
|
117
|
+
def blend(other, factor = 0.5)
|
|
118
|
+
factor = [[factor, 0.0].max, 1.0].min
|
|
119
|
+
|
|
120
|
+
new_r = (@red + (other.red - @red) * factor).round
|
|
121
|
+
new_g = (@green + (other.green - @green) * factor).round
|
|
122
|
+
new_b = (@blue + (other.blue - @blue) * factor).round
|
|
123
|
+
|
|
124
|
+
ColorTriplet.new(new_r, new_g, new_b)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Calculate color distance (Euclidean in RGB space)
|
|
128
|
+
# @param other [ColorTriplet] Color to compare
|
|
129
|
+
# @return [Float] Distance value
|
|
130
|
+
def distance(other)
|
|
131
|
+
dr = @red - other.red
|
|
132
|
+
dg = @green - other.green
|
|
133
|
+
db = @blue - other.blue
|
|
134
|
+
Math.sqrt(dr * dr + dg * dg + db * db)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Calculate weighted color distance (better perceptual accuracy)
|
|
138
|
+
# Uses weighted Euclidean distance based on human color perception
|
|
139
|
+
# @param other [ColorTriplet] Color to compare
|
|
140
|
+
# @return [Float] Weighted distance value
|
|
141
|
+
def weighted_distance(other)
|
|
142
|
+
dr = @red - other.red
|
|
143
|
+
dg = @green - other.green
|
|
144
|
+
db = @blue - other.blue
|
|
145
|
+
|
|
146
|
+
# Weighted by perceptual importance (red-green component is most important)
|
|
147
|
+
r_mean = (@red + other.red) / 2.0
|
|
148
|
+
weight_r = 2.0 + r_mean / 256.0
|
|
149
|
+
weight_g = 4.0
|
|
150
|
+
weight_b = 2.0 + (255.0 - r_mean) / 256.0
|
|
151
|
+
|
|
152
|
+
Math.sqrt(weight_r * dr * dr + weight_g * dg * dg + weight_b * db * db)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
class << self
|
|
156
|
+
# Create from hex string
|
|
157
|
+
# @param hex_str [String] Hex color string (e.g., "#ff0000" or "ff0000")
|
|
158
|
+
# @return [ColorTriplet]
|
|
159
|
+
def from_hex(hex_str)
|
|
160
|
+
hex_str = hex_str.delete_prefix("#")
|
|
161
|
+
raise ArgumentError, "Invalid hex color: #{hex_str}" unless hex_str.match?(/\A[0-9a-fA-F]{6}\z/)
|
|
162
|
+
|
|
163
|
+
r = hex_str[0, 2].to_i(16)
|
|
164
|
+
g = hex_str[2, 2].to_i(16)
|
|
165
|
+
b = hex_str[4, 2].to_i(16)
|
|
166
|
+
|
|
167
|
+
new(r, g, b)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# Create from normalized values (0.0-1.0)
|
|
171
|
+
# @param r [Float] Red component (0.0-1.0)
|
|
172
|
+
# @param g [Float] Green component (0.0-1.0)
|
|
173
|
+
# @param b [Float] Blue component (0.0-1.0)
|
|
174
|
+
# @return [ColorTriplet]
|
|
175
|
+
def from_normalized(r, g, b)
|
|
176
|
+
new(
|
|
177
|
+
(r * 255).round,
|
|
178
|
+
(g * 255).round,
|
|
179
|
+
(b * 255).round
|
|
180
|
+
)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Create from HSL values
|
|
184
|
+
# @param h [Float] Hue (0-360)
|
|
185
|
+
# @param s [Float] Saturation (0-100)
|
|
186
|
+
# @param l [Float] Lightness (0-100)
|
|
187
|
+
# @return [ColorTriplet]
|
|
188
|
+
def from_hsl(h, s, l)
|
|
189
|
+
h = h % 360
|
|
190
|
+
s = s / 100.0
|
|
191
|
+
l = l / 100.0
|
|
192
|
+
|
|
193
|
+
c = (1 - (2 * l - 1).abs) * s
|
|
194
|
+
x = c * (1 - ((h / 60.0) % 2 - 1).abs)
|
|
195
|
+
m = l - c / 2.0
|
|
196
|
+
|
|
197
|
+
r, g, b = case (h / 60).floor
|
|
198
|
+
when 0 then [c, x, 0]
|
|
199
|
+
when 1 then [x, c, 0]
|
|
200
|
+
when 2 then [0, c, x]
|
|
201
|
+
when 3 then [0, x, c]
|
|
202
|
+
when 4 then [x, 0, c]
|
|
203
|
+
else [c, 0, x]
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
new(
|
|
207
|
+
((r + m) * 255).round,
|
|
208
|
+
((g + m) * 255).round,
|
|
209
|
+
((b + m) * 255).round
|
|
210
|
+
)
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
private
|
|
215
|
+
|
|
216
|
+
def clamp_component(value)
|
|
217
|
+
[[value.to_i, 0].max, 255].min
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|