typr 1.7.0 → 1.9.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 +27 -1
- data/README.md +1 -1
- data/lib/browser.rb +82 -15
- data/lib/grid.rb +63 -23
- data/lib/line.rb +43 -9
- data/lib/space.rb +113 -8
- data/lib/stack.rb +62 -14
- data/lib/terminal.rb +394 -66
- data/lib/text.rb +50 -17
- data/lib/typr.rb +4 -2
- data/typr.gemspec +2 -2
- metadata +2 -2
data/lib/space.rb
CHANGED
|
@@ -16,7 +16,21 @@ class Space
|
|
|
16
16
|
include Typr
|
|
17
17
|
|
|
18
18
|
%w[left top right bottom].each{ |name| method = <<STR
|
|
19
|
-
|
|
19
|
+
##
|
|
20
|
+
# Raw +%s+ value as passed to the constructor, before resolution
|
|
21
|
+
# (nil, Integer, Float, or Proc). Useful for introspection.
|
|
22
|
+
#
|
|
23
|
+
# space.%s_setting #=> 0
|
|
24
|
+
#
|
|
25
|
+
def %s_setting; @%s; end
|
|
26
|
+
##
|
|
27
|
+
# Resolved +%s+ edge: Integer (absolute position), Float (fraction of
|
|
28
|
+
# the terminal), Proc (evaluated each layout pass), or a negative
|
|
29
|
+
# Integer (offset from the opposite edge, -1 = last). Defaults to the
|
|
30
|
+
# widget's natural extent when unset.
|
|
31
|
+
#
|
|
32
|
+
# space.%s #=> 4
|
|
33
|
+
#
|
|
20
34
|
def %s
|
|
21
35
|
max=Typr.#{ name[/left|right/] ? 'width' : 'height' }
|
|
22
36
|
if !@%s;[max, #{ case name
|
|
@@ -30,9 +44,18 @@ else 'top+[(respond_to?(:rows) ? rows : 0), 1].max-1+(respond_to?(:headspace) ?
|
|
|
30
44
|
else @%s end
|
|
31
45
|
end
|
|
32
46
|
STR
|
|
33
|
-
eval( method % ([name]*
|
|
47
|
+
eval( method % ([name]*15) ) }
|
|
48
|
+
|
|
49
|
+
##
|
|
50
|
+
# Deep-convert String keys to Symbols so string-keyed config (e.g. YAML)
|
|
51
|
+
# is honored. Non-Hash values pass through untouched.
|
|
52
|
+
#
|
|
53
|
+
# space.symbolize "colors" => { "border" => :red }
|
|
54
|
+
# #=> {colors: {border: :red}}
|
|
55
|
+
#
|
|
56
|
+
# @param obj [Object] hash or value to convert
|
|
57
|
+
# @return [Object] converted copy, or the value itself when not a Hash
|
|
34
58
|
|
|
35
|
-
# Deep-convert String keys to Symbols so string-keyed config (e.g. YAML) is honored.
|
|
36
59
|
def symbolize obj
|
|
37
60
|
case obj
|
|
38
61
|
when Hash
|
|
@@ -41,12 +64,44 @@ eval( method % ([name]*11) ) }
|
|
|
41
64
|
else obj end
|
|
42
65
|
end
|
|
43
66
|
|
|
67
|
+
##
|
|
68
|
+
# Viewport edges, readable and assignable. Each accepts an Integer
|
|
69
|
+
# (absolute position), a Float (fraction of the terminal), a Proc
|
|
70
|
+
# (evaluated each layout pass), or a negative Integer (offset from the
|
|
71
|
+
# opposite edge, -1 = last row/column); unset edges fall back to the
|
|
72
|
+
# widget's natural extent. +left_setting+ and friends return the raw
|
|
73
|
+
# constructor value before resolution.
|
|
74
|
+
#
|
|
75
|
+
# space.left = 0
|
|
76
|
+
# space.right = 0.5
|
|
77
|
+
# space.bottom = -1
|
|
78
|
+
# space.right_setting #=> 0.5
|
|
44
79
|
attr_writer :left, :top, :right, :bottom
|
|
80
|
+
##
|
|
81
|
+
# +margin+ is the left-edge padding string, +colors+ the per-part color
|
|
82
|
+
# hash, +interval+ the redraw period in seconds for {#start}, and
|
|
83
|
+
# +borders+ the raw edge characters (prefer {#border=}).
|
|
84
|
+
#
|
|
85
|
+
# space.margin = " "
|
|
86
|
+
# space.interval = 2
|
|
45
87
|
attr_accessor :margin, :colors, :interval, :borders
|
|
46
88
|
|
|
89
|
+
##
|
|
47
90
|
# Viewport width in cells (right - left + 1).
|
|
91
|
+
#
|
|
92
|
+
# space.width #=> 80
|
|
93
|
+
#
|
|
94
|
+
# @return [Integer]
|
|
95
|
+
|
|
48
96
|
def width; right - left + 1 end
|
|
97
|
+
|
|
98
|
+
##
|
|
49
99
|
# Viewport height in cells (bottom - top + 1).
|
|
100
|
+
#
|
|
101
|
+
# space.height #=> 24
|
|
102
|
+
#
|
|
103
|
+
# @return [Integer]
|
|
104
|
+
|
|
50
105
|
def height; bottom - top + 1 end
|
|
51
106
|
|
|
52
107
|
##
|
|
@@ -60,7 +115,7 @@ eval( method % ([name]*11) ) }
|
|
|
60
115
|
def data_at x, y; nil end
|
|
61
116
|
|
|
62
117
|
##
|
|
63
|
-
# The trigger key for a binding label like "[h]elp" or "[/]:
|
|
118
|
+
# The trigger key for a binding label like "[h]elp" or "[/]:narrow", or nil
|
|
64
119
|
# for named keys ("[up]", "[esc]") which stay keyboard-only.
|
|
65
120
|
#
|
|
66
121
|
# line.extract_key "[R]ecurse" # => "R"
|
|
@@ -70,18 +125,48 @@ eval( method % ([name]*11) ) }
|
|
|
70
125
|
key if key and key.size == 1
|
|
71
126
|
end
|
|
72
127
|
|
|
128
|
+
##
|
|
73
129
|
# Redraw every +interval+ seconds from a background thread.
|
|
130
|
+
#
|
|
131
|
+
# space.interval = 1
|
|
132
|
+
# space.start #=> #<Thread>
|
|
133
|
+
# space.stop # terminates it
|
|
134
|
+
#
|
|
135
|
+
# @return [Thread]
|
|
136
|
+
|
|
74
137
|
def start; @updater = Thread.new{ loop{show; sleep @interval }} end
|
|
75
|
-
|
|
138
|
+
|
|
139
|
+
##
|
|
140
|
+
# Stop the background refresh thread started by {#start}.
|
|
141
|
+
#
|
|
142
|
+
# space.stop #=> #<Thread> (terminated)
|
|
143
|
+
#
|
|
144
|
+
# @return [Thread]
|
|
145
|
+
|
|
76
146
|
def stop; @updater.terminate end
|
|
77
147
|
|
|
148
|
+
##
|
|
78
149
|
# Draw a border char at screen (x, y); skips nil and off-screen positions.
|
|
150
|
+
#
|
|
151
|
+
# space.draw_border 0, 0, "┌" #=> nil
|
|
152
|
+
#
|
|
153
|
+
# @param x [Integer] column (0-based)
|
|
154
|
+
# @param y [Integer] row (0-based)
|
|
155
|
+
# @param char [String, nil] character to draw
|
|
156
|
+
# @return [nil]
|
|
157
|
+
|
|
79
158
|
def draw_border x,y,char
|
|
80
159
|
draw move_code(x, y) + char unless not char or
|
|
81
160
|
x < 0 or x > Typr.width or y < 0 or y > Typr.height
|
|
82
161
|
end
|
|
83
162
|
|
|
163
|
+
##
|
|
84
164
|
# Draw the widget's border box (no-op when no borders are set).
|
|
165
|
+
#
|
|
166
|
+
# space.show #=> nil
|
|
167
|
+
#
|
|
168
|
+
# @return [nil]
|
|
169
|
+
|
|
85
170
|
def show
|
|
86
171
|
return if @borders.empty?
|
|
87
172
|
color @colors[:border]
|
|
@@ -97,8 +182,19 @@ eval( method % ([name]*11) ) }
|
|
|
97
182
|
draw_border(right + 1, bottom + 1, @borders[:bottom_right])
|
|
98
183
|
end
|
|
99
184
|
|
|
100
|
-
|
|
101
|
-
#
|
|
185
|
+
##
|
|
186
|
+
# Set border style: +:light+/:heavy+/:double+/:round+, a single char
|
|
187
|
+
# repeated across the box, an 8-char string (top, bottom, left, right,
|
|
188
|
+
# top-left, top-right, bottom-left, bottom-right), or nil for none.
|
|
189
|
+
#
|
|
190
|
+
# space.border = :round
|
|
191
|
+
# space.border = "─" # one char for every edge
|
|
192
|
+
# space.border = "──││┌┐└┘" # explicit edges, same as :light
|
|
193
|
+
# space.border = nil # remove the border
|
|
194
|
+
#
|
|
195
|
+
# @param border [Symbol, String, nil]
|
|
196
|
+
# @return [void]
|
|
197
|
+
|
|
102
198
|
def border=(border)
|
|
103
199
|
chars = case border
|
|
104
200
|
when Symbol
|
|
@@ -111,8 +207,17 @@ eval( method % ([name]*11) ) }
|
|
|
111
207
|
bottom_right ].map.with_index{ |part,id| [part.to_sym, chars[id]] }.to_h if chars
|
|
112
208
|
end
|
|
113
209
|
|
|
210
|
+
##
|
|
114
211
|
# Build a widget from boundary (left/top/right/bottom), border, margin,
|
|
115
|
-
# colors, interval, and keymap.
|
|
212
|
+
# colors, interval, and keymap. Every keyword becomes an instance
|
|
213
|
+
# variable (+border:+ is applied through {#border=}).
|
|
214
|
+
#
|
|
215
|
+
# box = Typr::Space.new(left: 0, top: 2, right: 0.5, bottom: -4,
|
|
216
|
+
# border: :round, colors: { border: :grey50 }, interval: 2)
|
|
217
|
+
#
|
|
218
|
+
# @param args [Hash] boundary and visual options (see the class example)
|
|
219
|
+
# @return [Space]
|
|
220
|
+
|
|
116
221
|
def initialize args={}
|
|
117
222
|
@max, @keymap, @colors, @margin = 0, {}, {}, ' '
|
|
118
223
|
@left, @top, @interval, @borders = 0, 0, 1, {}
|
data/lib/stack.rb
CHANGED
|
@@ -17,10 +17,25 @@ module Typr
|
|
|
17
17
|
# KEY_HOME / KEY_END (jump to first or last pageable row)
|
|
18
18
|
|
|
19
19
|
class Stack < Space
|
|
20
|
-
##
|
|
21
|
-
|
|
20
|
+
##
|
|
21
|
+
# Widget configuration and state: +left+/+top+/+right+/+bottom+ set
|
|
22
|
+
# the viewport (see {Space}), +alternate+ toggles striped rows
|
|
23
|
+
# (+:grey10+ against the default bg), +start+ is the scroll offset,
|
|
24
|
+
# +keymap+ maps key sequences to methods, +selected+ holds picked ids
|
|
25
|
+
# per type, and +header+ is the top-bar label.
|
|
26
|
+
#
|
|
27
|
+
# stack.start = 3
|
|
28
|
+
# stack.header = "Title"
|
|
22
29
|
|
|
23
30
|
attr_accessor :start, :keymap, :selected, :header
|
|
31
|
+
##
|
|
32
|
+
# +separator+ is the gap between columns, +hints+ the hint characters,
|
|
33
|
+
# +hints_start+ the offset of the current hint chunk ({#cycle}), and
|
|
34
|
+
# +modifier+ is +:alt+ after an Alt-digit hint press, +nil+ otherwise.
|
|
35
|
+
#
|
|
36
|
+
# stack.hints = "1234567890"
|
|
37
|
+
# stack.modifier #=> :alt (after picking with Alt+digit)
|
|
38
|
+
|
|
24
39
|
attr_accessor :separator, :hints, :hints_start, :modifier
|
|
25
40
|
|
|
26
41
|
##
|
|
@@ -174,39 +189,57 @@ module Typr
|
|
|
174
189
|
return response
|
|
175
190
|
end
|
|
176
191
|
|
|
177
|
-
##
|
|
192
|
+
##
|
|
193
|
+
# Scroll to the top of the dataset.
|
|
178
194
|
#
|
|
179
|
-
# stack.to_top
|
|
195
|
+
# stack.to_top # @start => 0
|
|
196
|
+
#
|
|
197
|
+
# @return [nil]
|
|
180
198
|
|
|
181
199
|
def to_top; @start = 0; return end
|
|
182
200
|
|
|
183
|
-
##
|
|
201
|
+
##
|
|
202
|
+
# Scroll to the bottom pageable position (last row minus viewport height).
|
|
203
|
+
#
|
|
204
|
+
# stack.to_bottom # @start => rows - height
|
|
184
205
|
#
|
|
185
|
-
#
|
|
206
|
+
# @return [nil]
|
|
186
207
|
|
|
187
208
|
def to_bottom; @start = rows - height; return end
|
|
188
209
|
|
|
189
|
-
##
|
|
210
|
+
##
|
|
211
|
+
# Step down by one row.
|
|
212
|
+
#
|
|
213
|
+
# stack.down # @start += 1
|
|
190
214
|
#
|
|
191
|
-
#
|
|
215
|
+
# @return [nil]
|
|
192
216
|
|
|
193
217
|
def down; @start += 1; return end
|
|
194
218
|
|
|
195
|
-
##
|
|
219
|
+
##
|
|
220
|
+
# Step up by one row.
|
|
196
221
|
#
|
|
197
|
-
# stack.up
|
|
222
|
+
# stack.up # @start -= 1
|
|
223
|
+
#
|
|
224
|
+
# @return [nil]
|
|
198
225
|
|
|
199
226
|
def up; @start -= 1; return end
|
|
200
227
|
|
|
201
|
-
##
|
|
228
|
+
##
|
|
229
|
+
# Jump down by one viewport of rows.
|
|
230
|
+
#
|
|
231
|
+
# stack.page_down # @start += height
|
|
202
232
|
#
|
|
203
|
-
#
|
|
233
|
+
# @return [nil]
|
|
204
234
|
|
|
205
235
|
def page_down; @start += height; return end
|
|
206
236
|
|
|
207
|
-
##
|
|
237
|
+
##
|
|
238
|
+
# Jump up by one viewport of rows.
|
|
239
|
+
#
|
|
240
|
+
# stack.page_up # @start -= height
|
|
208
241
|
#
|
|
209
|
-
#
|
|
242
|
+
# @return [nil]
|
|
210
243
|
|
|
211
244
|
def page_up; @start -= height; return end
|
|
212
245
|
|
|
@@ -230,7 +263,14 @@ module Typr
|
|
|
230
263
|
# stack.pick :column, 3 # pick a column in row 3
|
|
231
264
|
# stack.pick "rows" # multi-select rows
|
|
232
265
|
#
|
|
266
|
+
# Pressing Alt with a hint digit (ESC + digit) picks that hint row and
|
|
267
|
+
# sets +modifier+ to +:alt+ for the caller.
|
|
268
|
+
#
|
|
233
269
|
# Mouse: left-click a row to pick it; wheel up/down scrolls the page.
|
|
270
|
+
#
|
|
271
|
+
# @param type [Symbol, String] picker type (table above)
|
|
272
|
+
# @param row [Integer] starting row for column/field hints
|
|
273
|
+
# @return [Integer, Array, nil] picked id(s), selection on confirm, or nil on abort
|
|
234
274
|
|
|
235
275
|
def pick type = :row, row=0 #, key=nil
|
|
236
276
|
type = type.to_s
|
|
@@ -298,6 +338,14 @@ module Typr
|
|
|
298
338
|
return
|
|
299
339
|
end
|
|
300
340
|
|
|
341
|
+
##
|
|
342
|
+
# Walk the hint characters backwards by one chunk (mirror of {#cycle}),
|
|
343
|
+
# wrapping to the last full chunk before the start of the list.
|
|
344
|
+
#
|
|
345
|
+
# stack.cycle_back # hints_start -= hints.size (wraps at 0)
|
|
346
|
+
#
|
|
347
|
+
# @return [nil]
|
|
348
|
+
|
|
301
349
|
def cycle_back
|
|
302
350
|
max = [height-1, rows-1+headspace].min
|
|
303
351
|
@hints_start -= @hints.size
|