terminal-layout 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 283b397c0181527c2ded64f2865ebc71ede5aac9
4
+ data.tar.gz: adb2c56149641dcd9322173e512be240e1b6eca2
5
+ SHA512:
6
+ metadata.gz: 5b2b2c1eb88264c1084e879cdef933a5115edf521ca0288a3b3d594ce360a1155429847af7fe52a791d222c94885f89d75d3890e96477164f26f84880dbbd4f5
7
+ data.tar.gz: f28f73e2b8c7aa43bfab59f807103194096e621dee8e05a593ad1b99a1db9c4d2cfe24331f6f4897c960b522ea3b08e7524ccac4b77d574900a640493ff75314
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,14 @@
1
+ language: ruby
2
+ cache: bundler
3
+ rvm:
4
+ - 2.2.3
5
+
6
+ gemfile:
7
+ - Gemfile
8
+
9
+ bundler_args: -j2
10
+
11
+ before_script:
12
+
13
+ script:
14
+ - bundle exec rspec spec
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'pry-byebug'
7
+ end
8
+
9
+ group :test do
10
+ gem 'rspec'
11
+ gem 'term-ansicolor'
12
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,60 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ terminal-layout (0.1.0)
5
+ highline
6
+ ruby-terminfo (~> 0.1.1)
7
+ ruby-termios (~> 0.9.6)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ byebug (5.0.0)
13
+ columnize (= 0.9.0)
14
+ coderay (1.1.0)
15
+ columnize (0.9.0)
16
+ diff-lcs (1.2.5)
17
+ highline (1.7.2)
18
+ method_source (0.8.2)
19
+ pry (0.10.1)
20
+ coderay (~> 1.1.0)
21
+ method_source (~> 0.8.1)
22
+ slop (~> 3.4)
23
+ pry-byebug (3.2.0)
24
+ byebug (~> 5.0)
25
+ pry (~> 0.10)
26
+ rake (10.4.2)
27
+ rspec (3.3.0)
28
+ rspec-core (~> 3.3.0)
29
+ rspec-expectations (~> 3.3.0)
30
+ rspec-mocks (~> 3.3.0)
31
+ rspec-core (3.3.1)
32
+ rspec-support (~> 3.3.0)
33
+ rspec-expectations (3.3.0)
34
+ diff-lcs (>= 1.2.0, < 2.0)
35
+ rspec-support (~> 3.3.0)
36
+ rspec-mocks (3.3.1)
37
+ diff-lcs (>= 1.2.0, < 2.0)
38
+ rspec-support (~> 3.3.0)
39
+ rspec-support (3.3.0)
40
+ ruby-terminfo (0.1.1)
41
+ ruby-termios (0.9.6)
42
+ slop (3.6.0)
43
+ term-ansicolor (1.3.0)
44
+ tins (~> 1.0)
45
+ tins (1.3.5)
46
+
47
+ PLATFORMS
48
+ ruby
49
+
50
+ DEPENDENCIES
51
+ bundler (~> 1.7)
52
+ pry
53
+ pry-byebug
54
+ rake (~> 10.0)
55
+ rspec
56
+ term-ansicolor
57
+ terminal-layout!
58
+
59
+ BUNDLED WITH
60
+ 1.10.4
data/README.md ADDED
@@ -0,0 +1,7 @@
1
+ ![TravisCI Build Status](https://travis-ci.org/zdennis/terminal-layout.svg)
2
+
3
+
4
+
5
+ # terminal-layout
6
+
7
+ TerminalLayout is a layout and rendering engine for terminals. It is essentially a bare bones browser rendering engine as it generates a basic DOM and supports style nodes similar to CSS.
data/block-flow.rb ADDED
@@ -0,0 +1,361 @@
1
+ require 'pry'
2
+
3
+ $z = File.open("/tmp/z.log", "w+")
4
+ $z.sync = true
5
+
6
+ $stdout.sync = true
7
+
8
+ class Layout
9
+ def initialize(box, offset_x:0, offset_y:0)
10
+ @box = box
11
+ @x = offset_x
12
+ @y = offset_y
13
+ end
14
+
15
+ def layout_float(fbox)
16
+ # only allow the float to be as wide as its parent
17
+ if fbox.width > @box.width
18
+ fbox.width = @box.width
19
+ end
20
+
21
+ if fbox.float == :left
22
+ # if we cannot fit on this line, go to the next
23
+ if @x + fbox.width > @box.width
24
+ @x = 0
25
+ @y += 1
26
+ end
27
+
28
+ fbox.x = @x
29
+ fbox.y = @y
30
+
31
+ Layout.new(fbox, offset_x:@x, offset_y:@y).layout
32
+
33
+ @x += fbox.width
34
+ elsif fbox.float == :right
35
+ # loop in case there are left floats on the left as we move down rows
36
+ loop do
37
+ starting_x = starting_x_for_current_y
38
+ # if we cannot fit on this line, go to the next
39
+ if starting_x + fbox.width > @box.width
40
+ @x = 0
41
+ @y += 1
42
+ else
43
+ break
44
+ end
45
+ end
46
+
47
+ @x = ending_x_for_current_y - fbox.width
48
+ fbox.x = @x
49
+ fbox.y = @y
50
+
51
+ Layout.new(fbox, offset_x:@x, offset_y:@y).layout
52
+
53
+ # reset X back to what it should be
54
+ @x = starting_x_for_current_y
55
+ end
56
+ end
57
+
58
+ def starting_x_for_current_y
59
+ x = 0
60
+ @box.children.select { |cbox| cbox.display == :float && cbox.float == :left }.each do |fbox|
61
+ next unless fbox.y && fbox.y <= @y && (fbox.y + fbox.height) >= @y
62
+ x = [fbox.x + fbox.width, x].max
63
+ end
64
+ x
65
+ end
66
+
67
+ def ending_x_for_current_y
68
+ x = @box.width
69
+ @box.children.select { |cbox| cbox.display == :float && cbox.float == :right }.each do |fbox|
70
+ next unless fbox.y && fbox.y <= @y && (fbox.y + fbox.height) >= @y
71
+ x = [fbox.x, x].min
72
+ end
73
+ x
74
+ end
75
+
76
+ def layout
77
+ @tree = []
78
+
79
+ @box.children.each_with_index do |cbox, i|
80
+ previous_box = i > 0 ? @box.children[i - 1] : nil
81
+ if cbox.display == :float
82
+ layout_float cbox
83
+
84
+ @tree.push cbox
85
+ elsif cbox.display == :block
86
+ if previous_box && previous_box.display == :inline
87
+ @y += 1
88
+ end
89
+ @x = starting_x_for_current_y
90
+
91
+ cbox.width = ending_x_for_current_y - @x
92
+ new_box = Box.new("", style: cbox.style.merge(width: cbox.width))
93
+ new_box.children = [Box.new(cbox.content, children:[], style: {display: :inline})].concat cbox.children
94
+ new_box.children = Layout.new(new_box, offset_x:@x, offset_y:@y).layout
95
+ new_box.x = @x
96
+ new_box.y = @y
97
+
98
+ new_box.height = (new_box.children.map(&:y).max - new_box.y) + new_box.children.map(&:height).max
99
+
100
+ @y += new_box.height
101
+ @x = 0
102
+
103
+ @tree.push new_box
104
+ elsif cbox.display == :inline
105
+ if @x == 0
106
+ @x = starting_x_for_current_y
107
+ end
108
+ available_width = ending_x_for_current_y - @x
109
+
110
+ content_i = 0
111
+ content = ""
112
+
113
+ loop do
114
+ chars_needed = available_width
115
+ partial_content = cbox.content[content_i..(content_i + chars_needed)]
116
+ chars_needed = partial_content.length
117
+ @tree << Box.new(partial_content, children:[], style: {display: :inline, x:@x, y: @y, width:chars_needed, height:1})
118
+
119
+ content_i += chars_needed
120
+
121
+ if @x + chars_needed > available_width
122
+ @y += 1
123
+ @x = starting_x_for_current_y
124
+ else
125
+ @x += chars_needed
126
+ end
127
+
128
+ break if content_i >= cbox.content.length
129
+ end
130
+ end
131
+ end
132
+
133
+ @box.height = @box.height || (@box.children.map(&:y).max) - (@box.y || 0)
134
+
135
+ @tree
136
+ end
137
+ end
138
+
139
+ class Box
140
+ attr_accessor :children, :style, :content
141
+
142
+ def initialize(content, children:[], style:nil)
143
+ @style = style || { display: :block }
144
+ @content = content
145
+ @children = children
146
+ end
147
+
148
+ %w(width height display x y float).each do |method|
149
+ define_method(method){ style[method.to_sym] }
150
+ define_method("#{method}="){ |value| style[method.to_sym] = value }
151
+ end
152
+
153
+ def width
154
+ style[:width] || content.length
155
+ end
156
+
157
+ def height
158
+ if style[:height]
159
+ style[:height]
160
+ elsif style[:width]
161
+ (@content.to_s.length / style[:width].to_f).ceil
162
+ else # auto
163
+ 0
164
+ end
165
+ end
166
+
167
+ def inspect
168
+ to_s
169
+ end
170
+
171
+ def to_str
172
+ to_s
173
+ end
174
+
175
+ def to_s
176
+ "<Box position=(#{x},#{y}) dimensions=#{width}x#{height} display=#{display.inspect} content=#{content}/>"
177
+ end
178
+ end
179
+
180
+
181
+ require 'terminfo'
182
+ class TerminalRenderer
183
+ attr_reader :term_info
184
+
185
+ def initialize
186
+ @term_info = TermInfo.new ENV["TERM"], $stdout
187
+ # clear_screen
188
+ @x, @y = 0, 0
189
+ end
190
+
191
+ def log(str)
192
+ $z.puts str
193
+ end
194
+
195
+ def render(tree)
196
+ tree.each_with_index do |cbox, i|
197
+ previous_box = i > 0 ? tree[i-1] : nil
198
+ if cbox.display == :block
199
+ render_block cbox
200
+ elsif cbox.display == :inline
201
+ @x = cbox.x
202
+ log "move to column #{@x}"
203
+ move_to_column @x
204
+
205
+ render_inline cbox
206
+ elsif cbox.display == :float
207
+ needed_lines = cbox.y - @y
208
+ log "float puts #{needed_lines} times"
209
+ needed_lines.times{ $stdout.puts }
210
+ @y = cbox.y
211
+
212
+ render_float cbox
213
+ end
214
+ end
215
+ end
216
+
217
+ def render_float(fbox)
218
+ @x = fbox.x
219
+ log "move to column #{fbox.x}"
220
+ move_to_column fbox.x
221
+
222
+ render_inline Box.new(fbox.content, style:{
223
+ display: :inline,
224
+ width: fbox.width,
225
+ height: fbox.height,
226
+ x:fbox.x,
227
+ y:fbox.y
228
+ })
229
+
230
+ render(fbox.children)
231
+ end
232
+
233
+ def render_block(cbox)
234
+ @x = cbox.x
235
+ log "move to column #{@x}"
236
+ move_to_column @x
237
+
238
+ needed_lines = cbox.y - @y
239
+ log "puts #{needed_lines} times (#{cbox.y} - #{@y})"
240
+ if needed_lines >= 0
241
+ needed_lines.times { $stdout.puts }
242
+ else
243
+ move_up_n_rows needed_lines.abs
244
+ end
245
+ @y = cbox.y
246
+
247
+ if cbox.children.any?
248
+ render(cbox.children)
249
+ end
250
+
251
+ @x = cbox.x
252
+
253
+ render_inline(Box.new(cbox.content, style:{display: :inline, width: cbox.width, x:cbox.x, y:cbox.y}))
254
+ end
255
+
256
+ def render_inline(cbox)
257
+ count = 0
258
+ rel_count = 0
259
+
260
+ # make sure we start in the right place
261
+ log "inline @y: #{@y}"
262
+ needed_lines = cbox.y - @y
263
+ log "inline puts #{needed_lines} times"
264
+ if needed_lines >= 0
265
+ needed_lines.times{ $stdout.puts }
266
+ else
267
+ move_up_n_rows needed_lines.abs
268
+ end
269
+ @y = cbox.y
270
+
271
+ loop do
272
+ if count >= cbox.content.length
273
+ log "breaking because count >= cbox.content.length (#{count} >= #{cbox.content.length}) x:#{@x} y:#{@y} count:#{count}"
274
+ break
275
+ end
276
+
277
+ if rel_count >= cbox.width
278
+ $stdout.puts
279
+ rel_count = 0
280
+ @y += 1
281
+ @x = cbox.x
282
+ log "puts because inline content is at width (count % cbox.width) == 0 (#{count} % #{cbox.width}) == 0 x:#{@x} y:#{@y} count:#{count}"
283
+ end
284
+
285
+ log "print #{cbox.content[count].inspect} x:#{@x} y:#{@y} count:#{count}"
286
+ move_to_column @x
287
+
288
+ $stdout.print cbox.content[count]
289
+ count += 1
290
+ rel_count += 1
291
+ @x += 1
292
+ end
293
+
294
+ log "Done inline: x:#{@x} y:#{@y}"
295
+ end
296
+
297
+ def clear_to_beginning_of_line ; term_info.control "el1" ; end
298
+ def clear_screen ; term_info.control "clear" ; end
299
+ def clear_screen_down ; term_info.control "ed" ; end
300
+ def move_to_beginning_of_row ; move_to_column 0 ; end
301
+ def move_left ; move_left_n_characters 1 ; end
302
+ def move_left_n_characters(n) ; term_info.control "cub1" ; end
303
+ def move_right_n_characters(n) ; term_info.control "cuf1" ; end
304
+ def move_to_column_and_row(column, row) ; term_info.control "cup", column, row ; end
305
+ def move_to_column(n) ; term_info.control "hpa", n ; end
306
+ def move_up_n_rows(n) ; n.times { term_info.control "cuu1" } ; end
307
+ def move_down_n_rows(n) ; n.times { term_info.control "cud1" } ; end
308
+ end
309
+
310
+
311
+
312
+ parent = Box.new(nil,
313
+ children: [
314
+ Box.new("<"*5, style:{display: :float, float: :left, width:5}),
315
+ Box.new("r"*40, style:{display: :float, float: :right, width:20}),
316
+ Box.new("A"*40, style: {display: :block}),
317
+ Box.new(">"*15, style:{display: :float, float: :left, width:5}),
318
+ Box.new("_"*6, style: {display: :inline}),
319
+ Box.new("-"*6, style: {display: :inline}),
320
+ Box.new("~"*9, style: {display: :inline}),
321
+ Box.new("B", style: {display: :block},
322
+ children: [
323
+ Box.new("b"*10, style: {display: :block}, children:[
324
+ Box.new("*"*3, style: {display: :inline}),
325
+ Box.new("!"*3, style: {display: :inline}),
326
+ Box.new("$"*3, style: {display: :inline}),
327
+ Box.new("["*3, style: {display: :block})
328
+ ]),
329
+ ]),
330
+ Box.new("C"*60, style: {display: :block}),
331
+ Box.new("D"*20, style: {display: :block}),
332
+ Box.new("E"*10, style: {display: :block})
333
+ ],
334
+ style: {
335
+ display: :block,
336
+ width: 60,
337
+ height: nil
338
+ }
339
+ )
340
+
341
+
342
+ layout_tree = Layout.new(parent).layout
343
+
344
+
345
+ def print_tree(tree, indent=0)
346
+ tree.each do |box|
347
+ print " " * indent
348
+ puts box
349
+ print_tree box.children, indent + 2
350
+ end
351
+ end
352
+
353
+
354
+ print_tree layout_tree
355
+ TerminalRenderer.new.render(layout_tree)
356
+
357
+
358
+ # print_tree layout_tree
359
+ # require 'pry'
360
+ # binding.pry
361
+ puts