tty-prompt 0.1.0 → 0.2.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/.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
|