terminal-layout 0.3.1 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 717c542a1d6c338e54086d1a3bb5b77dd95cb035
4
- data.tar.gz: 2009b46c650de33f6eb1c427acfa59896b27c608
3
+ metadata.gz: effa639a6efd09195fc644fe6d4b325191ca7905
4
+ data.tar.gz: 187b259dcc98d8584948c4856772d440c6895564
5
5
  SHA512:
6
- metadata.gz: 06115b77a9a0176f96793a2a61cd9a518429a96a3583942f13789dd819db2d33e818c2aeee708a0df429ed13bd483940bf5c3d155b6a2e9a7b94f7f64a0e28f9
7
- data.tar.gz: 0afcb428fcfdcdb0c2c3d739697e411f81a1e8faeb881a35698c6b338db2c3fcf0c9c54faea966b38857cbff3a6c6315d632130e02d1ef9761119d6d47def123
6
+ metadata.gz: e2538c3ca865a7d81c0bc562d1a6c6c71da80fc345785ad3f3c138bb1622c0917369b36081244b48e309a7dc1fd63d4399e876341fe0b7834150a5d59c92d982
7
+ data.tar.gz: 5e57352329d7cf5cecd6b09d98d6d6d65fb8931b32dc0fdc7db510a8428842ec07a6fd58a45b77aee3a803aeaa8ce775a39eda2635a3d9e19b17411752aac86f
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- terminal-layout (0.3.1)
4
+ terminal-layout (0.4.0)
5
5
  highline (~> 1.7, >= 1.7.8)
6
6
  ruby-terminfo (~> 0.1.1)
7
7
  ruby-termios (~> 0.9.6)
data/lib/ansi_string.rb CHANGED
@@ -42,19 +42,20 @@ class ANSIString
42
42
 
43
43
  range_begin = range.begin
44
44
  range_end = range.end
45
- if range.end != range.begin
46
- range_end = range.exclude_end? ? range.end - 1 : range.end
45
+
46
+ if range.exclude_end?
47
+ if range_begin == 0 && range_end == 0
48
+ return ""
49
+ else
50
+ range_end -= 1
51
+ end
47
52
  end
48
53
 
49
54
  range_begin = @without_ansi.length - range.begin.abs if range.begin < 0
50
55
  range_end = @without_ansi.length - range.end.abs if range.end < 0
51
56
 
52
- if range_begin == 0 && range_end == 0 && range.exclude_end?
53
- return ""
54
- else
55
- str = build_string_with_ansi_for(range_begin..range_end)
56
- ANSIString.new str if str
57
- end
57
+ str = build_string_with_ansi_for(range_begin..range_end)
58
+ ANSIString.new str if str
58
59
  end
59
60
 
60
61
  def []=(range, replacement_str)
@@ -1,3 +1,3 @@
1
1
  module TerminalLayout
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -1,5 +1,6 @@
1
1
  require 'ansi_string'
2
2
  require 'ostruct'
3
+ require 'treefell'
3
4
 
4
5
  module TerminalLayout
5
6
  Dimension = Struct.new(:width, :height)
@@ -80,7 +81,7 @@ module TerminalLayout
80
81
 
81
82
  define_method("#{method}=") do |value|
82
83
  style[method.to_sym] = value
83
- @box.computed[method] = value
84
+ @box.computed[method.to_sym] = value
84
85
  end
85
86
  end
86
87
 
@@ -109,7 +110,7 @@ module TerminalLayout
109
110
  end
110
111
 
111
112
  def to_s
112
- "<#{self.class.name} position=(#{x},#{y}) dimensions=#{width}x#{height} content=#{content}/>"
113
+ "<#{self.class.name} position=(#{x},#{y}) dimensions=#{width}x#{height} content=#{content} name=#{@box.name}/>"
113
114
  end
114
115
 
115
116
  def render
@@ -136,6 +137,7 @@ module TerminalLayout
136
137
  end
137
138
 
138
139
  def layout
140
+ Treefell['render'].puts "layout #{self.inspect}"
139
141
  self.children = []
140
142
  @current_x = 0
141
143
  @current_y = 0
@@ -151,6 +153,7 @@ module TerminalLayout
151
153
  end
152
154
 
153
155
  children2crawl.each do |cbox|
156
+ Treefell['render'].puts "layout crawling children #{cbox.inspect}"
154
157
  if cbox.display == :float
155
158
  next if cbox.width.to_i == 0
156
159
 
@@ -175,10 +178,12 @@ module TerminalLayout
175
178
  available_width = ending_x_for_current_y - @current_x
