terminal-layout 0.4.2 → 0.4.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 80aa4a0e91137ff86176dcbadddd0b409704d3e1
4
- data.tar.gz: 5b959060b022e65741abdca373a33713055c34c8
3
+ metadata.gz: 3ed9ef7985d3a6245c22719a1d3ff99bfe281ed3
4
+ data.tar.gz: c18265ddc6660e6112dfed6248ea845d6419d02d
5
5
  SHA512:
6
- metadata.gz: f0cf393e5f454b12b9d3a4e205d00ceafcdc8c1dea90717a12747b67900e213668ff19d614d7d29b8a190d096693cd560ace32261b83b4921d045d81d9e9bfd0
7
- data.tar.gz: f3ffaf2df0f703a28055eeff39c92d82653ffb01bfeafca2b292331ad2bc97f41ff04fee59ba2f7817780e6657c96a8f5e6b3721cb87f931ce9f0462cb4719fb
6
+ metadata.gz: 63784d51ef8e26f6eb877564c975a6fd6ce9ca6deba51f8cc78275a9c35c3d6ff7a5e37bae75035c8c14421951a9f7d0c00fc969d0721620c12da6db6b027f6e
7
+ data.tar.gz: 8d85eecd9132e6596faa48d48c82e6e92992fb835c2411e96ca784f6daab09d66f5de9efd6aa597aa0335db786c0802e339c9fe55eb03c4eb16076fd6e5fce13
@@ -1 +1 @@
1
- 2.2.3
1
+ 2.3.1
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- terminal-layout (0.4.2)
4
+ terminal-layout (0.4.3)
5
5
  ansi_string (~> 0.1)
6
6
  highline (~> 1.7, >= 1.7.8)
7
7
  ruby-terminfo (~> 0.1.1)
@@ -12,43 +12,42 @@ GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
14
  ansi_string (0.1.0)
15
- byebug (5.0.0)
16
- columnize (= 0.9.0)
17
- coderay (1.1.0)
18
- columnize (0.9.0)
15
+ byebug (9.0.5)
16
+ coderay (1.1.1)
19
17
  diff-lcs (1.2.5)
20
18
  highline (1.7.8)
21
19
  method_source (0.8.2)
22
- pry (0.10.1)
20
+ pry (0.10.3)
23
21
  coderay (~> 1.1.0)
24
22
  method_source (~> 0.8.1)
25
23
  slop (~> 3.4)
26
- pry-byebug (3.2.0)
27
- byebug (~> 5.0)
24
+ pry-byebug (3.4.0)
25
+ byebug (~> 9.0)
28
26
  pry (~> 0.10)
29
- rake (10.4.2)
30
- rspec (3.3.0)
31
- rspec-core (~> 3.3.0)
32
- rspec-expectations (~> 3.3.0)
33
- rspec-mocks (~> 3.3.0)
34
- rspec-core (3.3.1)
35
- rspec-support (~> 3.3.0)
36
- rspec-expectations (3.3.0)
27
+ rake (10.5.0)
28
+ rspec (3.5.0)
29
+ rspec-core (~> 3.5.0)
30
+ rspec-expectations (~> 3.5.0)
31
+ rspec-mocks (~> 3.5.0)
32
+ rspec-core (3.5.1)
33
+ rspec-support (~> 3.5.0)
34
+ rspec-expectations (3.5.0)
37
35
  diff-lcs (>= 1.2.0, < 2.0)
38
- rspec-support (~> 3.3.0)
39
- rspec-mocks (3.3.1)
36
+ rspec-support (~> 3.5.0)
37
+ rspec-mocks (3.5.0)
40
38
  diff-lcs (>= 1.2.0, < 2.0)
41
- rspec-support (~> 3.3.0)
42
- rspec-support (3.3.0)
39
+ rspec-support (~> 3.5.0)
40
+ rspec-support (3.5.0)
43
41
  ruby-terminfo (0.1.1)
44
42
  ruby-termios (0.9.6)
45
43
  slop (3.6.0)
46
- term-ansicolor (1.3.0)
44
+ term-ansicolor (1.3.2)
47
45
  tins (~> 1.0)
