terminal-layout 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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