176
179
  end
177
180
 
178
- render_object = render_object_for(cbox, content:nil, style: {width: (cbox.width || available_width)})
181
+ render_object = render_object_for(cbox, content:nil, style: {
182
+ x: @current_x,
183
+ y: @current_y,
184
+ width: (cbox.width || available_width)
185
+ })
179
186
  render_object.layout
180
- render_object.x = @current_x
181
- render_object.y = @current_y
182
187
 
183
188
  if cbox.height
184
189
  render_object.height = cbox.height
@@ -200,7 +205,18 @@ module TerminalLayout
200
205
  loop do
201
206
  partial_content = cbox.content[content_i...(content_i + available_width)]
202
207
  chars_needed = partial_content.length
203
- self.children << render_object_for(cbox, content:partial_content, style: {display: :inline, x:@current_x, y: @current_y, width:chars_needed, height:1})
208
+ Treefell['render'].puts "laying out inline #{cbox.name} @current_x=#{@current_x} @current_y=#{@current_y} x=#{x} y=#{y}"
209
+ self.children << render_object_for(
210
+ cbox,
211
+ content:partial_content,
212
+ style: {
213
+ display: :inline,
214
+ x: @current_x,
215
+ y: @current_y,
216
+ width:chars_needed,
217
+ height:1
218
+ }
219
+ )
204
220
 
205
221
  content_i += chars_needed
206
222
 
@@ -230,6 +246,12 @@ module TerminalLayout
230
246
  end
231
247
  end
232
248
 
249
+ self.children.each do |child|
250
+ child.box.computed[:x] += x
251
+ child.box.computed[:y] += y
252
+ end
253
+ Treefell['render'].puts "laid out box=#{box.name} render-object=#{self.children}"
254
+
233
255
  self.children
234
256
  end
235
257
 
@@ -316,7 +338,7 @@ module TerminalLayout
316
338
  class Box
317
339
  include EventEmitter
318
340
 
319
- attr_accessor :style, :children, :content, :computed
341
+ attr_accessor :style, :children, :content, :computed, :name
320
342
 
321
343
  def initialize(style:{}, children:[], content:"")
322
344
  @style = style
@@ -350,6 +372,17 @@ module TerminalLayout
350
372
  emit :child_changed, old_children, new_children
351
373
  end
352
374
 
375
+ def find_child_of_type(type, &block)
376
+ children.each do |child|
377
+ matches = child.is_a?(type)
378
+ matches &= block.call(child) if matches && block
379
+ return child if matches
380
+ child_matches = child.find_child_of_type(type, &block)
381
+ return child_matches if child_matches
382
+ end
383
+ nil
384
+ end
385
+
353
386
  def position
354
387
  Position.new(x, y)
355
388
  end
@@ -375,7 +408,7 @@ module TerminalLayout
375
408
  end
376
409
 
377
410
  def to_s
378
- "<Box##{object_id} position=(#{x},#{y}) dimensions=#{width}x#{height} display=#{display.inspect} content=#{content}/>"
411
+ "<#{self.class}##{object_id} position=(#{x},#{y}) dimensions=#{width}x#{height} display=#{display.inspect} content=#{content} name=#{@name}/>"
379
412
  end
380
413
 
381
414
  def update_computed(style)
@@ -399,7 +432,7 @@ module TerminalLayout
399
432
  def subscribe_to_events_on_children
400
433
  @children.each do |child|
401
434
  child.on(:content_changed) do |*args|
402
- emit :child_changed
435
+ emit :content_changed
403
436
  end
404
437
  child.on(:child_changed) do |*args|
405
438
  emit :child_changed
@@ -407,11 +440,13 @@ module TerminalLayout
407
440
  child.on(:position_changed) do |*args|
408
441
  emit :position_changed
409
442
  end
443
+ child.on(:focused_changed) do |*args|
444
+ emit :focused_changed, *args
445
+ end
410
446
  end
411
447
  end
412
448
  end
413
449
 
414
-
415
450
  class InputBox < Box
416
451
  # cursor_position is the actual coordinates on the screen of where then
417
452
  # cursor is rendered
@@ -421,11 +456,26 @@ module TerminalLayout
421
456
  # displayed on a single line
422
457
  attr_accessor :position
423
458
 
459
+ def focus!
460
+ return if @focused
461
+ @focused = true
462
+ emit :focus_changed, !@focused, @focused
463
+ end
464
+
465
+ def remove_focus!
466
+ return unless @focused
467
+ @focused = false
468
+ emit :focus_changed, !@focused, @focused
469
+ end
470
+
471
+ def focused? ; !!@focused ; end
472
+
424
473
  def initialize(*args)