48
- tins (1.3.5)
49
- treefell (0.3.0)
46
+ tins (1.10.2)
47
+ treefell (0.3.1)
50
48
  ansi_string (~> 0.1)
51
- term-ansicolor (~> 1.3)
49
+ term-ansicolor (~> 1.3.2)
50
+ tins (= 1.10.2)
52
51
 
53
52
  PLATFORMS
54
53
  ruby
@@ -62,4 +61,4 @@ DEPENDENCIES
62
61
  terminal-layout!
63
62
 
64
63
  BUNDLED WITH
65
- 1.11.2
64
+ 1.12.5
@@ -1,32 +1,13 @@
1
1
  require 'ostruct'
2
2
  require 'ansi_string'
3
3
  require 'treefell'
4
+ require 'terminal_layout/event_emitter'
5
+ require 'terminal_layout/renderer'
4
6
 
5
7
  module TerminalLayout
6
8
  Dimension = Struct.new(:width, :height)
7
9
  Position = Struct.new(:x, :y)
8
10
 
9
- module EventEmitter
10
- def _callbacks
11
- @_callbacks ||= Hash.new { |h, k| h[k] = [] }
12
- end
13
-
14
- def on(type, *args, &blk)
15
- _callbacks[type] << blk
16
- self
17
- end
18
-
19
- def unsubscribe
20
- _callbacks.clear
21
- end
22
-
23
- def emit(type, *args)
24
- _callbacks[type].each do |blk|
25
- blk.call(*args)
26
- end
27
- end
28
- end
29
-
30
11
  class RenderObject
31
12
  include EventEmitter
32
13
 
@@ -137,7 +118,6 @@ module TerminalLayout
137
118
  end
138
119
 
139
120
  def layout
140
- Treefell['render'].puts "layout #{self.inspect}"
141
121
  self.children = []
142
122
  @current_x = 0
143
123
  @current_y = 0
@@ -153,7 +133,6 @@ module TerminalLayout
153
133
  end
154
134
 
155
135
  children2crawl.each do |cbox|
156
- Treefell['render'].puts "layout crawling children #{cbox.inspect}"
157
136
  if cbox.display == :float
158
137
  next if cbox.width.to_i == 0
159
138
 
@@ -205,7 +184,6 @@ module TerminalLayout
205
184
  loop do
206
185
  partial_content = cbox.content[content_i...(content_i + available_width)]
207
186
  chars_needed = partial_content.length
