ansi-select 0.2.5 → 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/CHANGELOG.md +7 -0
- data/bin/ansi-select +1 -1
- data/lib/ansi/selector.rb +24 -22
- data/lib/ansi/selector/impl.rb +85 -22
- data/lib/ansi/selector/multi_impl.rb +2 -2
- data/lib/ansi/selector/single_impl.rb +1 -1
- data/lib/ansi/selector/version.rb +1 -1
- data/position.sh +14 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0b7678dcd7b0eb448dc1ffa8cd3ee7621c89093
|
4
|
+
data.tar.gz: 4e7f2a784d81aa8c3e488715ab795381ec87fcd1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 008e8fa95ec62bfcf6ebb7233b3b4f6cc360fe3ef275ce3f515d4955fef24783bc92e589ff1d1b3c6ed694c4c08c64e0f353786c4f84fa7d62fbfbd8706ae088
|
7
|
+
data.tar.gz: 709585d4347c5398ac9030d4566f8f5fe6827aeca847fe065778f776c47876754219e62c4eca4ff87749eb541a32ce6bea7b0585c93ab5d36ef3e0752f87e7cb
|
data/CHANGELOG.md
CHANGED
data/bin/ansi-select
CHANGED
data/lib/ansi/selector.rb
CHANGED
@@ -1,32 +1,34 @@
|
|
1
1
|
module Ansi
|
2
2
|
class Selector
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
class << self
|
4
|
+
# @param [Array<Object>] options
|
5
|
+
# @param [Proc] formatter
|
6
|
+
# @param [Fixnum] preselected
|
7
|
+
#
|
8
|
+
# @return [Object] option
|
9
|
+
def select(options, formatter: default_formatter, preselected: 0)
|
10
|
+
require_relative "selector/single_impl"
|
10
11
|
|
11
|
-
|
12
|
-
|
12
|
+
SingleImpl.new(options, formatter, preselected).select
|
13
|
+
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
15
|
+
# @param [Array<Object>] options
|
16
|
+
# @param [Proc] formatter
|
17
|
+
# @param [Array<Fixnum>] preselected
|
18
|
+
#
|
19
|
+
# @return [Array<Object>] option
|
20
|
+
def multi_select(options, formatter: default_formatter, preselected: [])
|
21
|
+
require_relative "selector/multi_impl"
|
21
22
|
|
22
|
-
|
23
|
-
|
23
|
+
MultiImpl.new(options, formatter, preselected).select
|
24
|
+
end
|
24
25
|
|
25
|
-
|
26
|
+
private
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
# @return [Proc]
|
29
|
+
def default_formatter
|
30
|
+
:to_s.to_proc
|
31
|
+
end
|
30
32
|
end
|
31
33
|
end
|
32
34
|
end
|
data/lib/ansi/selector/impl.rb
CHANGED
@@ -16,20 +16,54 @@ module Ansi
|
|
16
16
|
@formatter = formatter
|
17
17
|
@highlighted_line_index = 0
|
18
18
|
@cursor_line_index = 0
|
19
|
+
@columns = terminal_columns
|
19
20
|
|
20
21
|
# Converts options to column-aligned strings.
|
21
|
-
formatted = @options.map(&@formatter).map(&method(:Array))
|
22
|
+
formatted = @options.map(&@formatter).map(&method(:Array)).map { |line| line.map(&method(:strip_ansi_colors)) }
|
22
23
|
@formatted ||= formatted.map do |f|
|
23
24
|
f.map.with_index do |part, column|
|
24
25
|
width = formatted.map { |fm| fm[column] }.compact.map(&:size).max
|
25
26
|
part.to_s.ljust(width)
|
26
27
|
end.join(' ')
|
27
28
|
end
|
29
|
+
|
30
|
+
Signal.trap('SIGWINCH', proc do
|
31
|
+
columns = terminal_columns
|
32
|
+
if columns < @columns && !all_options_fit?(columns)
|
33
|
+
# When a buffer gets narrower, the text that doesn't fit into the screen anymore
|
34
|
+
# starts jumping around in a way that makes it hard to predict. In such case we
|
35
|
+
# clear everything and re-print options at the beginning of the buffer to
|
36
|
+
# simplify things.
|
37
|
+
tty.print(`printf '\e[2J'`)
|
38
|
+
tty.print(`tput cup 0 0`)
|
39
|
+
else
|
40
|
+
print_line(0)
|
41
|
+
end
|
42
|
+
|
43
|
+
@columns = columns
|
44
|
+
print_options
|
45
|
+
end)
|
46
|
+
end
|
47
|
+
|
48
|
+
def all_options_fit?(columns)
|
49
|
+
option_indices.map(&method(:final_text_for_line)).map(&:size).all? { |size| size < columns }
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [Fixnum]
|
53
|
+
def terminal_columns
|
54
|
+
`tput cols`.to_i
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return [Fixnum]
|
58
|
+
def terminal_lines
|
59
|
+
`tput lines`.to_i
|
28
60
|
end
|
29
61
|
|
30
62
|
def select
|
31
63
|
print_options
|
32
64
|
answer = ask_to_choose
|
65
|
+
# We need to reprint here in order to render the lines that are behind the buffer.
|
66
|
+
range(@highlighted_line_index, @options.size - 1).each(&method(:print_line))
|
33
67
|
go_to_line(@options.size)
|
34
68
|
|
35
69
|
answer
|
@@ -45,16 +79,16 @@ module Ansi
|
|
45
79
|
end
|
46
80
|
|
47
81
|
def print_options
|
48
|
-
@options.each.with_index do |_, index|
|
49
|
-
print_line(index
|
82
|
+
@options[0...terminal_lines].each.with_index do |_, index|
|
83
|
+
print_line(index)
|
50
84
|
|
51
85
|
unless index == @options.size - 1
|
52
|
-
tty.print $/ # This
|
86
|
+
tty.print $/ # This global variable is a cross-platform new line.
|
53
87
|
@cursor_line_index += 1
|
54
88
|
end
|
55
89
|
end
|
56
90
|
|
57
|
-
|
91
|
+
print_line(0)
|
58
92
|
end
|
59
93
|
|
60
94
|
# @return [String]
|
@@ -81,38 +115,36 @@ module Ansi
|
|
81
115
|
when "\u0003", "q"
|
82
116
|
exit(0)
|
83
117
|
when " "
|
84
|
-
|
118
|
+
space_key_handler
|
85
119
|
when CODES[:carriage_return_key]
|
86
120
|
break carriage_return_handler
|
87
121
|
when "\e[A", "k", CODES[:cursor_up]
|
88
|
-
|
122
|
+
scroll_to(@highlighted_line_index - 1)
|
89
123
|
when "\e[B", "j", CODES[:cursor_down]
|
90
|
-
|
124
|
+
scroll_to(@highlighted_line_index + 1)
|
91
125
|
end
|
92
126
|
end
|
93
127
|
end
|
94
128
|
|
95
129
|
# @param [Fixnum] index
|
96
|
-
|
97
|
-
|
130
|
+
def scroll_to(index)
|
131
|
+
indices_to_reprint = range(@highlighted_line_index, index)
|
132
|
+
@highlighted_line_index = indices_to_reprint.last
|
133
|
+
indices_to_reprint.each(&method(:print_line))
|
134
|
+
end
|
135
|
+
|
136
|
+
# @param [Fixnum] index
|
137
|
+
def print_line(index)
|
98
138
|
go_to_line(index)
|
99
|
-
text =
|
139
|
+
text = final_text_for_line(index)
|
100
140
|
|
101
|
-
if
|
141
|
+
if index == @highlighted_line_index
|
102
142
|
tty.print(CODES[:standout_mode] + text + CODES[:exit_standout_mode])
|
103
143
|
else
|
104
144
|
tty.print(text)
|
105
145
|
end
|
106
146
|
end
|
107
147
|
|
108
|
-
# @param [Fixnum] index
|
109
|
-
def highlight_line(index)
|
110
|
-
print_line(@highlighted_line_index, false)
|
111
|
-
print_line(index, true)
|
112
|
-
|
113
|
-
@highlighted_line_index = index
|
114
|
-
end
|
115
|
-
|
116
148
|
# @param [Fixnum] index
|
117
149
|
def go_to_line(index)
|
118
150
|
if index == @cursor_line_index
|
@@ -120,24 +152,55 @@ module Ansi
|
|
120
152
|
elsif index > @cursor_line_index
|
121
153
|
(index - @cursor_line_index).times { tty.print CODES[:cursor_down] }
|
122
154
|
else
|
123
|
-
|
155
|
+
row_before_going = `bash position.sh`.to_i
|
156
|
+
(@cursor_line_index - index).times do |step|
|
157
|
+
tty.print(`tput ri`) if step >= row_before_going
|
158
|
+
tty.print CODES[:cursor_up]
|
159
|
+
end
|
124
160
|
end
|
125
161
|
|
126
162
|
@cursor_line_index = index
|
127
163
|
tty.print CODES[:carriage_return_key]
|
128
164
|
end
|
129
165
|
|
166
|
+
# @param [Fixnum] index
|
167
|
+
#
|
168
|
+
# @return [String]
|
169
|
+
def final_text_for_line(index)
|
170
|
+
maybe_add_ellipsis(prefix(index) + @formatted[index])
|
171
|
+
end
|
172
|
+
|
173
|
+
# @param [String] text
|
174
|
+
def maybe_add_ellipsis(text)
|
175
|
+
text.size >= @columns ? text[0...(@columns - 2)] + '…' : text
|
176
|
+
end
|
177
|
+
|
178
|
+
# @param [String] text
|
179
|
+
#
|
180
|
+
# @return [String]
|
181
|
+
def strip_ansi_colors(text)
|
182
|
+
text.gsub(/\e\[(\d+;?)+m/, '')
|
183
|
+
end
|
184
|
+
|
130
185
|
def prefix(index)
|
131
186
|
raise NotImplementedError
|
132
187
|
end
|
133
188
|
|
134
|
-
def
|
189
|
+
def space_key_handler
|
135
190
|
raise NotImplementedError
|
136
191
|
end
|
137
192
|
|
138
193
|
def carriage_return_handler
|
139
194
|
raise NotImplementedError
|
140
195
|
end
|
196
|
+
|
197
|
+
def option_indices
|
198
|
+
(0...@options.size)
|
199
|
+
end
|
200
|
+
|
201
|
+
def range(from, to)
|
202
|
+
((from <= to) ? from.upto(to) : from.downto(to)).to_a.select { |index| (0...@options.size).cover?(index) }
|
203
|
+
end
|
141
204
|
end
|
142
205
|
end
|
143
206
|
end
|
@@ -14,9 +14,9 @@ module Ansi
|
|
14
14
|
@selected_options[index] ? ' [x] ' : ' [ ] '
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
17
|
+
def space_key_handler
|
18
18
|
@selected_options[@cursor_line_index] = !@selected_options[@cursor_line_index]
|
19
|
-
print_line(@cursor_line_index
|
19
|
+
print_line(@cursor_line_index)
|
20
20
|
end
|
21
21
|
|
22
22
|
def carriage_return_handler
|
data/position.sh
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
# based on a script from http://invisible-island.net/xterm/xterm.faq.html
|
3
|
+
exec < /dev/tty
|
4
|
+
oldstty=$(stty -g)
|
5
|
+
stty raw -echo min 0
|
6
|
+
# on my system, the following line can be replaced by the line below it
|
7
|
+
echo -en "\033[6n" > /dev/tty
|
8
|
+
# tput u7 > /dev/tty # when TERM=xterm (and relatives)
|
9
|
+
IFS=';' read -r -d R -a pos
|
10
|
+
stty $oldstty
|
11
|
+
# change from one-based to zero based so they work with: tput cup $row $col
|
12
|
+
row=$((${pos[0]:2} - 1)) # strip off the esc-[
|
13
|
+
|
14
|
+
echo "$row"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ansi-select
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Volodymyr Shatskyi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-10-
|
11
|
+
date: 2015-10-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -63,6 +63,7 @@ files:
|
|
63
63
|
- lib/ansi/selector/multi_impl.rb
|
64
64
|
- lib/ansi/selector/single_impl.rb
|
65
65
|
- lib/ansi/selector/version.rb
|
66
|
+
- position.sh
|
66
67
|
homepage: https://github.com/shockone/ansi-select
|
67
68
|
licenses: []
|
68
69
|
metadata: {}
|