425
474
  super
426
475
  @computed = { x: 0, y: 0 }
427
476
  @cursor_position = OpenStruct.new(x: 0, y: 0)
428
477
  @position = 0
478
+ @focused = false
429
479
  end
430
480
 
431
481
  def cursor_off
@@ -457,6 +507,7 @@ module TerminalLayout
457
507
  # spans multiple lines. We do not want to update the x/y position(s)
458
508
  # in this instance. We want to keep the original starting x/y.
459
509
  if style[:y] && style[:y] > 0
510
+ Treefell['render'].puts "update_computed received a y > 0. Removing Y from update."
460
511
  style = style.dup.delete_if { |k,_| [:x, :y].include?(k) }
461
512
  end
462
513
  @computed.merge!(style)
@@ -480,6 +531,8 @@ module TerminalLayout
480
531
  end
481
532
 
482
533
  def render_cursor(input_box)
534
+ Treefell['render'].puts "render cursor at box=#{input_box.inspect} computed=#{input_box.computed.inspect}"
535
+
483
536
  move_up_n_rows @y
484
537
  move_to_beginning_of_row
485
538
 
@@ -526,6 +579,8 @@ module TerminalLayout
526
579
  @x = cursor_x
527
580
  @y = cursor_y
528
581
 
582
+ Treefell['render'].puts "rendering cursor at x=#{@x} y=#{@y}"
583
+
529
584
  if input_box.style[:cursor] == 'none'
530
585
  @output.print @term_info.control_string "civis"
531
586
  else
@@ -537,6 +592,14 @@ module TerminalLayout
537
592
  dumb_render(object, reset: reset)
538
593
  end
539
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
+
540
603
  def dumb_render(object, reset: false)
541
604
  if reset
542
605
  @y = 0
@@ -546,10 +609,7 @@ module TerminalLayout
546
609
  move_up_n_rows @y
547
610
  move_to_beginning_of_row
548
611
 
549
- loop do
550
- break unless object.parent
551
- object = object.parent
552
- end
612
+ object = find_top_of_tree(object)
553
613
 
554
614
  object_width = object.width
555
615
 
@@ -571,6 +631,7 @@ module TerminalLayout
571
631
  line2print = "#{new_line}\e[0m"
572
632
  term_info.control "el"
573
633
  move_to_beginning_of_row
634
+ term_info.control "el"
574
635
  Treefell['render'].puts "printing line=#{line2print.inspect}"
575
636
  @output.puts line2print
576
637
  else
@@ -584,18 +645,14 @@ module TerminalLayout
584
645
  lines_drawn = (printable_content.length / object_width.to_f).ceil
585
646
  @y = lines_drawn
586
647
 
587
- input_box = find_input_box(object.box)
648
+ input_box = object.box.find_child_of_type(InputBox) do |box|
649
+ box.focused?
650
+ end
588
651
  render_cursor(input_box)
589
652
 
590
653
  @previously_printed_lines = printable_lines
591
654
  end
592
655
 
593
- def find_input_box(dom_node)
594
- dom_node.children.detect do |child|
595
- child.is_a?(InputBox) || find_input_box(child)
596
- end
597
- end
598
-
599
656
  def clear_to_beginning_of_line ; term_info.control "el1" ; end
600
657
  def clear_screen ; term_info.control "clear" ; end
601
658
  def clear_screen_down ; term_info.control "ed" ; end
@@ -261,6 +261,11 @@ describe 'ANSIString' do
261
261
  expect(ansi_string[12..14]).to eq "ABC"
262
262
  end
263
263
 
264
+ it "returns dos thine" do
265
+ ansi_string = ANSIString.new("ABC")
266
+ expect(ansi_string[0...1]).to eq "A"
267
+ end
268
+
264
269
  it "returns up to the end" do
265
270
  expect(ansi_string[-2..-1]).to eq yellow("ow")
266
271
  end
data/spec/spec_helper.rb CHANGED
@@ -2,7 +2,6 @@ $LOAD_PATH << File.dirname(__FILE__) + "/../lib"
2
2
 
3
3
  require 'pry'
4
4
  require 'terminal_layout'
5
- require 'ansi_string'
6
5
 
7
6
  # This file was generated by the `rspec --init` command. Conventionally, all
8
7
  # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
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.3.1
4
+ version: 0.4.0
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-05-18 00:00:00.000000000 Z
11
+ date: 2016-05-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-terminfo