208
- Treefell['render'].puts "laying out inline #{cbox.name} @current_x=#{@current_x} @current_y=#{@current_y} x=#{x} y=#{y}"
209
187
  self.children << render_object_for(
210
188
  cbox,
211
189
  content:partial_content,
@@ -250,7 +228,6 @@ module TerminalLayout
250
228
  child.box.computed[:x] += x
251
229
  child.box.computed[:y] += y
252
230
  end
253
- Treefell['render'].puts "laid out box=#{box.name} render-object=#{self.children}"
254
231
 
255
232
  self.children
256
233
  end
@@ -507,170 +484,10 @@ module TerminalLayout
507
484
  # spans multiple lines. We do not want to update the x/y position(s)
508
485
  # in this instance. We want to keep the original starting x/y.
509
486
  if style[:y] && style[:y] > 0
510
- Treefell['render'].puts "update_computed received a y > 0. Removing Y from update."
511
487
  style = style.dup.delete_if { |k,_| [:x, :y].include?(k) }
512
488
  end
513
489
  @computed.merge!(style)
514
490
  end
515
491
  end
516
492
 
517
- require 'terminfo'
518
- require 'termios'
519
- require 'highline/system_extensions'
520
- class TerminalRenderer
521
- include HighLine::SystemExtensions
522
- include EventEmitter
523
-
524
- attr_reader :term_info
525
-
526
- def initialize(output: $stdout)
527
- @output = output
528
- @term_info = TermInfo.new ENV["TERM"], @output
529
- @previously_printed_lines = []
530
- @x, @y = 0, 0
531
- end
532
-
533
- def render_cursor(input_box)
534
- Treefell['render'].puts "render cursor at box=#{input_box.inspect} computed=#{input_box.computed.inspect}"
535
-
536
- move_up_n_rows @y
537
- move_to_beginning_of_row
538
-
539
- position = input_box.position
540
-
541
- cursor_position = input_box.cursor_position
542
- cursor_x = cursor_position.x
543
- cursor_y = cursor_position.y
544
-
545
- relative_position_on_row = position
546
- initial_offset_x = input_box.computed[:x] + (input_box.computed[:y] * terminal_width)
547
- cursor_x = 0
548
- cursor_y = 0
549
-
550
- absolute_position_on_row = relative_position_on_row + initial_offset_x
551
- loop do
552
- if absolute_position_on_row >= terminal_width
553
- # reset offset
554
- initial_offset_x = 0
555
-
556
- absolute_position_on_row -= terminal_width
557
-
558
- # move down a line
559
- cursor_y += 1
560
- else
561
- # we fit on the current line
562
- cursor_x = absolute_position_on_row
563
- break
564
- end
565
- end
566
-
567
- if @y < cursor_y
568
- # moving backwards
569
- move_up_n_rows(@y - cursor_y)
570
- elsif @y > cursor_y
571
- # moving forwards
572
- move_down_n_rows(cursor_y - @y)
573
- end
574
-
575
- move_down_n_rows cursor_y
576
- move_to_beginning_of_row
577
- move_right_n_characters cursor_x
578
-
579
- @x = cursor_x
580
- @y = cursor_y
581
-
582
- Treefell['render'].puts "rendering cursor at x=#{@x} y=#{@y}"
583
-
584
- if input_box.style[:cursor] == 'none'
585
- @output.print @term_info.control_string "civis"
586
- else
587
- @output.print @term_info.control_string "cnorm"
588
- end
589
- end
590
-
591
- def render(object, reset: false)
592
- dumb_render(object, reset: reset)
593
- end
594
-
595
- def find_top_of_tree(object)
596
- loop do
597
- break unless object.parent
598
- object = object.parent
599
- end
600
- object
601
- end
602
-
603
- def dumb_render(object, reset: false)
604
- if reset
605
- @y = 0
606
- @previously_printed_lines.clear
607
- end
608
- @output.print @term_info.control_string "civis"
609
- move_up_n_rows @y
610
- move_to_beginning_of_row
611
-
612
- object = find_top_of_tree(object)
613
-
614
- object_width = object.width
615
-
616
- rendered_content = object.render
617
- printable_content = rendered_content.sub(/\s*\Z/m, '')
618
-
619
- printable_lines = printable_content.split(/\n/).each_with_object([]) do |line, results|
620
- if line.empty?
621
- results << line
622
- else
623
- results.concat line.scan(/.{1,#{terminal_width}}/)
624
- end
625
- end
626
-
627
- printable_lines.zip(@previously_printed_lines) do |new_line, previous_line|
628
- if new_line != previous_line
629
- # be sure to reset the terminal at the outset of every line
630
- # because we don't know what state the previous line ended in
631
- line2print = "#{new_line}\e[0m"
632
- term_info.control "el"
633
- move_to_beginning_of_row
634
- term_info.control "el"
635
- Treefell['render'].puts "printing line=#{line2print.inspect}"
636
- @output.puts line2print
637
- else
638
- move_down_n_rows 1
639
- end
640
- end
641
- move_to_beginning_of_row
642
- clear_screen_down
643
-
644
- # calculate lines drawn so we know where we are
645
- lines_drawn = (printable_content.length / object_width.to_f).ceil
646
- @y = lines_drawn
647
-
648
- input_box = object.box.find_child_of_type(InputBox) do |box|
649
- box.focused?
650
- end
651
- render_cursor(input_box)
652
-
653
- @previously_printed_lines = printable_lines
654
- end
655
-
656
- def clear_to_beginning_of_line ; term_info.control "el1" ; end
657
- def clear_screen ; term_info.control "clear" ; end
658
- def clear_screen_down ; term_info.control "ed" ; end
659
- def move_to_beginning_of_row ; move_to_column 0 ; end
660
- def move_left ; move_left_n_characters 1 ; end
661
- def move_left_n_characters(n) ; n.times { term_info.control "cub1" } ; end
662
- def move_right_n_characters(n) ; n.times { term_info.control "cuf1" } ; end
663
- def move_to_column_and_row(column, row) ; term_info.control "cup", column, row ; end
664
- def move_to_column(n) ; term_info.control "hpa", n ; end
665
- def move_up_n_rows(n) ; n.times { term_info.control "cuu1" } ; end
666
- def move_down_n_rows(n) ; n.times { term_info.control "cud1" } ; end
667
-
668
- def terminal_width
669
- terminal_size[0]
670
- end
671
-
672
- def terminal_height
673
- terminal_size[1]
674
- end
675
- end
676
493
  end
@@ -0,0 +1,22 @@
1
+ module TerminalLayout
2
+ module EventEmitter
3
+ def _callbacks
4
+ @_callbacks ||= Hash.new { |h, k| h[k] = [] }
5
+ end
6
+
7
+ def on(type, *args, &blk)
8
+ _callbacks[type] << blk
9
+ self
10
+ end
11
+
12
+ def unsubscribe
13
+ _callbacks.clear
14
+ end
15
+
16
+ def emit(type, *args)
17
+ _callbacks[type].each do |blk|
18
+ blk.call(*args)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,178 @@
1
+ require 'terminfo'
2
+ require 'termios'
3
+ require 'highline/system_extensions'
4
+
5
+ module TerminalLayout
6
+ class Renderer
7
+ include HighLine::SystemExtensions
8
+ include EventEmitter
9
+
10
+ attr_reader :term_info
11
+
12
+ def initialize(output: $stdout)
13
+ @output = output
14
+ @term_info = TermInfo.new ENV["TERM"], @output
15
+ @previously_printed_lines = []
16
+ @x, @y = 0, 0
17
+ end
18
+
19
+ def render_cursor(input_box)
20
+ Treefell['render'].puts %|\nCURSOR RENDER: #{self.class}##{__callee__} caller=#{caller[0..5].join("\n")}}|
21
+ move_up_n_rows @y
22
+ move_to_beginning_of_row
23
+
24
+ position = input_box.position
25
+
26
+ cursor_position = input_box.cursor_position
27
+ cursor_x = cursor_position.x
28
+ cursor_y = cursor_position.y
29
+
30
+ relative_position_on_row = position
31
+ initial_offset_x = input_box.computed[:x] + (input_box.computed[:y] * terminal_width)
32
+ cursor_x = 0
33
+ cursor_y = 0
34
+
35
+ absolute_position_on_row = relative_position_on_row + initial_offset_x
36
+ loop do
37
+ if absolute_position_on_row >= terminal_width
38
+ # reset offset
39
+ initial_offset_x = 0
40
+
41
+ absolute_position_on_row -= terminal_width
42
+
43
+ # move down a line
44
+ cursor_y += 1
45
+ else
46
+ # we fit on the current line
47
+ cursor_x = absolute_position_on_row
48
+ break
49
+ end
50
+ end
51
+
52
+ if @y < cursor_y
53
+ # moving backwards
54
+ move_up_n_rows(@y - cursor_y)
55
+ elsif @y > cursor_y
56
+ # moving forwards
57
+ move_down_n_rows(cursor_y - @y)
58
+ end
59
+
60
+ move_down_n_rows cursor_y
61
+ move_to_beginning_of_row
62
+ move_right_n_characters cursor_x
63
+
64
+ @x = cursor_x
65
+ @y = cursor_y
66
+
67
+ if input_box.style[:cursor] == 'none'
68
+ @output.print @term_info.control_string "civis"
69
+ else
70
+ @output.print @term_info.control_string "cnorm"
71
+ end
72
+ end
73
+
74
+ def render(object, reset: false)
75
+ dumb_render(object, reset: reset)
76
+ end
77
+
78
+ def find_top_of_tree(object)
79
+ loop do
80
+ break unless object.parent
81
+ object = object.parent
82
+ end
83
+ object
84
+ end
85
+
86
+ def fullzip(a, b, &blk)
87
+ results = if a.length >= b.length
88
+ a.zip(b)
89
+ else
90
+ b.zip(a).map(&:reverse)
91
+ end
92
+ if block_given?
93
+ results.each { |*args| blk.call(*args) }
94
+ else
95
+ results
96
+ end
97
+ end
98
+
99
+ def dumb_render(object, reset: false)
100
+ Treefell['render'].puts %|\nDUMB RENDER: #{self.class}##{__callee__} reset=#{reset} caller=#{caller[0..5].join("\n")}}|
101
+ if reset
102
+ @y = 0
103
+ @previously_printed_lines.clear
104
+ else
105
+ move_up_n_rows @y
106
+ move_to_beginning_of_row
107
+ @y = 0
108
+ end
109
+ @output.print @term_info.control_string "civis"
110
+
111
+ object = find_top_of_tree(object)
112
+
113
+ object_width = object.width
114
+
115
+ rendered_content = object.render
116
+ printable_content = rendered_content.sub(/\s*\Z/m, '')
117
+ printable_lines = printable_content.split(/\n/).each_with_object([]) do |line, results|
118
+ if line.empty?
119
+ results << line
120
+ else
121
+ results.concat line.scan(/.{1,#{terminal_width}}/)
122
+ end
123
+ end
124
+
125
+ i = 0
126
+ fullzip(printable_lines, @previously_printed_lines) do |new_line, previous_line|
127
+ i += 1
128
+ if new_line && new_line != previous_line
129
+ # be sure to reset the terminal at the outset of every line
130
+ # because we don't know what state the previous line ended in
131
+ line2print = "#{new_line}\e[0m"
132
+ term_info.control "el"
133
+ move_to_beginning_of_row
134
+ term_info.control "el"
135
+ @output.puts line2print
136
+ move_to_beginning_of_row
137
+ elsif i <= printable_lines.length
138
+ move_down_n_rows 1
139
+ end
140
+ end
141
+
142
+ move_to_beginning_of_row
143
+ clear_screen_down
144
+
145
+ # calculate lines drawn so we know where we are
146
+ lines_drawn = (printable_content.length / object_width.to_f).ceil
147
+ @y = lines_drawn
148
+
149
+ input_box = object.box.find_child_of_type(InputBox) do |box|
150
+ box.focused?
151
+ end
152
+ render_cursor(input_box)
153
+
154
+ @previously_printed_lines = printable_lines
155
+ end
156
+
157
+ def clear_to_beginning_of_line ; term_info.control "el1" ; end
158
+ def clear_screen ; term_info.control "clear" ; end
159
+ def clear_screen_down ; term_info.control "ed" ; end
160
+ def move_to_beginning_of_row ; move_to_column 0 ; end
161
+ def move_left ; move_left_n_characters 1 ; end
162
+ def move_left_n_characters(n) ; n.times { term_info.control "cub1" } ; end
163
+ def move_right_n_characters(n) ; n.times { term_info.control "cuf1" } ; end
164
+ def move_to_column_and_row(column, row) ; term_info.control "cup", column, row ; end
165
+ def move_to_column(n) ; term_info.control "hpa", n ; end
166
+ def move_up_n_rows(n) ; n.times { term_info.control "cuu1" } ; end
167
+ def move_down_n_rows(n) ; n.times { term_info.control "cud1" } ; end
168
+
169
+ def terminal_width
170
+ terminal_size[0]
171
+ end
172
+
173
+ def terminal_height
174
+ terminal_size[1]
175
+ end
176
+ end
177
+
178
+ end
@@ -1,3 +1,3 @@
1
1
  module TerminalLayout
2
- VERSION = "0.4.2"
2
+ VERSION = "0.4.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: terminal-layout
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zach Dennis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-01 00:00:00.000000000 Z
11
+ date: 2016-07-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ansi_string
@@ -145,6 +145,8 @@ files:
145
145
  - block-flow.rb
146
146
  - lib/tasks/gem.rake
147
147
  - lib/terminal_layout.rb
148
+ - lib/terminal_layout/event_emitter.rb
149
+ - lib/terminal_layout/renderer.rb
148
150
  - lib/terminal_layout/version.rb
149
151
  - spec/spec_helper.rb
150
152
  - spec/terminal_layout_spec.rb
@@ -170,7 +172,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
170
172
  version: '0'
171
173
  requirements: []
172
174
  rubyforge_project:
173
- rubygems_version: 2.4.5.1
175
+ rubygems_version: 2.5.1
174
176
  signing_key:
175
177
  specification_version: 4
176
178
  summary: A terminal layout manager