tty-prompt 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -2
- data/CHANGELOG.md +12 -0
- data/README.md +223 -59
- data/lib/tty/prompt/choice.rb +83 -0
- data/lib/tty/prompt/choices.rb +92 -0
- data/lib/tty/prompt/codes.rb +32 -0
- data/lib/tty/prompt/cursor.rb +131 -0
- data/lib/tty/prompt/list.rb +209 -0
- data/lib/tty/prompt/mode/echo.rb +10 -9
- data/lib/tty/prompt/mode/raw.rb +10 -9
- data/lib/tty/prompt/multi_list.rb +105 -0
- data/lib/tty/prompt/question/validation.rb +12 -27
- data/lib/tty/prompt/question.rb +58 -107
- data/lib/tty/prompt/reader.rb +44 -11
- data/lib/tty/prompt/response.rb +31 -36
- data/lib/tty/prompt/response_delegation.rb +3 -2
- data/lib/tty/prompt/statement.rb +10 -10
- data/lib/tty/prompt/test.rb +15 -0
- data/lib/tty/prompt/version.rb +3 -3
- data/lib/tty/prompt.rb +72 -9
- data/lib/tty-prompt.rb +11 -0
- data/spec/unit/ask_spec.rb +32 -35
- data/spec/unit/choice/eql_spec.rb +24 -0
- data/spec/unit/choice/from_spec.rb +25 -0
- data/spec/unit/choices/add_spec.rb +14 -0
- data/spec/unit/choices/each_spec.rb +15 -0
- data/spec/unit/choices/new_spec.rb +12 -0
- data/spec/unit/choices/pluck_spec.rb +11 -0
- data/spec/unit/cursor/new_spec.rb +74 -0
- data/spec/unit/error_spec.rb +4 -8
- data/spec/unit/multi_select_spec.rb +163 -0
- data/spec/unit/question/character_spec.rb +5 -16
- data/spec/unit/question/default_spec.rb +4 -10
- data/spec/unit/question/in_spec.rb +15 -12
- data/spec/unit/question/initialize_spec.rb +1 -6
- data/spec/unit/question/modify_spec.rb +25 -24
- data/spec/unit/question/required_spec.rb +31 -0
- data/spec/unit/question/validate_spec.rb +25 -17
- data/spec/unit/question/validation/call_spec.rb +22 -0
- data/spec/unit/response/read_bool_spec.rb +38 -27
- data/spec/unit/response/read_char_spec.rb +5 -8
- data/spec/unit/response/read_date_spec.rb +8 -12
- data/spec/unit/response/read_email_spec.rb +25 -22
- data/spec/unit/response/read_multiple_spec.rb +11 -13
- data/spec/unit/response/read_number_spec.rb +12 -16
- data/spec/unit/response/read_range_spec.rb +10 -13
- data/spec/unit/response/read_spec.rb +39 -38
- data/spec/unit/response/read_string_spec.rb +7 -12
- data/spec/unit/say_spec.rb +10 -14
- data/spec/unit/select_spec.rb +192 -0
- data/spec/unit/statement/initialize_spec.rb +0 -4
- data/spec/unit/suggest_spec.rb +6 -9
- data/spec/unit/warn_spec.rb +4 -8
- metadata +32 -8
- data/spec/unit/question/argument_spec.rb +0 -30
- data/spec/unit/question/valid_spec.rb +0 -46
- data/spec/unit/question/validation/valid_value_spec.rb +0 -22
data/lib/tty/prompt.rb
CHANGED
@@ -20,12 +20,12 @@ module TTY
|
|
20
20
|
# @api private
|
21
21
|
attr_reader :output
|
22
22
|
|
23
|
-
#
|
23
|
+
# Prompt prefix
|
24
24
|
#
|
25
25
|
# @api private
|
26
26
|
attr_reader :prefix
|
27
27
|
|
28
|
-
# Initialize a
|
28
|
+
# Initialize a Prompt
|
29
29
|
#
|
30
30
|
# @api public
|
31
31
|
def initialize(input = stdin, output = stdout, options = {})
|
@@ -37,7 +37,7 @@ module TTY
|
|
37
37
|
# Ask a question.
|
38
38
|
#
|
39
39
|
# @example
|
40
|
-
# shell = TTY::
|
40
|
+
# shell = TTY::Prompt.new
|
41
41
|
# shell.ask("What is your name?")
|
42
42
|
#
|
43
43
|
# @param [String] statement
|
@@ -51,22 +51,85 @@ module TTY
|
|
51
51
|
# @return [TTY::Question]
|
52
52
|
#
|
53
53
|
# @api public
|
54
|
-
def ask(
|
54
|
+
def ask(message, *args, &block)
|
55
55
|
options = Utils.extract_options!(args)
|
56
56
|
|
57
|
-
question = Question.new
|
58
|
-
question.
|
59
|
-
|
57
|
+
question = Question.new(self, options)
|
58
|
+
question.call(message, &block)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Ask a question with a list of options
|
62
|
+
#
|
63
|
+
# @example
|
64
|
+
# prompt = TTY::Prompt.new
|
65
|
+
# prompt.select("What size?", %w(large medium small))
|
66
|
+
#
|
67
|
+
# @example
|
68
|
+
# prompt = TTY::Prompt.new
|
69
|
+
# prompt.select("What size?") do |menu|
|
70
|
+
# menu.choice :large
|
71
|
+
# menu.choices %w(:medium :small)
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# @param [String] question
|
75
|
+
# the question to ask
|
76
|
+
#
|
77
|
+
# @param [Array[Object]] choices
|
78
|
+
# the choices to select from
|
79
|
+
#
|
80
|
+
# @api public
|
81
|
+
def select(question, *args, &block)
|
82
|
+
options = Utils.extract_options!(args)
|
83
|
+
choices = if block
|
84
|
+
[]
|
85
|
+
elsif args.empty?
|
86
|
+
options
|
87
|
+
else
|
88
|
+
args.flatten
|
89
|
+
end
|
90
|
+
|
91
|
+
list = List.new(self, options)
|
92
|
+
list.call(question, choices, &block)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Ask a question with multiple attributes activated
|
96
|
+
#
|
97
|
+
# @example
|
98
|
+
# prompt = TTY::Prompt.new
|
99
|
+
# choices = %w(Scorpion Jax Kitana Baraka Jade)
|
100
|
+
# prompt.multi_select("Choose your destiny?", choices)
|
101
|
+
#
|
102
|
+
# @param [String] question
|
103
|
+
# the question to ask
|
104
|
+
#
|
105
|
+
# @param [Array[Object]] choices
|
106
|
+
# the choices to select from
|
107
|
+
#
|
108
|
+
# @return [String]
|
109
|
+
#
|
110
|
+
# @api public
|
111
|
+
def multi_select(question, *args, &block)
|
112
|
+
options = Utils.extract_options!(args)
|
113
|
+
choices = if block
|
114
|
+
[]
|
115
|
+
elsif args.empty?
|
116
|
+
options
|
117
|
+
else
|
118
|
+
args.flatten
|
119
|
+
end
|
120
|
+
|
121
|
+
list = MultiList.new(self, options)
|
122
|
+
list.call(question, choices, &block)
|
60
123
|
end
|
61
124
|
|
62
125
|
# A shortcut method to ask the user positive question and return
|
63
|
-
# true for 'yes' reply.
|
126
|
+
# true for 'yes' reply, false for 'no'.
|
64
127
|
#
|
65
128
|
# @return [Boolean]
|
66
129
|
#
|
67
130
|
# @api public
|
68
131
|
def yes?(statement, *args, &block)
|
69
|
-
ask(statement,
|
132
|
+
ask(statement, {read: :bool}, &block)
|
70
133
|
end
|
71
134
|
|
72
135
|
# A shortcut method to ask the user negative question and return
|
data/lib/tty-prompt.rb
CHANGED
@@ -5,11 +5,22 @@ require 'pastel'
|
|
5
5
|
require 'tty-platform'
|
6
6
|
|
7
7
|
require 'tty/prompt'
|
8
|
+
require 'tty/prompt/choice'
|
9
|
+
require 'tty/prompt/choices'
|
10
|
+
require 'tty/prompt/codes'
|
11
|
+
require 'tty/prompt/cursor'
|
12
|
+
require 'tty/prompt/list'
|
13
|
+
require 'tty/prompt/multi_list'
|
8
14
|
require 'tty/prompt/mode'
|
9
15
|
require 'tty/prompt/question'
|
10
16
|
require 'tty/prompt/reader'
|
11
17
|
require 'tty/prompt/response'
|
12
18
|
require 'tty/prompt/statement'
|
13
19
|
require 'tty/prompt/suggestion'
|
20
|
+
require 'tty/prompt/test'
|
14
21
|
require 'tty/prompt/utils'
|
15
22
|
require 'tty/prompt/version'
|
23
|
+
|
24
|
+
module TTY
|
25
|
+
PromptConfigurationError = Class.new(StandardError)
|
26
|
+
end
|
data/spec/unit/ask_spec.rb
CHANGED
@@ -3,74 +3,71 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
RSpec.describe TTY::Prompt, '#ask' do
|
6
|
-
let(:input) { StringIO.new }
|
7
|
-
let(:output) { StringIO.new }
|
8
|
-
let(:prefix) { '' }
|
9
|
-
let(:options) { { prefix: prefix } }
|
10
6
|
|
11
|
-
subject(:prompt) { TTY::
|
7
|
+
subject(:prompt) { TTY::TestPrompt.new }
|
12
8
|
|
13
9
|
it 'prints message' do
|
14
|
-
prompt.ask
|
15
|
-
expect(output.string).to eql
|
10
|
+
prompt.ask("What is your name?")
|
11
|
+
expect(prompt.output.string).to eql("What is your name?")
|
16
12
|
end
|
17
13
|
|
18
14
|
it 'prints an empty message ' do
|
19
|
-
prompt.ask
|
20
|
-
expect(output.string).to eql
|
15
|
+
prompt.ask('')
|
16
|
+
expect(prompt.output.string).to eql('')
|
21
17
|
end
|
22
18
|
|
23
19
|
it 'prints an empty message and returns nil if EOF is sent to stdin' do
|
24
|
-
input << nil
|
25
|
-
input.rewind
|
26
|
-
|
27
|
-
expect(
|
20
|
+
prompt.input << nil
|
21
|
+
prompt.input.rewind
|
22
|
+
response = prompt.ask("")
|
23
|
+
expect(response).to eql(nil)
|
24
|
+
expect(prompt.output.string).to eq('')
|
28
25
|
end
|
29
26
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
expect(output.string).to eql " > Are you Polish?\n"
|
38
|
-
end
|
27
|
+
it "asks a question with a prefix '>'" do
|
28
|
+
prompt = TTY::TestPrompt.new(prefix: ' > ')
|
29
|
+
prompt.input << ''
|
30
|
+
prompt.input.rewind
|
31
|
+
response = prompt.ask "Are you Polish?"
|
32
|
+
expect(response).to eq(nil)
|
33
|
+
expect(prompt.output.string).to eql " > Are you Polish?"
|
39
34
|
end
|
40
35
|
|
41
36
|
it 'asks a question with block' do
|
42
|
-
input << ''
|
43
|
-
input.rewind
|
44
|
-
|
45
|
-
default 'Piotr'
|
37
|
+
prompt.input << ''
|
38
|
+
prompt.input.rewind
|
39
|
+
value = prompt.ask "What is your name?" do |q|
|
40
|
+
q.default 'Piotr'
|
46
41
|
end
|
47
|
-
expect(
|
42
|
+
expect(value).to eql "Piotr"
|
43
|
+
expect(prompt.output.string).to eq('What is your name?')
|
48
44
|
end
|
49
45
|
|
50
46
|
context 'yes?' do
|
51
47
|
it 'agrees' do
|
52
|
-
input << 'yes'
|
53
|
-
input.rewind
|
48
|
+
prompt.input << 'yes'
|
49
|
+
prompt.input.rewind
|
54
50
|
expect(prompt.yes?("Are you a human?")).to eq(true)
|
51
|
+
expect(prompt.output.string).to eq('Are you a human?')
|
55
52
|
end
|
56
53
|
|
57
54
|
it 'disagrees' do
|
58
|
-
input << 'no'
|
59
|
-
input.rewind
|
55
|
+
prompt.input << 'no'
|
56
|
+
prompt.input.rewind
|
60
57
|
expect(prompt.yes?("Are you a human?")).to eq(false)
|
61
58
|
end
|
62
59
|
end
|
63
60
|
|
64
61
|
context 'no?' do
|
65
62
|
it 'agrees' do
|
66
|
-
input << 'no'
|
67
|
-
input.rewind
|
63
|
+
prompt.input << 'no'
|
64
|
+
prompt.input.rewind
|
68
65
|
expect(prompt.no?("Are you a human?")).to eq(true)
|
69
66
|
end
|
70
67
|
|
71
68
|
it 'disagrees' do
|
72
|
-
input << 'yes'
|
73
|
-
input.rewind
|
69
|
+
prompt.input << 'yes'
|
70
|
+
prompt.input.rewind
|
74
71
|
expect(prompt.no?("Are you a human?")).to eq(false)
|
75
72
|
end
|
76
73
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe TTY::Prompt::Choice, '#==' do
|
6
|
+
it "is true with the same name and value attributes" do
|
7
|
+
expect(described_class.new(:large, 1)).
|
8
|
+
to eq(described_class.new(:large, 1))
|
9
|
+
end
|
10
|
+
|
11
|
+
it "is false with different name attribute" do
|
12
|
+
expect(described_class.new(:large, 1)).
|
13
|
+
not_to eq(described_class.new(:medium, 1))
|
14
|
+
end
|
15
|
+
|
16
|
+
it "is false with different value attribute" do
|
17
|
+
expect(described_class.new(:large, 1)).
|
18
|
+
not_to eq(described_class.new(:large, 2))
|
19
|
+
end
|
20
|
+
|
21
|
+
it "is false with non-choice object" do
|
22
|
+
expect(described_class.new(:large, 1)).not_to eq(:other)
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe TTY::Prompt::Choice, '#from' do
|
6
|
+
it "creates choice from choice" do
|
7
|
+
choice = described_class.new(:large, 1)
|
8
|
+
expect(described_class.from(choice)).to eq(choice)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "creates choice from string" do
|
12
|
+
choice = described_class.new('large', 'large')
|
13
|
+
expect(described_class.from('large')).to eq(choice)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "creates choice from array" do
|
17
|
+
choice = described_class.new('large', 1)
|
18
|
+
expect(described_class.from([:large, 1])).to eq(choice)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "creates choice from hash value" do
|
22
|
+
choice = described_class.new('large', 1)
|
23
|
+
expect(described_class.from({large: 1})).to eq(choice)
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe TTY::Prompt::Choices, '#<<' do
|
6
|
+
it "adds choice to collection" do
|
7
|
+
choices = described_class.new
|
8
|
+
expect(choices).to be_empty
|
9
|
+
choice = TTY::Prompt::Choice.from([:label, 1])
|
10
|
+
choices << [:label, 1]
|
11
|
+
expect(choices.size).to eq(1)
|
12
|
+
expect(choices.to_ary).to eq([choice])
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe TTY::Prompt::Choices, '.each' do
|
6
|
+
it "iterates over collection" do
|
7
|
+
choices = described_class[:large, :medium, :small]
|
8
|
+
actual = []
|
9
|
+
choices.each do |choice|
|
10
|
+
actual << choice.name
|
11
|
+
end
|
12
|
+
expect(actual).to eq([:large, :medium, :small])
|
13
|
+
expect(choices.each).to be_kind_of(Enumerator)
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe TTY::Prompt::Choices, '.new' do
|
6
|
+
it "creates choices collection" do
|
7
|
+
choice_1 = TTY::Prompt::Choice.from(:label1)
|
8
|
+
choice_2 = TTY::Prompt::Choice.from(:label2)
|
9
|
+
collection = described_class[:label1, :label2]
|
10
|
+
expect(collection.choices).to eq([choice_1, choice_2])
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe TTY::Prompt::Choices, '.pluck' do
|
6
|
+
it "plucks choice from collection by name" do
|
7
|
+
collection = %w(large medium small)
|
8
|
+
choices = described_class[*collection]
|
9
|
+
expect(choices.pluck('medium').name).to eq('medium')
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe TTY::Prompt::Cursor do
|
6
|
+
it "allows to print without mutating state" do
|
7
|
+
cursor = described_class.new
|
8
|
+
expect(cursor.shell).to eq(false)
|
9
|
+
expect(cursor.print.shell).to eq(true)
|
10
|
+
expect(cursor.shell).to eq(false)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "shows cursor" do
|
14
|
+
cursor = described_class.new
|
15
|
+
expect(cursor.show).to eq("\e[?25h")
|
16
|
+
end
|
17
|
+
|
18
|
+
it "hides cursor" do
|
19
|
+
cursor = described_class.new
|
20
|
+
expect(cursor.hide).to eq("\e[?25l")
|
21
|
+
end
|
22
|
+
|
23
|
+
it "saves cursor position" do
|
24
|
+
cursor = described_class.new
|
25
|
+
expect(cursor.save).to eq("\e[s")
|
26
|
+
end
|
27
|
+
|
28
|
+
it "restores cursor position" do
|
29
|
+
cursor = described_class.new
|
30
|
+
expect(cursor.restore).to eq("\e[u")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "moves up default by 1 line" do
|
34
|
+
cursor = described_class.new
|
35
|
+
expect(cursor.move_up).to eq("\e[1A")
|
36
|
+
end
|
37
|
+
|
38
|
+
it "moves up by 5 lines" do
|
39
|
+
cursor = described_class.new
|
40
|
+
expect(cursor.move_up(5)).to eq("\e[5A")
|
41
|
+
end
|
42
|
+
|
43
|
+
it "moves down default by 1 line" do
|
44
|
+
cursor = described_class.new
|
45
|
+
expect(cursor.move_down).to eq("\e[1B")
|
46
|
+
end
|
47
|
+
|
48
|
+
it "clears line" do
|
49
|
+
cursor = described_class.new
|
50
|
+
expect(cursor.clear_line).to eq("\e[1000D\e[K")
|
51
|
+
end
|
52
|
+
|
53
|
+
it "clears 5 lines up" do
|
54
|
+
cursor = described_class.new
|
55
|
+
expect(cursor.clear_lines(5)).to eq([
|
56
|
+
"\e[1A\e[1000D\e[K",
|
57
|
+
"\e[1A\e[1000D\e[K",
|
58
|
+
"\e[1A\e[1000D\e[K",
|
59
|
+
"\e[1A\e[1000D\e[K",
|
60
|
+
"\e[1A\e[1000D\e[K"
|
61
|
+
].join)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "clears 5 lines down" do
|
65
|
+
cursor = described_class.new
|
66
|
+
expect(cursor.clear_lines(5, :down)).to eq([
|
67
|
+
"\e[1B\e[1000D\e[K",
|
68
|
+
"\e[1B\e[1000D\e[K",
|
69
|
+
"\e[1B\e[1000D\e[K",
|
70
|
+
"\e[1B\e[1000D\e[K",
|
71
|
+
"\e[1B\e[1000D\e[K"
|
72
|
+
].join)
|
73
|
+
end
|
74
|
+
end
|
data/spec/unit/error_spec.rb
CHANGED
@@ -3,28 +3,24 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
RSpec.describe TTY::Prompt, '.error' do
|
6
|
-
let(:input) { StringIO.new }
|
7
|
-
let(:output) { StringIO.new }
|
8
6
|
let(:color) { Pastel.new(enabled: true) }
|
9
7
|
|
10
|
-
subject(:prompt) {
|
8
|
+
subject(:prompt) { TTY::TestPrompt.new }
|
11
9
|
|
12
10
|
before { allow(Pastel).to receive(:new).and_return(color) }
|
13
11
|
|
14
|
-
after { output.rewind }
|
15
|
-
|
16
12
|
it 'displays one message' do
|
17
13
|
prompt.error "Nothing is fine!"
|
18
|
-
expect(output.string).to eql "\e[31mNothing is fine!\e[0m\n"
|
14
|
+
expect(prompt.output.string).to eql "\e[31mNothing is fine!\e[0m\n"
|
19
15
|
end
|
20
16
|
|
21
17
|
it 'displays many messages' do
|
22
18
|
prompt.error "Nothing is fine!", "All is broken!"
|
23
|
-
expect(output.string).to eql "\e[31mNothing is fine!\e[0m\n\e[31mAll is broken!\e[0m\n"
|
19
|
+
expect(prompt.output.string).to eql "\e[31mNothing is fine!\e[0m\n\e[31mAll is broken!\e[0m\n"
|
24
20
|
end
|
25
21
|
|
26
22
|
it 'displays message with option' do
|
27
23
|
prompt.error "Nothing is fine!", newline: false
|
28
|
-
expect(output.string).to eql "\e[31mNothing is fine!\e[0m"
|
24
|
+
expect(prompt.output.string).to eql "\e[31mNothing is fine!\e[0m"
|
29
25
|
end
|
30
26
|
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe TTY::Prompt do
|
6
|
+
let(:color) { Pastel.new(enabled: true) }
|
7
|
+
|
8
|
+
before { allow(Pastel).to receive(:new).and_return(color) }
|
9
|
+
|
10
|
+
it "selects nothing when return pressed immediately" do
|
11
|
+
prompt = TTY::TestPrompt.new
|
12
|
+
choices = %w(vodka beer wine whisky bourbon)
|
13
|
+
prompt.input << "\r"
|
14
|
+
prompt.input.rewind
|
15
|
+
expect(prompt.multi_select("Select drinks?", choices)). to eq([])
|
16
|
+
expect(prompt.output.string).to eq([
|
17
|
+
"\e[?25lSelect drinks? \e[90m(Use arrow keys, press Space to select and Enter to finish)\e[0m\n",
|
18
|
+
"‣ ⬡ vodka\n",
|
19
|
+
" ⬡ beer\n",
|
20
|
+
" ⬡ wine\n",
|
21
|
+
" ⬡ whisky\n",
|
22
|
+
" ⬡ bourbon\n",
|
23
|
+
"\e[1A\e[1000D\e[K" * 6,
|
24
|
+
"Select drinks? \n\e[?25h"
|
25
|
+
].join)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "selects item when space pressed" do
|
29
|
+
prompt = TTY::TestPrompt.new
|
30
|
+
choices = %w(vodka beer wine whisky bourbon)
|
31
|
+
prompt.input << " \r"
|
32
|
+
prompt.input.rewind
|
33
|
+
expect(prompt.multi_select("Select drinks?", choices)). to eq(['vodka'])
|
34
|
+
expect(prompt.output.string).to eq([
|
35
|
+
"\e[?25lSelect drinks? \e[90m(Use arrow keys, press Space to select and Enter to finish)\e[0m\n",
|
36
|
+
"‣ ⬡ vodka\n",
|
37
|
+
" ⬡ beer\n",
|
38
|
+
" ⬡ wine\n",
|
39
|
+
" ⬡ whisky\n",
|
40
|
+
" ⬡ bourbon\n",
|
41
|
+
"\e[1A\e[1000D\e[K" * 6,
|
42
|
+
"Select drinks? vodka\n",
|
43
|
+
"‣ \e[32m⬢\e[0m vodka\n",
|
44
|
+
" ⬡ beer\n",
|
45
|
+
" ⬡ wine\n",
|
46
|
+
" ⬡ whisky\n",
|
47
|
+
" ⬡ bourbon\n",
|
48
|
+
"\e[1A\e[1000D\e[K" * 6,
|
49
|
+
"Select drinks? \e[32mvodka\e[0m\n\e[?25h"
|
50
|
+
].join)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "sets choice custom values" do
|
54
|
+
prompt = TTY::TestPrompt.new
|
55
|
+
choices = {vodka: 1, beer: 2, wine: 3, whisky: 4, bourbon: 5}
|
56
|
+
prompt.input << " \r"
|
57
|
+
prompt.input.rewind
|
58
|
+
expect(prompt.multi_select("Select drinks?", choices)).to eq([1])
|
59
|
+
expect(prompt.output.string).to eq([
|
60
|
+
"\e[?25lSelect drinks? \e[90m(Use arrow keys, press Space to select and Enter to finish)\e[0m\n",
|
61
|
+
"‣ ⬡ vodka\n",
|
62
|
+
" ⬡ beer\n",
|
63
|
+
" ⬡ wine\n",
|
64
|
+
" ⬡ whisky\n",
|
65
|
+
" ⬡ bourbon\n",
|
66
|
+
"\e[1A\e[1000D\e[K" * 6,
|
67
|
+
"Select drinks? vodka\n",
|
68
|
+
"‣ \e[32m⬢\e[0m vodka\n",
|
69
|
+
" ⬡ beer\n",
|
70
|
+
" ⬡ wine\n",
|
71
|
+
" ⬡ whisky\n",
|
72
|
+
" ⬡ bourbon\n",
|
73
|
+
"\e[1A\e[1000D\e[K" * 6,
|
74
|
+
"Select drinks? \e[32mvodka\e[0m\n\e[?25h"
|
75
|
+
].join)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "sets choice name and value through DSL" do
|
79
|
+
prompt = TTY::TestPrompt.new
|
80
|
+
prompt.input << " \r"
|
81
|
+
prompt.input.rewind
|
82
|
+
value = prompt.multi_select("Select drinks?") do |menu|
|
83
|
+
menu.choice :vodka, {score: 1}
|
84
|
+
menu.choice :beer, 2
|
85
|
+
menu.choice :wine, 3
|
86
|
+
menu.choices whisky: 4, bourbon: 5
|
87
|
+
end
|
88
|
+
expect(value).to eq([{score: 1}])
|
89
|
+
expect(prompt.output.string).to eq([
|
90
|
+
"\e[?25lSelect drinks? \e[90m(Use arrow keys, press Space to select and Enter to finish)\e[0m\n",
|
91
|
+
"‣ ⬡ vodka\n",
|
92
|
+
" ⬡ beer\n",
|
93
|
+
" ⬡ wine\n",
|
94
|
+
" ⬡ whisky\n",
|
95
|
+
" ⬡ bourbon\n",
|
96
|
+
"\e[1A\e[1000D\e[K" * 6,
|
97
|
+
"Select drinks? vodka\n",
|
98
|
+
"‣ \e[32m⬢\e[0m vodka\n",
|
99
|
+
" ⬡ beer\n",
|
100
|
+
" ⬡ wine\n",
|
101
|
+
" ⬡ whisky\n",
|
102
|
+
" ⬡ bourbon\n",
|
103
|
+
"\e[1A\e[1000D\e[K" * 6,
|
104
|
+
"Select drinks? \e[32mvodka\e[0m\n\e[?25h"
|
105
|
+
].join)
|
106
|
+
end
|
107
|
+
|
108
|
+
it "sets default options through DSL syntax" do
|
109
|
+
prompt = TTY::TestPrompt.new
|
110
|
+
prompt.input << "\r"
|
111
|
+
prompt.input.rewind
|
112
|
+
value = prompt.multi_select("Select drinks?") do |menu|
|
113
|
+
menu.default 2, 5
|
114
|
+
|
115
|
+
menu.choice :vodka, {score: 10}
|
116
|
+
menu.choice :beer, {score: 20}
|
117
|
+
menu.choice :wine, {score: 30}
|
118
|
+
menu.choice :whisky, {score: 40}
|
119
|
+
menu.choice :bourbon, {score: 50}
|
120
|
+
end
|
121
|
+
expect(value).to match_array([{score: 20}, {score: 50}])
|
122
|
+
expect(prompt.output.string).to eq([
|
123
|
+
"\e[?25lSelect drinks? beer, bourbon\n",
|
124
|
+
" ⬡ vodka\n",
|
125
|
+
" \e[32m⬢\e[0m beer\n",
|
126
|
+
" ⬡ wine\n",
|
127
|
+
" ⬡ whisky\n",
|
128
|
+
"‣ \e[32m⬢\e[0m bourbon\n",
|
129
|
+
"\e[1A\e[1000D\e[K" * 6,
|
130
|
+
"Select drinks? \e[32mbeer, bourbon\e[0m\n\e[?25h",
|
131
|
+
].join)
|
132
|
+
end
|
133
|
+
|
134
|
+
it "sets default options through hash syntax" do
|
135
|
+
prompt = TTY::TestPrompt.new
|
136
|
+
prompt.input << "\r"
|
137
|
+
prompt.input.rewind
|
138
|
+
value = prompt.multi_select("Select drinks?",default: [2, 5]) do |menu|
|
139
|
+
menu.choice :vodka, {score: 10}
|
140
|
+
menu.choice :beer, {score: 20}
|
141
|
+
menu.choice :wine, {score: 30}
|
142
|
+
menu.choice :whisky, {score: 40}
|
143
|
+
menu.choice :bourbon, {score: 50}
|
144
|
+
end
|
145
|
+
expect(value).to match_array([{score: 20}, {score: 50}])
|
146
|
+
end
|
147
|
+
|
148
|
+
it "raises error for defaults out of range" do
|
149
|
+
prompt = TTY::TestPrompt.new
|
150
|
+
prompt.input << "\r"
|
151
|
+
prompt.input.rewind
|
152
|
+
expect {
|
153
|
+
prompt.multi_select("Select drinks?",default: [2, 6]) do |menu|
|
154
|
+
menu.choice :vodka, {score: 10}
|
155
|
+
menu.choice :beer, {score: 20}
|
156
|
+
menu.choice :wine, {score: 30}
|
157
|
+
menu.choice :whisky, {score: 40}
|
158
|
+
menu.choice :bourbon, {score: 50}
|
159
|
+
end
|
160
|
+
}.to raise_error(TTY::PromptConfigurationError,
|
161
|
+
/default index `6` out of range \(1 - 5\)/)
|
162
|
+
end
|
163
|
+
end
|
@@ -3,22 +3,11 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
RSpec.describe TTY::Prompt::Question, '#character' do
|
6
|
-
let(:input) { StringIO.new }
|
7
|
-
let(:output) { StringIO.new }
|
8
|
-
let(:prompt) { TTY::Prompt.new(input, output) }
|
9
|
-
|
10
6
|
it 'switches to character input' do
|
11
|
-
|
12
|
-
input
|
13
|
-
|
14
|
-
|
15
|
-
expect(
|
16
|
-
end
|
17
|
-
|
18
|
-
it 'acts as reader without arguments' do
|
19
|
-
input << "abcd"
|
20
|
-
input.rewind
|
21
|
-
q = prompt.ask("Which one do you prefer a, b, c or d?")
|
22
|
-
expect(q.char).to eq(false)
|
7
|
+
prompt = TTY::TestPrompt.new
|
8
|
+
prompt.input << "abcd"
|
9
|
+
prompt.input.rewind
|
10
|
+
answer = prompt.ask("Which one do you prefer a, b, c or d?") { |q| q.char(true) }
|
11
|
+
expect(answer).to eq("abcd")
|
23
12
|
end
|
24
13
|
end
|
@@ -3,23 +3,17 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
RSpec.describe TTY::Prompt::Question, '#default' do
|
6
|
-
let(:input) { StringIO.new }
|
7
|
-
let(:output) { StringIO.new }
|
8
|
-
let(:prompt) { TTY::Prompt.new(input, output) }
|
9
|
-
|
10
6
|
it 'uses default value' do
|
7
|
+
prompt = TTY::TestPrompt.new
|
11
8
|
name = 'Anonymous'
|
12
|
-
|
13
|
-
answer = q.read
|
9
|
+
answer = prompt.ask('What is your name?', default: name)
|
14
10
|
expect(answer).to eq(name)
|
15
11
|
end
|
16
12
|
|
17
13
|
it 'uses default value in block' do
|
14
|
+
prompt = TTY::TestPrompt.new
|
18
15
|
name = 'Anonymous'
|
19
|
-
|
20
|
-
default name
|
21
|
-
end
|
22
|
-
answer = q.read
|
16
|
+
answer = prompt.ask('What is your name?') { |q| q.default(name) }
|
23
17
|
expect(answer).to eq(name)
|
24
18
|
end
|
25
19
|
end
|