natty-ui 0.35.0 → 1.0.2
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/README.md +6 -6
- data/examples/24bit-colors.rb +9 -5
- data/examples/3bit-colors.rb +7 -7
- data/examples/8bit-colors.rb +5 -7
- data/examples/attributes.rb +2 -3
- data/examples/elements.rb +9 -6
- data/examples/examples.rb +9 -9
- data/examples/frames.rb +31 -0
- data/examples/hbars.rb +6 -3
- data/examples/info.rb +13 -10
- data/examples/key-codes.rb +8 -9
- data/examples/ls.rb +24 -22
- data/examples/named-colors.rb +4 -3
- data/examples/sections.rb +26 -24
- data/examples/select.rb +28 -0
- data/examples/sh.rb +25 -7
- data/examples/tables.rb +19 -37
- data/examples/tasks.rb +32 -22
- data/examples/vbars.rb +5 -3
- data/lib/natty-ui/dumb_progress.rb +68 -0
- data/lib/natty-ui/element.rb +61 -70
- data/lib/natty-ui/features.rb +771 -949
- data/lib/natty-ui/frame.rb +87 -0
- data/lib/natty-ui/helper/table.rb +1376 -0
- data/lib/natty-ui/margin.rb +83 -0
- data/lib/natty-ui/progress.rb +116 -152
- data/lib/natty-ui/renderer/bars.rb +93 -0
- data/lib/natty-ui/renderer/choice.rb +56 -0
- data/lib/natty-ui/renderer/dumb_choice.rb +34 -0
- data/lib/natty-ui/renderer/dumb_select.rb +60 -0
- data/lib/natty-ui/renderer/dumb_shell_runner.rb +19 -0
- data/lib/natty-ui/renderer/heading.rb +26 -0
- data/lib/natty-ui/renderer/horizontal_rule.rb +32 -0
- data/lib/natty-ui/{ls_renderer.rb → renderer/ls.rb} +15 -27
- data/lib/natty-ui/renderer/mark.rb +13 -0
- data/lib/natty-ui/renderer/quote.rb +13 -0
- data/lib/natty-ui/renderer/select.rb +63 -0
- data/lib/natty-ui/renderer/shell.rb +15 -0
- data/lib/natty-ui/renderer/shell_runner.rb +29 -0
- data/lib/natty-ui/renderer/table_renderer.rb +429 -0
- data/lib/natty-ui/section.rb +144 -32
- data/lib/natty-ui/task.rb +38 -25
- data/lib/natty-ui/temporary.rb +27 -14
- data/lib/natty-ui/utils/border.rb +139 -0
- data/lib/natty-ui/utils/str_const.rb +62 -0
- data/lib/natty-ui/utils/utils.rb +47 -0
- data/lib/natty-ui/version.rb +1 -1
- data/lib/natty-ui.rb +76 -35
- metadata +31 -28
- data/examples/cols.rb +0 -38
- data/examples/illustration.rb +0 -60
- data/examples/options.rb +0 -28
- data/examples/themes.rb +0 -51
- data/lib/natty-ui/attributes.rb +0 -593
- data/lib/natty-ui/choice.rb +0 -67
- data/lib/natty-ui/dumb_choice.rb +0 -47
- data/lib/natty-ui/dumb_options.rb +0 -64
- data/lib/natty-ui/framed.rb +0 -50
- data/lib/natty-ui/hbars_renderer.rb +0 -66
- data/lib/natty-ui/options.rb +0 -78
- data/lib/natty-ui/shell_renderer.rb +0 -91
- data/lib/natty-ui/table.rb +0 -325
- data/lib/natty-ui/table_renderer.rb +0 -165
- data/lib/natty-ui/theme.rb +0 -403
- data/lib/natty-ui/utils.rb +0 -111
- data/lib/natty-ui/vbars_renderer.rb +0 -49
- data/lib/natty-ui/width_finder.rb +0 -137
- data/natty-ui.gemspec +0 -34
data/lib/natty-ui/attributes.rb
DELETED
|
@@ -1,593 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module NattyUI
|
|
4
|
-
# @todo This chapter needs more documentation.
|
|
5
|
-
#
|
|
6
|
-
class Attributes
|
|
7
|
-
# @return [Attributes] updated copy of itself
|
|
8
|
-
def merge(**attributes)
|
|
9
|
-
attributes.empty? ? dup : dup._assign(attributes)
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
# @return [Attributes] itself
|
|
13
|
-
def merge!(**attributes) = attributes.empty? ? self : _assign(attributes)
|
|
14
|
-
alias assign merge!
|
|
15
|
-
|
|
16
|
-
# @private
|
|
17
|
-
def to_hash = _store({})
|
|
18
|
-
|
|
19
|
-
# @private
|
|
20
|
-
def to_h(&block) = block ? _store({}).to_h(&block) : _store({})
|
|
21
|
-
|
|
22
|
-
private
|
|
23
|
-
|
|
24
|
-
def initialize(**attributes)
|
|
25
|
-
_init
|
|
26
|
-
_assign(attributes) unless attributes.empty?
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def _init = nil
|
|
30
|
-
def _assign(_opt) = self
|
|
31
|
-
def _store(opt) = opt
|
|
32
|
-
def as_uint(value) = [0, value.to_i].max
|
|
33
|
-
def as_nint(value) = ([0, value.to_i].max if value)
|
|
34
|
-
|
|
35
|
-
def as_wh(value)
|
|
36
|
-
return unless value
|
|
37
|
-
return value > 0 ? value : nil if value.is_a?(Numeric)
|
|
38
|
-
value.is_a?(Range) ? wh_from(value.begin, value.end) : nil
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def wh_from(min, max)
|
|
42
|
-
min = normalized(min)
|
|
43
|
-
max = normalized(max)
|
|
44
|
-
return max ? (..max) : nil unless min
|
|
45
|
-
return Range.new(min, nil) unless max
|
|
46
|
-
min == max ? min : Range.new(*[min, max].minmax)
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def normalized(value)
|
|
50
|
-
return value < 0 ? nil : value if value.is_a?(Float) && value < 1
|
|
51
|
-
(value = value.to_i) < 1 ? nil : value
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
module Align
|
|
55
|
-
# Horizontal element alignment.
|
|
56
|
-
#
|
|
57
|
-
# @return [:left, :right, :centered]
|
|
58
|
-
attr_reader :align
|
|
59
|
-
|
|
60
|
-
# @attribute [w] align
|
|
61
|
-
def align=(value)
|
|
62
|
-
@align = Utils.align(value)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
protected
|
|
66
|
-
|
|
67
|
-
def _init
|
|
68
|
-
@align = :left
|
|
69
|
-
super
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def _assign(opt)
|
|
73
|
-
self.align = opt[:align] if opt.key?(:align)
|
|
74
|
-
super
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def _store(opt)
|
|
78
|
-
opt[:align] = @align if @align != :left
|
|
79
|
-
super
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
module Position
|
|
84
|
-
# Horizontal element position.
|
|
85
|
-
#
|
|
86
|
-
# @return [nil, :right, :centered]
|
|
87
|
-
attr_reader :position
|
|
88
|
-
|
|
89
|
-
# @attribute [w] position
|
|
90
|
-
def position=(value)
|
|
91
|
-
@position = Utils.position(value)
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
protected
|
|
95
|
-
|
|
96
|
-
def _assign(opt)
|
|
97
|
-
self.position = opt[:position] if opt.key?(:position)
|
|
98
|
-
super
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def _store(opt)
|
|
102
|
-
opt[:position] = @position if @position
|
|
103
|
-
super
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
module Vertical
|
|
108
|
-
# Vertical element alignment.
|
|
109
|
-
#
|
|
110
|
-
# @return [:top, :bottom, :middle]
|
|
111
|
-
attr_reader :vertical
|
|
112
|
-
|
|
113
|
-
# @attribute [w] vertical
|
|
114
|
-
def vertical=(value)
|
|
115
|
-
@vertical = Utils.vertical(value)
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
protected
|
|
119
|
-
|
|
120
|
-
def _init
|
|
121
|
-
@vertical = :top
|
|
122
|
-
super
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
def _assign(opt)
|
|
126
|
-
self.vertical = opt[:vertical] if opt.key?(:vertical)
|
|
127
|
-
super
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
def _store(opt)
|
|
131
|
-
opt[:vertical] = @vertical if @vertical != :top
|
|
132
|
-
super
|
|
133
|
-
end
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
module Width
|
|
137
|
-
# Element width.
|
|
138
|
-
#
|
|
139
|
-
# @return [Integer] dedicated element width
|
|
140
|
-
# @return [Range] width range: {#min_width}..{#max_width}
|
|
141
|
-
# @return [nil] when unassigned
|
|
142
|
-
attr_reader :width
|
|
143
|
-
|
|
144
|
-
# @attribute [w] width
|
|
145
|
-
def width=(value)
|
|
146
|
-
@width = as_wh(value)
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
# Minimum element width.
|
|
150
|
-
#
|
|
151
|
-
# @attribute [r] min_width
|
|
152
|
-
# @return [Integer, nil]
|
|
153
|
-
def min_width = width.is_a?(Range) ? @width.begin : @width
|
|
154
|
-
|
|
155
|
-
# @attribute [w] min_width
|
|
156
|
-
def min_width=(value)
|
|
157
|
-
@width = wh_from(value, max_width)
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
# Maximum element width.
|
|
161
|
-
#
|
|
162
|
-
# @attribute [r] max_width
|
|
163
|
-
# @return [Integer, nil]
|
|
164
|
-
def max_width = width.is_a?(Range) ? @width.end : @width
|
|
165
|
-
|
|
166
|
-
# @attribute [w] max_width
|
|
167
|
-
def max_width=(value)
|
|
168
|
-
@width = wh_from(min_width, value)
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
protected
|
|
172
|
-
|
|
173
|
-
def _assign(opt)
|
|
174
|
-
@width = as_wh(opt[:width]) if opt.key?(:width)
|
|
175
|
-
self.min_width = opt[:min_width] if opt.key?(:min_width)
|
|
176
|
-
self.max_width = opt[:max_width] if opt.key?(:max_width)
|
|
177
|
-
super
|
|
178
|
-
end
|
|
179
|
-
|
|
180
|
-
def _store(opt)
|
|
181
|
-
opt[:width] = @width if @width
|
|
182
|
-
super
|
|
183
|
-
end
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
module Height
|
|
187
|
-
# Element height.
|
|
188
|
-
#
|
|
189
|
-
# @return [Integer] dedicated element height
|
|
190
|
-
# @return [Range] height range: {#min_height}..{#max_height}
|
|
191
|
-
# @return [nil] when unassigned
|
|
192
|
-
attr_reader :height
|
|
193
|
-
|
|
194
|
-
# @attribute [w] height
|
|
195
|
-
def height=(value)
|
|
196
|
-
@height = as_wh(value)
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
# Minimum element height.
|
|
200
|
-
#
|
|
201
|
-
# @attribute [r] min_height
|
|
202
|
-
# @return [Integer, nil]
|
|
203
|
-
def min_height = @height.is_a?(Range) ? @height.begin : @height
|
|
204
|
-
|
|
205
|
-
# @attribute [w] min_height
|
|
206
|
-
def min_height=(value)
|
|
207
|
-
@height = wh_from(value.to_i, max_height)
|
|
208
|
-
end
|
|
209
|
-
|
|
210
|
-
# Maximum element height.
|
|
211
|
-
#
|
|
212
|
-
# @attribute [r] max_height
|
|
213
|
-
# @return [Integer, nil]
|
|
214
|
-
def max_height = @height.is_a?(Range) ? @height.begin : @height
|
|
215
|
-
|
|
216
|
-
# @attribute [w] max_height
|
|
217
|
-
def max_height=(value)
|
|
218
|
-
@height = wh_from(min_height, value.to_i)
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
protected
|
|
222
|
-
|
|
223
|
-
def _assign(opt)
|
|
224
|
-
@height = as_wh(opt[:height]) if opt.key?(:height)
|
|
225
|
-
self.min_height = opt[:min_height] if opt.key?(:min_height)
|
|
226
|
-
self.max_height = opt[:max_height] if opt.key?(:max_height)
|
|
227
|
-
super
|
|
228
|
-
end
|
|
229
|
-
|
|
230
|
-
def _store(opt)
|
|
231
|
-
opt[:height] = @height if @height
|
|
232
|
-
super
|
|
233
|
-
end
|
|
234
|
-
end
|
|
235
|
-
|
|
236
|
-
module Padding
|
|
237
|
-
# Text padding within the element.
|
|
238
|
-
#
|
|
239
|
-
# @return [Array<Integer>] top, right, bottom, left
|
|
240
|
-
attr_reader :padding
|
|
241
|
-
|
|
242
|
-
# @attribute [w] padding
|
|
243
|
-
def padding=(*value)
|
|
244
|
-
@padding = Utils.padding(*value).freeze
|
|
245
|
-
end
|
|
246
|
-
|
|
247
|
-
# Text top padding.
|
|
248
|
-
#
|
|
249
|
-
# @attribute [r] padding_top
|
|
250
|
-
# @return [Integer]
|
|
251
|
-
def padding_top = @padding[0]
|
|
252
|
-
|
|
253
|
-
# @attribute [w] padding_top
|
|
254
|
-
def padding_top=(value)
|
|
255
|
-
@padding[0] = as_uint(value)
|
|
256
|
-
end
|
|
257
|
-
|
|
258
|
-
# Text right padding.
|
|
259
|
-
#
|
|
260
|
-
# @attribute [r] padding_right
|
|
261
|
-
# @return [Integer]
|
|
262
|
-
def padding_right = @padding[1]
|
|
263
|
-
|
|
264
|
-
# @attribute [w] padding_right
|
|
265
|
-
def padding_right=(value)
|
|
266
|
-
@padding[1] = as_uint(value)
|
|
267
|
-
end
|
|
268
|
-
|
|
269
|
-
# Text bottom padding.
|
|
270
|
-
#
|
|
271
|
-
# @attribute [r] padding_bottom
|
|
272
|
-
# @return [Integer]
|
|
273
|
-
def padding_bottom = @padding[2]
|
|
274
|
-
|
|
275
|
-
# @attribute [w] padding_bottom
|
|
276
|
-
def padding_bottom=(value)
|
|
277
|
-
@padding[2] = as_uint(value)
|
|
278
|
-
end
|
|
279
|
-
|
|
280
|
-
# Text left padding.
|
|
281
|
-
#
|
|
282
|
-
# @attribute [r] padding_left
|
|
283
|
-
# @return [Integer]
|
|
284
|
-
def padding_left = @padding[3]
|
|
285
|
-
|
|
286
|
-
# @attribute [w] padding_left
|
|
287
|
-
def padding_left=(value)
|
|
288
|
-
@padding[3] = as_uint(value)
|
|
289
|
-
end
|
|
290
|
-
|
|
291
|
-
protected
|
|
292
|
-
|
|
293
|
-
def _init
|
|
294
|
-
@padding = Array.new(4, 0)
|
|
295
|
-
super
|
|
296
|
-
end
|
|
297
|
-
|
|
298
|
-
def _assign(opt)
|
|
299
|
-
self.padding = opt[:padding] if opt.key?(:padding)
|
|
300
|
-
@padding[0] = as_uint(opt[:padding_top]) if opt.key?(:padding_top)
|
|
301
|
-
@padding[1] = as_uint(opt[:padding_right]) if opt.key?(:padding_right)
|
|
302
|
-
@padding[2] = as_uint(opt[:padding_bottom]) if opt.key?(:padding_bottom)
|
|
303
|
-
@padding[3] = as_uint(opt[:padding_left]) if opt.key?(:padding_left)
|
|
304
|
-
super
|
|
305
|
-
end
|
|
306
|
-
|
|
307
|
-
def _store(opt)
|
|
308
|
-
val = @padding.dup
|
|
309
|
-
if val[1] == val[3]
|
|
310
|
-
val.pop
|
|
311
|
-
if val[0] == val[2]
|
|
312
|
-
if val[0] == val[1]
|
|
313
|
-
opt[:padding] = val[0] if val[0] != 0
|
|
314
|
-
return super
|
|
315
|
-
end
|
|
316
|
-
val.pop
|
|
317
|
-
end
|
|
318
|
-
end
|
|
319
|
-
opt[:padding] = val
|
|
320
|
-
super
|
|
321
|
-
end
|
|
322
|
-
|
|
323
|
-
def initialize_copy(*_)
|
|
324
|
-
super
|
|
325
|
-
@padding = @padding.dup
|
|
326
|
-
end
|
|
327
|
-
end
|
|
328
|
-
|
|
329
|
-
module Margin
|
|
330
|
-
# Element margin.
|
|
331
|
-
#
|
|
332
|
-
# @return [Array<Integer>] [top, right, bottom, left]
|
|
333
|
-
attr_reader :margin
|
|
334
|
-
|
|
335
|
-
# @attribute [w] margin
|
|
336
|
-
def margin=(*value)
|
|
337
|
-
@margin = Utils.margin(*value).freeze
|
|
338
|
-
end
|
|
339
|
-
|
|
340
|
-
# Element top margin.
|
|
341
|
-
#
|
|
342
|
-
# @attribute [r] margin_top
|
|
343
|
-
# @return [Integer]
|
|
344
|
-
def margin_top = @margin[0]
|
|
345
|
-
|
|
346
|
-
# @attribute [w] margin_top
|
|
347
|
-
def margin_top=(value)
|
|
348
|
-
@margin[0] = as_uint(value)
|
|
349
|
-
end
|
|
350
|
-
|
|
351
|
-
# Element right margin.
|
|
352
|
-
#
|
|
353
|
-
# @attribute [r] margin_right
|
|
354
|
-
# @return [Integer]
|
|
355
|
-
def margin_right = @margin[1]
|
|
356
|
-
|
|
357
|
-
# @attribute [w] margin_right
|
|
358
|
-
def margin_right=(value)
|
|
359
|
-
@margin[1] = as_uint(value)
|
|
360
|
-
end
|
|
361
|
-
|
|
362
|
-
# Element bottom margin.
|
|
363
|
-
#
|
|
364
|
-
# @attribute [r] margin_bottom
|
|
365
|
-
# @return [Integer]
|
|
366
|
-
def margin_bottom = @margin[2]
|
|
367
|
-
|
|
368
|
-
# @attribute [w] margin_bottom
|
|
369
|
-
def margin_bottom=(value)
|
|
370
|
-
@margin[2] = as_uint(value)
|
|
371
|
-
end
|
|
372
|
-
|
|
373
|
-
# Element left margin.
|
|
374
|
-
#
|
|
375
|
-
# @attribute [r] margin_left
|
|
376
|
-
# @return [Integer]
|
|
377
|
-
def margin_left = @margin[3]
|
|
378
|
-
|
|
379
|
-
# @attribute [w] margin_left
|
|
380
|
-
def margin_left=(value)
|
|
381
|
-
@margin[3] = as_uint(value)
|
|
382
|
-
end
|
|
383
|
-
|
|
384
|
-
protected
|
|
385
|
-
|
|
386
|
-
def _init
|
|
387
|
-
@margin = Array.new(4, 0)
|
|
388
|
-
super
|
|
389
|
-
end
|
|
390
|
-
|
|
391
|
-
def _assign(opt)
|
|
392
|
-
self.margin = opt[:margin] if opt.key?(:margin)
|
|
393
|
-
@margin[0] = as_uint(opt[:margin_top]) if opt.key?(:margin_top)
|
|
394
|
-
@margin[1] = as_uint(opt[:margin_right]) if opt.key?(:margin_right)
|
|
395
|
-
@margin[2] = as_uint(opt[:margin_bottom]) if opt.key?(:margin_bottom)
|
|
396
|
-
@margin[3] = as_uint(opt[:margin_left]) if opt.key?(:margin_left)
|
|
397
|
-
super
|
|
398
|
-
end
|
|
399
|
-
|
|
400
|
-
def _store(opt)
|
|
401
|
-
val = @margin.dup
|
|
402
|
-
if val[1] == val[3]
|
|
403
|
-
val.pop
|
|
404
|
-
if val[0] == val[2]
|
|
405
|
-
if val[0] == val[1]
|
|
406
|
-
opt[:margin] = val[0] if val[0] != 0
|
|
407
|
-
return super
|
|
408
|
-
end
|
|
409
|
-
val.pop
|
|
410
|
-
end
|
|
411
|
-
end
|
|
412
|
-
opt[:margin] = val
|
|
413
|
-
super
|
|
414
|
-
end
|
|
415
|
-
|
|
416
|
-
def initialize_copy(*_)
|
|
417
|
-
super
|
|
418
|
-
@margin = @margin.dup
|
|
419
|
-
end
|
|
420
|
-
end
|
|
421
|
-
|
|
422
|
-
module Style
|
|
423
|
-
# Text style.
|
|
424
|
-
#
|
|
425
|
-
# @return [Array, nil]
|
|
426
|
-
attr_reader :style
|
|
427
|
-
|
|
428
|
-
# @attribute [w] style
|
|
429
|
-
def style=(value)
|
|
430
|
-
@style = Utils.style(value)
|
|
431
|
-
end
|
|
432
|
-
|
|
433
|
-
def style_bbcode
|
|
434
|
-
"[#{@style.join(' ')}]" if @style
|
|
435
|
-
end
|
|
436
|
-
|
|
437
|
-
protected
|
|
438
|
-
|
|
439
|
-
def _assign(opt)
|
|
440
|
-
@style = Utils.style(opt[:style]) if opt.key?(:style)
|
|
441
|
-
super
|
|
442
|
-
end
|
|
443
|
-
|
|
444
|
-
def _store(opt)
|
|
445
|
-
opt[:style] = @style if @style
|
|
446
|
-
super
|
|
447
|
-
end
|
|
448
|
-
end
|
|
449
|
-
|
|
450
|
-
module BorderStyle
|
|
451
|
-
# Border style.
|
|
452
|
-
#
|
|
453
|
-
# @return [Array, nil]
|
|
454
|
-
attr_reader :border_style
|
|
455
|
-
|
|
456
|
-
# @attribute [w] border_style
|
|
457
|
-
def border_style=(value)
|
|
458
|
-
@border_style = Utils.style(value)
|
|
459
|
-
end
|
|
460
|
-
|
|
461
|
-
def border_style_bbcode
|
|
462
|
-
"[#{@border_style.join(' ')}]" if @border_style
|
|
463
|
-
end
|
|
464
|
-
|
|
465
|
-
protected
|
|
466
|
-
|
|
467
|
-
def _assign(opt)
|
|
468
|
-
@border_style = Utils.style(opt[:border_style]) if opt.key?(
|
|
469
|
-
:border_style
|
|
470
|
-
)
|
|
471
|
-
super
|
|
472
|
-
end
|
|
473
|
-
|
|
474
|
-
def _store(opt)
|
|
475
|
-
opt[:border_style] = @border_style if @border_style
|
|
476
|
-
super
|
|
477
|
-
end
|
|
478
|
-
end
|
|
479
|
-
|
|
480
|
-
module Border
|
|
481
|
-
# Border type.
|
|
482
|
-
#
|
|
483
|
-
# @return [
|
|
484
|
-
# :default,
|
|
485
|
-
# :rounded,
|
|
486
|
-
# :heavy,
|
|
487
|
-
# :double,
|
|
488
|
-
# :vintage,
|
|
489
|
-
# :defaulth,
|
|
490
|
-
# :defaultv,
|
|
491
|
-
# :heavyh,
|
|
492
|
-
# :heavyv,
|
|
493
|
-
# :doubleh,
|
|
494
|
-
# :doublev
|
|
495
|
-
# ]
|
|
496
|
-
# @return [nil] when element has no border
|
|
497
|
-
attr_reader :border
|
|
498
|
-
|
|
499
|
-
# @attribute [w] border
|
|
500
|
-
def border=(value)
|
|
501
|
-
if value
|
|
502
|
-
@border_chars = Theme.current.border(value)
|
|
503
|
-
@border = value
|
|
504
|
-
else
|
|
505
|
-
@border_chars = @border = nil
|
|
506
|
-
end
|
|
507
|
-
end
|
|
508
|
-
|
|
509
|
-
# @private
|
|
510
|
-
# @return [String, nil]
|
|
511
|
-
attr_reader :border_chars
|
|
512
|
-
|
|
513
|
-
protected
|
|
514
|
-
|
|
515
|
-
def _assign(opt)
|
|
516
|
-
self.border = opt[:border] if opt.key?(:border)
|
|
517
|
-
super
|
|
518
|
-
end
|
|
519
|
-
|
|
520
|
-
def _store(opt)
|
|
521
|
-
opt[:border] = @border if @border_chars
|
|
522
|
-
super
|
|
523
|
-
end
|
|
524
|
-
end
|
|
525
|
-
end
|
|
526
|
-
|
|
527
|
-
module WithAttributes
|
|
528
|
-
attr_reader :attributes
|
|
529
|
-
|
|
530
|
-
def attributes=(value)
|
|
531
|
-
@attributes =
|
|
532
|
-
if value.is_a?(self.class::Attributes)
|
|
533
|
-
value.dup
|
|
534
|
-
elsif value.respond_to?(:to_hash)
|
|
535
|
-
self.class::Attributes.new(**value.to_hash)
|
|
536
|
-
else
|
|
537
|
-
self.class::Attributes.new(**value.to_h)
|
|
538
|
-
end
|
|
539
|
-
end
|
|
540
|
-
|
|
541
|
-
private
|
|
542
|
-
|
|
543
|
-
def initialize(**attributes)
|
|
544
|
-
@attributes = self.class::Attributes.new(**attributes)
|
|
545
|
-
end
|
|
546
|
-
|
|
547
|
-
def initialize_copy(*_)
|
|
548
|
-
super
|
|
549
|
-
@attributes = @attributes.dup
|
|
550
|
-
end
|
|
551
|
-
end
|
|
552
|
-
|
|
553
|
-
private_constant :WithAttributes
|
|
554
|
-
|
|
555
|
-
module TextWithAttributes
|
|
556
|
-
include WithAttributes
|
|
557
|
-
|
|
558
|
-
attr_reader :text
|
|
559
|
-
|
|
560
|
-
def empty? = @text.empty?
|
|
561
|
-
alias _to_s to_s
|
|
562
|
-
private :_to_s
|
|
563
|
-
def to_str = @text.join("\n")
|
|
564
|
-
alias to_s to_str
|
|
565
|
-
|
|
566
|
-
def inspect
|
|
567
|
-
if (att = @attributes.to_hash).empty?
|
|
568
|
-
"#{_to_s.chop} @text=#{to_s.inspect}>"
|
|
569
|
-
else
|
|
570
|
-
"#{_to_s.chop} @attributes=#{att} @text=#{to_s.inspect}>"
|
|
571
|
-
end
|
|
572
|
-
end
|
|
573
|
-
|
|
574
|
-
private
|
|
575
|
-
|
|
576
|
-
def initialize(*text, **attributes)
|
|
577
|
-
@text = text
|
|
578
|
-
@attributes =
|
|
579
|
-
if text.last.is_a?(self.class::Attributes)
|
|
580
|
-
text.pop.merge(**@attributes)
|
|
581
|
-
else
|
|
582
|
-
self.class::Attributes.new(**attributes)
|
|
583
|
-
end
|
|
584
|
-
end
|
|
585
|
-
|
|
586
|
-
def initialize_copy(*_)
|
|
587
|
-
super
|
|
588
|
-
@text = @text.map(&:dup)
|
|
589
|
-
end
|
|
590
|
-
end
|
|
591
|
-
|
|
592
|
-
private_constant :TextWithAttributes
|
|
593
|
-
end
|
data/lib/natty-ui/choice.rb
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative 'element'
|
|
4
|
-
|
|
5
|
-
module NattyUI
|
|
6
|
-
class Choice < Element
|
|
7
|
-
def select
|
|
8
|
-
yield(self) if block_given?
|
|
9
|
-
pin_line = NattyUI.lines_written
|
|
10
|
-
draw
|
|
11
|
-
last = @current
|
|
12
|
-
Terminal.on_key_event do |event|
|
|
13
|
-
case event.name
|
|
14
|
-
when 'Esc', 'Ctrl+c'
|
|
15
|
-
return if @abortable
|
|
16
|
-
when 'Enter', 'Space'
|
|
17
|
-
return @ret[@current]
|
|
18
|
-
when 'Home'
|
|
19
|
-
@current = 0
|
|
20
|
-
when 'End'
|
|
21
|
-
@current = @texts.size - 1
|
|
22
|
-
when 'Up', 'Back', 'Shift+Tab', 'i', 'w'
|
|
23
|
-
@current = @texts.size - 1 if (@current -= 1) < 0
|
|
24
|
-
when 'Down', 'Tab', 'k', 's'
|
|
25
|
-
@current = 0 if (@current += 1) == @texts.size
|
|
26
|
-
else
|
|
27
|
-
next true unless event.simple?
|
|
28
|
-
c = event.key.ord
|
|
29
|
-
@current = (c - 48).clamp(0, @texts.size - 1) if c.between?(48, 57)
|
|
30
|
-
end
|
|
31
|
-
next true if last == @current
|
|
32
|
-
pin_line = NattyUI.back_to_line(pin_line, erase: false)
|
|
33
|
-
draw
|
|
34
|
-
last = @current
|
|
35
|
-
end
|
|
36
|
-
ensure
|
|
37
|
-
NattyUI.back_to_line(@start_line)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
private
|
|
41
|
-
|
|
42
|
-
def initialize(parent, args, kwargs, abortable, selected)
|
|
43
|
-
super(parent)
|
|
44
|
-
@start_line = NattyUI.lines_written
|
|
45
|
-
@texts = args + kwargs.values
|
|
46
|
-
@ret = Array.new(args.size, &:itself) + kwargs.keys
|
|
47
|
-
@abortable = abortable
|
|
48
|
-
@current = @ret.index(selected) || 0
|
|
49
|
-
theme = Theme.current
|
|
50
|
-
@mark = [theme.mark(:choice), theme.choice_style]
|
|
51
|
-
@mark_current = [theme.mark(:current_choice), theme.choice_current_style]
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def draw
|
|
55
|
-
@texts.each_with_index do |str, idx|
|
|
56
|
-
mark, style = idx == @current ? @mark_current : @mark
|
|
57
|
-
@parent.puts(
|
|
58
|
-
"#{style}#{str}",
|
|
59
|
-
first_line_prefix: mark,
|
|
60
|
-
first_line_prefix_width: mark.width
|
|
61
|
-
)
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
private_constant :Choice
|
|
67
|
-
end
|
data/lib/natty-ui/dumb_choice.rb
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative 'element'
|
|
4
|
-
|
|
5
|
-
module NattyUI
|
|
6
|
-
class DumbChoice < Element
|
|
7
|
-
def select
|
|
8
|
-
yield(self) if block_given?
|
|
9
|
-
draw
|
|
10
|
-
Terminal.on_key_event do |event|
|
|
11
|
-
return if @abortable && %w[Esc Ctrl+c].include?(event.name)
|
|
12
|
-
next true unless event.simple?
|
|
13
|
-
code = event.raw.upcase
|
|
14
|
-
if @ret.size <= 9
|
|
15
|
-
next true unless ('1'..'9').include?(code)
|
|
16
|
-
code = @ret[code.ord - 49] and return code
|
|
17
|
-
elsif ('A'..'Z').include?(code)
|
|
18
|
-
code = @ret[code.ord - 65] and return code
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
private
|
|
24
|
-
|
|
25
|
-
def draw
|
|
26
|
-
glyph = @ret.size <= 9 ? 1 : 'A'
|
|
27
|
-
@texts.each do |str|
|
|
28
|
-
@parent.puts(
|
|
29
|
-
str,
|
|
30
|
-
first_line_prefix: "[\\#{glyph}] ",
|
|
31
|
-
first_line_prefix_width: 4
|
|
32
|
-
)
|
|
33
|
-
glyph = glyph.succ
|
|
34
|
-
end
|
|
35
|
-
@texts = nil
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def initialize(parent, args, kwargs, abortable)
|
|
39
|
-
super(parent)
|
|
40
|
-
@ret = Array.new(args.size, &:itself) + kwargs.keys
|
|
41
|
-
@texts = args + kwargs.values
|
|
42
|
-
@abortable = abortable
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
private_constant :DumbChoice
|
|
47
|
-
end
|