terminal-layout 0.2.0 → 0.3.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/.ruby-version +1 -0
- data/Gemfile.lock +2 -3
- data/Rakefile +3 -0
- data/lib/ansi_string.rb +23 -9
- data/lib/tasks/gem.rake +62 -0
- data/lib/terminal_layout.rb +41 -20
- data/lib/terminal_layout/version.rb +3 -0
- data/spec/ansi_string_spec.rb +27 -0
- data/terminal-layout.gemspec +5 -5
- metadata +14 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b5943e939a5e3ba0dca04844bbea647acc52b05
|
4
|
+
data.tar.gz: 805918708734666de21d1298a74a245aa517eb86
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b87d75ee8483d361a9268fe65514bc61500590d427aab37c68b1b3c8f7ac70af11e5461e600e1629664046c4df8be33f0b8cf3add4734be0d7f1649b349f5ea2
|
7
|
+
data.tar.gz: c0cb7f37b2b2e0ea59cf3bcfa024c18f50f6f0aa572c740abc978d6ed4ca1263bf15914dc8ec5c2cdac985a1bf747f2df5a2eb2c100d8308752b7ebe2e77aec7
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.2.3
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
terminal-layout (0.
|
5
|
-
highline
|
4
|
+
terminal-layout (0.3.0)
|
5
|
+
highline (~> 1.7, >= 1.7.8)
|
6
6
|
ruby-terminfo (~> 0.1.1)
|
7
7
|
ruby-termios (~> 0.9.6)
|
8
8
|
|
@@ -49,7 +49,6 @@ PLATFORMS
|
|
49
49
|
|
50
50
|
DEPENDENCIES
|
51
51
|
bundler (~> 1.7)
|
52
|
-
pry
|
53
52
|
pry-byebug
|
54
53
|
rake (~> 10.0)
|
55
54
|
rspec
|
data/Rakefile
ADDED
data/lib/ansi_string.rb
CHANGED
@@ -24,6 +24,14 @@ class ANSIString
|
|
24
24
|
self
|
25
25
|
end
|
26
26
|
|
27
|
+
def insert(position, string)
|
28
|
+
if position < 0
|
29
|
+
position = @without_ansi.length + position + 1
|
30
|
+
end
|
31
|
+
self[position...position] = string
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
27
35
|
def empty?
|
28
36
|
length == 0
|
29
37
|
end
|
@@ -33,14 +41,19 @@ class ANSIString
|
|
33
41
|
range = (range..range) if range.is_a?(Integer)
|
34
42
|
|
35
43
|
range_begin = range.begin
|
36
|
-
range_end = range.
|
44
|
+
range_end = range.end
|
45
|
+
if range.end != range.begin
|
46
|
+
range_end = range.exclude_end? ? range.end - 1 : range.end
|
47
|
+
end
|
37
48
|
|
38
49
|
range_begin = @without_ansi.length - range.begin.abs if range.begin < 0
|
39
50
|
range_end = @without_ansi.length - range.end.abs if range.end < 0
|
40
51
|
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
44
57
|
end
|
45
58
|
end
|
46
59
|
|
@@ -83,22 +96,23 @@ class ANSIString
|
|
83
96
|
if md.captures.any?
|
84
97
|
results << md.captures.map.with_index do |_, i|
|
85
98
|
# captures use 1-based indexing
|
86
|
-
self[md.begin(i+1)
|
99
|
+
self[md.begin(i+1)..md.end(i+1)-1]
|
87
100
|
end
|
88
101
|
else
|
89
|
-
results << self[md.begin(0)
|
102
|
+
results << self[md.begin(0)..md.end(0)-1]
|
90
103
|
end
|
91
104
|
end
|
92
105
|
results
|
93
106
|
end
|
94
107
|
|
95
108
|
def slice(index, length=nil)
|
109
|
+
return ANSIString.new("") if length == 0
|
96
110
|
range = nil
|
97
111
|
index = index.without_ansi if index.is_a?(ANSIString)
|
98
112
|
index = Regexp.new Regexp.escape(index) if index.is_a?(String)
|
99
113
|
if index.is_a?(Integer)
|
100
|
-
length
|
101
|
-
range = (index
|
114
|
+
length ||= 1
|
115
|
+
range = (index..index+length-1)
|
102
116
|
elsif index.is_a?(Range)
|
103
117
|
range = index
|
104
118
|
elsif index.is_a?(Regexp)
|
@@ -106,7 +120,7 @@ class ANSIString
|
|
106
120
|
capture_group_index = length || 0
|
107
121
|
if md
|
108
122
|
capture_group = md.offset(capture_group_index)
|
109
|
-
range = (capture_group.first
|
123
|
+
range = (capture_group.first..capture_group.last-1)
|
110
124
|
end
|
111
125
|
else
|
112
126
|
raise(ArgumentError, "Must pass in at least an index or a range.")
|
data/lib/tasks/gem.rake
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
namespace :bump do
|
2
|
+
namespace :version do
|
3
|
+
class ProjectVersion
|
4
|
+
FILE = File.dirname(__FILE__) + '/../terminal_layout/version.rb'
|
5
|
+
PATTERN = /VERSION\s*=\s*"(\d+)\.(\d+)\.(\d+)"/m
|
6
|
+
|
7
|
+
def initialize(file=FILE, pattern=PATTERN)
|
8
|
+
@file = file
|
9
|
+
@pattern = pattern
|
10
|
+
end
|
11
|
+
|
12
|
+
def bump(major:nil, minor:nil, patch:nil)
|
13
|
+
version = nil
|
14
|
+
contents.sub!(@pattern) do
|
15
|
+
_major = major.call($1) if major
|
16
|
+
_minor = minor.call($2) if minor
|
17
|
+
_patch = patch.call($3) if patch
|
18
|
+
version = "#{_major}.#{_minor}.#{_patch}"
|
19
|
+
results = %|VERSION = "#{version}"|
|
20
|
+
end
|
21
|
+
File.write(@file, contents)
|
22
|
+
system "bundle"
|
23
|
+
system "git add #{ProjectVersion::FILE} && git commit -m 'Bumping version to #{version}'"
|
24
|
+
system "git tag v#{version}"
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def contents
|
30
|
+
@contents ||= File.read(@file)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "Increments the patch number by 1 for the project"
|
35
|
+
task :patch do
|
36
|
+
ProjectVersion.new.bump(
|
37
|
+
major: ->(major){ major },
|
38
|
+
minor: ->(minor){ minor },
|
39
|
+
patch: ->(patch){ patch.succ }
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "Increments the minor number by 1 for the project"
|
44
|
+
task :minor do
|
45
|
+
ProjectVersion.new.bump(
|
46
|
+
major: ->(major){ major },
|
47
|
+
minor: ->(minor){ minor.succ },
|
48
|
+
patch: ->(patch){ 0 }
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
desc "Increments the major number by 1 for the project"
|
53
|
+
task :major do
|
54
|
+
ProjectVersion.new.bump(
|
55
|
+
major: ->(major){ major.succ },
|
56
|
+
minor: ->(minor){ 0 },
|
57
|
+
patch: ->(patch){ 0 }
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
data/lib/terminal_layout.rb
CHANGED
@@ -335,8 +335,8 @@ module TerminalLayout
|
|
335
335
|
emit :child_changed
|
336
336
|
end
|
337
337
|
|
338
|
-
child.on(:
|
339
|
-
emit :
|
338
|
+
child.on(:position_changed) do |*args|
|
339
|
+
emit :position_changed
|
340
340
|
end
|
341
341
|
end
|
342
342
|
end
|
@@ -402,12 +402,17 @@ module TerminalLayout
|
|
402
402
|
|
403
403
|
|
404
404
|
class InputBox < Box
|
405
|
+
# cursor_position is the actual coordinates on the screen of where then
|
406
|
+
# cursor is rendered
|
405
407
|
attr_accessor :cursor_position
|
406
408
|
|
409
|
+
# position is the desired X-position of the cursor if everything was
|
410
|
+
# displayed on a single line
|
411
|
+
attr_accessor :position
|
412
|
+
|
407
413
|
def initialize(*args)
|
408
414
|
super
|
409
415
|
@computed = { x: 0, y: 0 }
|
410
|
-
@cursor_offset_x = 0
|
411
416
|
@cursor_position = OpenStruct.new(x: 0, y: 0)
|
412
417
|
@position = 0
|
413
418
|
end
|
@@ -429,20 +434,21 @@ module TerminalLayout
|
|
429
434
|
end
|
430
435
|
end
|
431
436
|
|
432
|
-
def position=(
|
433
|
-
|
434
|
-
@
|
435
|
-
emit :
|
437
|
+
def position=(new_position)
|
438
|
+
old_position = @position
|
439
|
+
@position = new_position
|
440
|
+
emit :position_changed, old_position, @position
|
436
441
|
end
|
437
442
|
|
438
443
|
def update_computed(style)
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
+
# if the style being updated has a y greater than 0
|
445
|
+
# then it's because the renderable content for the input box
|
446
|
+
# spans multiple lines. We do not want to update the x/y position(s)
|
447
|
+
# in this instance. We want to keep the original starting x/y.
|
448
|
+
if style[:y] && style[:y] > 0
|
449
|
+
style = style.dup.delete_if { |k,_| [:x, :y].include?(k) }
|
444
450
|
end
|
445
|
-
@
|
451
|
+
@computed.merge!(style)
|
446
452
|
end
|
447
453
|
end
|
448
454
|
|
@@ -466,17 +472,32 @@ module TerminalLayout
|
|
466
472
|
move_up_n_rows @y
|
467
473
|
move_to_beginning_of_row
|
468
474
|
|
475
|
+
position = input_box.position
|
476
|
+
|
469
477
|
cursor_position = input_box.cursor_position
|
470
478
|
cursor_x = cursor_position.x
|
471
479
|
cursor_y = cursor_position.y
|
472
480
|
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
481
|
+
relative_position_on_row = position
|
482
|
+
initial_offset_x = input_box.computed[:x] + (input_box.computed[:y] * terminal_width)
|
483
|
+
cursor_x = 0
|
484
|
+
cursor_y = 0
|
485
|
+
|
486
|
+
absolute_position_on_row = relative_position_on_row + initial_offset_x
|
487
|
+
loop do
|
488
|
+
if absolute_position_on_row >= terminal_width
|
489
|
+
# reset offset
|
490
|
+
initial_offset_x = 0
|
491
|
+
|
492
|
+
absolute_position_on_row -= terminal_width
|
493
|
+
|
494
|
+
# move down a line
|
495
|
+
cursor_y += 1
|
496
|
+
else
|
497
|
+
# we fit on the current line
|
498
|
+
cursor_x = absolute_position_on_row
|
499
|
+
break
|
500
|
+
end
|
480
501
|
end
|
481
502
|
|
482
503
|
if @y < cursor_y
|
data/spec/ansi_string_spec.rb
CHANGED
@@ -105,6 +105,32 @@ describe 'ANSIString' do
|
|
105
105
|
end
|
106
106
|
end
|
107
107
|
|
108
|
+
describe "#insert (see Ruby's String#insert for intent)" do
|
109
|
+
it "insert a string into the ANSIString" do
|
110
|
+
ansi_string = ANSIString.new "az"
|
111
|
+
ansi_string.insert 1, "thru"
|
112
|
+
expect(ansi_string).to eq ANSIString.new("athruz")
|
113
|
+
|
114
|
+
ansi_string.insert 0, "_"
|
115
|
+
expect(ansi_string).to eq ANSIString.new("_athruz")
|
116
|
+
|
117
|
+
ansi_string.insert ansi_string.length, "_"
|
118
|
+
expect(ansi_string).to eq ANSIString.new("_athruz_")
|
119
|
+
end
|
120
|
+
|
121
|
+
it "insert an ANSIString into an ANSIString" do
|
122
|
+
ansi_string = ANSIString.new blue("az")
|
123
|
+
ansi_string.insert 1, yellow("thru")
|
124
|
+
expect(ansi_string).to eq ANSIString.new("\e[34ma\e[33mthru\e[0mz\e[0m")
|
125
|
+
end
|
126
|
+
|
127
|
+
it "inserts from the end with a negative position" do
|
128
|
+
ansi_string = ANSIString.new blue("az")
|
129
|
+
ansi_string.insert -2, yellow("thru")
|
130
|
+
expect(ansi_string).to eq ANSIString.new("\e[34ma\e[33mthru\e[0mz\e[0m")
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
108
134
|
describe "#length" do
|
109
135
|
subject(:ansi_string){ ANSIString.new blue(string) }
|
110
136
|
let(:string){ "this is blue" }
|
@@ -540,6 +566,7 @@ describe 'ANSIString' do
|
|
540
566
|
|
541
567
|
it "returns a substring of characters of N length given a start index and max length N" do
|
542
568
|
ansi_string = ANSIString.new("a#{blue('b')}c")
|
569
|
+
expect(ansi_string.slice(0, 0)).to eq ANSIString.new("")
|
543
570
|
expect(ansi_string.slice(0, 2)).to eq ANSIString.new("a#{blue('b')}")
|
544
571
|
expect(ansi_string.slice(1, 2)).to eq ANSIString.new("#{blue('b')}c")
|
545
572
|
|
data/terminal-layout.gemspec
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
lib = File.expand_path('../lib', __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'terminal_layout/version'
|
4
5
|
|
5
6
|
Gem::Specification.new do |spec|
|
6
7
|
spec.name = "terminal-layout"
|
7
|
-
spec.version =
|
8
|
+
spec.version = TerminalLayout::VERSION
|
8
9
|
spec.authors = ["Zach Dennis"]
|
9
10
|
spec.email = ["zach.dennis@gmail.com"]
|
10
11
|
spec.summary = %q{A terminal layout manager}
|
@@ -17,12 +18,11 @@ Gem::Specification.new do |spec|
|
|
17
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
19
|
spec.require_paths = ["lib"]
|
19
20
|
|
20
|
-
spec.add_dependency
|
21
|
-
spec.add_dependency
|
22
|
-
spec.add_dependency
|
21
|
+
spec.add_dependency "ruby-terminfo", "~> 0.1.1"
|
22
|
+
spec.add_dependency "ruby-termios", "~> 0.9.6"
|
23
|
+
spec.add_dependency 'highline', '~> 1.7', '>= 1.7.8'
|
23
24
|
|
24
25
|
spec.add_development_dependency "bundler", "~> 1.7"
|
25
26
|
spec.add_development_dependency "rake", "~> 10.0"
|
26
27
|
spec.add_development_dependency "rspec", "~> 3.2"
|
27
|
-
spec.add_development_dependency "pry"
|
28
28
|
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
|
+
version: 0.3.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-
|
11
|
+
date: 2016-05-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby-terminfo
|
@@ -42,16 +42,22 @@ dependencies:
|
|
42
42
|
name: highline
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.7'
|
45
48
|
- - ">="
|
46
49
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
50
|
+
version: 1.7.8
|
48
51
|
type: :runtime
|
49
52
|
prerelease: false
|
50
53
|
version_requirements: !ruby/object:Gem::Requirement
|
51
54
|
requirements:
|
55
|
+
- - "~>"
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '1.7'
|
52
58
|
- - ">="
|
53
59
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
60
|
+
version: 1.7.8
|
55
61
|
- !ruby/object:Gem::Dependency
|
56
62
|
name: bundler
|
57
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,20 +100,6 @@ dependencies:
|
|
94
100
|
- - "~>"
|
95
101
|
- !ruby/object:Gem::Version
|
96
102
|
version: '3.2'
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: pry
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - ">="
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
111
103
|
description: A terminal layout manager
|
112
104
|
email:
|
113
105
|
- zach.dennis@gmail.com
|
@@ -116,13 +108,17 @@ extensions: []
|
|
116
108
|
extra_rdoc_files: []
|
117
109
|
files:
|
118
110
|
- ".rspec"
|
111
|
+
- ".ruby-version"
|
119
112
|
- ".travis.yml"
|
120
113
|
- Gemfile
|
121
114
|
- Gemfile.lock
|
122
115
|
- README.md
|
116
|
+
- Rakefile
|
123
117
|
- block-flow.rb
|
124
118
|
- lib/ansi_string.rb
|
119
|
+
- lib/tasks/gem.rake
|
125
120
|
- lib/terminal_layout.rb
|
121
|
+
- lib/terminal_layout/version.rb
|
126
122
|
- spec/ansi_string_spec.rb
|
127
123
|
- spec/spec_helper.rb
|
128
124
|
- spec/terminal_layout_spec.rb
|