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