thor 0.18.1 → 0.19.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 +7 -0
- data/README.md +13 -7
- data/Thorfile +4 -5
- data/bin/thor +1 -1
- data/lib/thor.rb +78 -67
- data/lib/thor/actions.rb +57 -56
- data/lib/thor/actions/create_file.rb +33 -35
- data/lib/thor/actions/create_link.rb +2 -3
- data/lib/thor/actions/directory.rb +37 -38
- data/lib/thor/actions/empty_directory.rb +67 -69
- data/lib/thor/actions/file_manipulation.rb +17 -15
- data/lib/thor/actions/inject_into_file.rb +27 -29
- data/lib/thor/base.rb +193 -189
- data/lib/thor/command.rb +20 -23
- data/lib/thor/core_ext/hash_with_indifferent_access.rb +21 -24
- data/lib/thor/core_ext/io_binary_read.rb +2 -4
- data/lib/thor/core_ext/ordered_hash.rb +9 -11
- data/lib/thor/error.rb +5 -1
- data/lib/thor/group.rb +53 -54
- data/lib/thor/invocation.rb +44 -38
- data/lib/thor/line_editor.rb +17 -0
- data/lib/thor/line_editor/basic.rb +35 -0
- data/lib/thor/line_editor/readline.rb +88 -0
- data/lib/thor/parser.rb +4 -4
- data/lib/thor/parser/argument.rb +28 -29
- data/lib/thor/parser/arguments.rb +102 -98
- data/lib/thor/parser/option.rb +26 -22
- data/lib/thor/parser/options.rb +86 -86
- data/lib/thor/rake_compat.rb +9 -10
- data/lib/thor/runner.rb +141 -141
- data/lib/thor/shell.rb +27 -34
- data/lib/thor/shell/basic.rb +91 -63
- data/lib/thor/shell/color.rb +44 -43
- data/lib/thor/shell/html.rb +59 -60
- data/lib/thor/util.rb +24 -27
- data/lib/thor/version.rb +1 -1
- data/spec/actions/create_file_spec.rb +25 -27
- data/spec/actions/create_link_spec.rb +19 -18
- data/spec/actions/directory_spec.rb +31 -31
- data/spec/actions/empty_directory_spec.rb +18 -18
- data/spec/actions/file_manipulation_spec.rb +38 -28
- data/spec/actions/inject_into_file_spec.rb +13 -13
- data/spec/actions_spec.rb +43 -43
- data/spec/base_spec.rb +45 -38
- data/spec/command_spec.rb +13 -14
- data/spec/core_ext/hash_with_indifferent_access_spec.rb +19 -19
- data/spec/core_ext/ordered_hash_spec.rb +6 -6
- data/spec/exit_condition_spec.rb +4 -4
- data/spec/fixtures/invoke.thor +19 -0
- data/spec/fixtures/script.thor +1 -1
- data/spec/group_spec.rb +30 -24
- data/spec/helper.rb +28 -15
- data/spec/invocation_spec.rb +39 -19
- data/spec/line_editor/basic_spec.rb +28 -0
- data/spec/line_editor/readline_spec.rb +69 -0
- data/spec/line_editor_spec.rb +43 -0
- data/spec/parser/argument_spec.rb +12 -12
- data/spec/parser/arguments_spec.rb +11 -11
- data/spec/parser/option_spec.rb +33 -25
- data/spec/parser/options_spec.rb +66 -52
- data/spec/quality_spec.rb +75 -0
- data/spec/rake_compat_spec.rb +10 -10
- data/spec/register_spec.rb +60 -30
- data/spec/runner_spec.rb +67 -62
- data/spec/sandbox/application.rb +2 -0
- data/spec/sandbox/app{1}/README +3 -0
- data/spec/sandbox/bundle/execute.rb +6 -0
- data/spec/sandbox/bundle/main.thor +1 -0
- data/spec/sandbox/command.thor +10 -0
- data/spec/sandbox/doc/%file_name%.rb.tt +1 -0
- data/spec/sandbox/doc/COMMENTER +11 -0
- data/spec/sandbox/doc/README +3 -0
- data/spec/sandbox/doc/block_helper.rb +3 -0
- data/spec/sandbox/doc/config.rb +1 -0
- data/spec/sandbox/doc/config.yaml.tt +1 -0
- data/spec/sandbox/doc/excluding/%file_name%.rb.tt +1 -0
- data/spec/sandbox/enum.thor +10 -0
- data/spec/sandbox/group.thor +128 -0
- data/spec/sandbox/invoke.thor +131 -0
- data/spec/sandbox/path with spaces b/data/spec/sandbox/path with → spaces +0 -0
- data/spec/sandbox/preserve/script.sh +3 -0
- data/spec/sandbox/script.thor +220 -0
- data/spec/sandbox/subcommand.thor +17 -0
- data/spec/shell/basic_spec.rb +107 -86
- data/spec/shell/color_spec.rb +32 -8
- data/spec/shell/html_spec.rb +3 -4
- data/spec/shell_spec.rb +7 -7
- data/spec/subcommand_spec.rb +20 -2
- data/spec/thor_spec.rb +111 -97
- data/spec/util_spec.rb +30 -30
- data/thor.gemspec +14 -14
- metadata +69 -25
@@ -0,0 +1,28 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
describe Thor::LineEditor::Basic do
|
4
|
+
describe ".available?" do
|
5
|
+
it "returns true" do
|
6
|
+
expect(Thor::LineEditor::Basic).to be_available
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#readline" do
|
11
|
+
it "uses $stdin and $stdout to get input from the user" do
|
12
|
+
expect($stdout).to receive(:print).with("Enter your name ")
|
13
|
+
expect($stdin).to receive(:gets).and_return("George")
|
14
|
+
expect($stdin).not_to receive(:noecho)
|
15
|
+
editor = Thor::LineEditor::Basic.new("Enter your name ", {})
|
16
|
+
expect(editor.readline).to eq("George")
|
17
|
+
end
|
18
|
+
|
19
|
+
it "disables echo when asked to" do
|
20
|
+
expect($stdout).to receive(:print).with("Password: ")
|
21
|
+
noecho_stdin = double("noecho_stdin")
|
22
|
+
expect(noecho_stdin).to receive(:gets).and_return("secret")
|
23
|
+
expect($stdin).to receive(:noecho).and_yield(noecho_stdin)
|
24
|
+
editor = Thor::LineEditor::Basic.new("Password: ", :echo => false)
|
25
|
+
expect(editor.readline).to eq("secret")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
describe Thor::LineEditor::Readline do
|
4
|
+
before do
|
5
|
+
unless defined? ::Readline
|
6
|
+
::Readline = double("Readline")
|
7
|
+
allow(::Readline).to receive(:completion_append_character=).with(nil)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe ".available?" do
|
12
|
+
it "returns true when ::Readline exists" do
|
13
|
+
allow(Object).to receive(:const_defined?).with(:Readline).and_return(true)
|
14
|
+
expect(described_class).to be_available
|
15
|
+
end
|
16
|
+
|
17
|
+
it "returns false when ::Readline does not exist" do
|
18
|
+
allow(Object).to receive(:const_defined?).with(:Readline).and_return(false)
|
19
|
+
expect(described_class).not_to be_available
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#readline" do
|
24
|
+
it "invokes the readline library" do
|
25
|
+
expect(::Readline).to receive(:readline).with("> ", true).and_return("foo")
|
26
|
+
expect(::Readline).not_to receive(:completion_proc=)
|
27
|
+
editor = Thor::LineEditor::Readline.new("> ", {})
|
28
|
+
expect(editor.readline).to eq("foo")
|
29
|
+
end
|
30
|
+
|
31
|
+
it "supports the add_to_history option" do
|
32
|
+
expect(::Readline).to receive(:readline).with("> ", false).and_return("foo")
|
33
|
+
expect(::Readline).not_to receive(:completion_proc=)
|
34
|
+
editor = Thor::LineEditor::Readline.new("> ", :add_to_history => false)
|
35
|
+
expect(editor.readline).to eq("foo")
|
36
|
+
end
|
37
|
+
|
38
|
+
it "provides tab completion when given a limited_to option" do
|
39
|
+
expect(::Readline).to receive(:readline)
|
40
|
+
expect(::Readline).to receive(:completion_proc=) do |proc|
|
41
|
+
expect(proc.call("")).to eq %w[Apples Chicken Chocolate]
|
42
|
+
expect(proc.call("Ch")).to eq %w[Chicken Chocolate]
|
43
|
+
expect(proc.call("Chi")).to eq ["Chicken"]
|
44
|
+
end
|
45
|
+
|
46
|
+
editor = Thor::LineEditor::Readline.new("Best food: ", :limited_to => %w[Apples Chicken Chocolate])
|
47
|
+
editor.readline
|
48
|
+
end
|
49
|
+
|
50
|
+
it "provides path tab completion when given the path option" do
|
51
|
+
expect(::Readline).to receive(:readline)
|
52
|
+
expect(::Readline).to receive(:completion_proc=) do |proc|
|
53
|
+
expect(proc.call("../line_ed").sort).to eq ["../line_editor/", "../line_editor_spec.rb"].sort
|
54
|
+
end
|
55
|
+
|
56
|
+
editor = Thor::LineEditor::Readline.new("Path to file: ", :path => true)
|
57
|
+
Dir.chdir(File.dirname(__FILE__)) { editor.readline }
|
58
|
+
end
|
59
|
+
|
60
|
+
it "uses STDIN when asked not to echo input" do
|
61
|
+
expect($stdout).to receive(:print).with("Password: ")
|
62
|
+
noecho_stdin = double("noecho_stdin")
|
63
|
+
expect(noecho_stdin).to receive(:gets).and_return("secret")
|
64
|
+
expect($stdin).to receive(:noecho).and_yield(noecho_stdin)
|
65
|
+
editor = Thor::LineEditor::Readline.new("Password: ", :echo => false)
|
66
|
+
expect(editor.readline).to eq("secret")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
describe Thor::LineEditor, "on a system with Readline support" do
|
4
|
+
before do
|
5
|
+
@original_readline = ::Readline if defined? ::Readline
|
6
|
+
silence_warnings { ::Readline = double("Readline") }
|
7
|
+
end
|
8
|
+
|
9
|
+
after do
|
10
|
+
silence_warnings { ::Readline = @original_readline }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe ".readline" do
|
14
|
+
it "uses the Readline line editor" do
|
15
|
+
editor = double("Readline")
|
16
|
+
expect(Thor::LineEditor::Readline).to receive(:new).with("Enter your name ", :default => "Brian").and_return(editor)
|
17
|
+
expect(editor).to receive(:readline).and_return("George")
|
18
|
+
expect(Thor::LineEditor.readline("Enter your name ", :default => "Brian")).to eq("George")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe Thor::LineEditor, "on a system without Readline support" do
|
24
|
+
before do
|
25
|
+
if defined? ::Readline
|
26
|
+
@original_readline = ::Readline
|
27
|
+
Object.send(:remove_const, :Readline)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
after do
|
32
|
+
silence_warnings { ::Readline = @original_readline }
|
33
|
+
end
|
34
|
+
|
35
|
+
describe ".readline" do
|
36
|
+
it "uses the Basic line editor" do
|
37
|
+
editor = double("Basic")
|
38
|
+
expect(Thor::LineEditor::Basic).to receive(:new).with("Enter your name ", :default => "Brian").and_return(editor)
|
39
|
+
expect(editor).to receive(:readline).and_return("George")
|
40
|
+
expect(Thor::LineEditor.readline("Enter your name ", :default => "Brian")).to eq("George")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -1,35 +1,35 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "helper"
|
2
|
+
require "thor/parser"
|
3
3
|
|
4
4
|
describe Thor::Argument do
|
5
5
|
|
6
|
-
def argument(name, options={})
|
6
|
+
def argument(name, options = {})
|
7
7
|
@argument ||= Thor::Argument.new(name, options)
|
8
8
|
end
|
9
9
|
|
10
10
|
describe "errors" do
|
11
11
|
it "raises an error if name is not supplied" do
|
12
|
-
expect
|
12
|
+
expect do
|
13
13
|
argument(nil)
|
14
|
-
|
14
|
+
end.to raise_error(ArgumentError, "Argument name can't be nil.")
|
15
15
|
end
|
16
16
|
|
17
17
|
it "raises an error if type is unknown" do
|
18
|
-
expect
|
18
|
+
expect do
|
19
19
|
argument(:command, :type => :unknown)
|
20
|
-
|
20
|
+
end.to raise_error(ArgumentError, "Type :unknown is not valid for arguments.")
|
21
21
|
end
|
22
22
|
|
23
|
-
it "raises an error if argument is required and
|
24
|
-
expect
|
23
|
+
it "raises an error if argument is required and has default values" do
|
24
|
+
expect do
|
25
25
|
argument(:command, :type => :string, :default => "bar", :required => true)
|
26
|
-
|
26
|
+
end.to raise_error(ArgumentError, "An argument cannot be required and have default value.")
|
27
27
|
end
|
28
28
|
|
29
29
|
it "raises an error if enum isn't an array" do
|
30
|
-
expect
|
30
|
+
expect do
|
31
31
|
argument(:command, :type => :string, :enum => "bar")
|
32
|
-
|
32
|
+
end.to raise_error(ArgumentError, "An argument cannot have an enum other than an array.")
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
@@ -1,14 +1,14 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "helper"
|
2
|
+
require "thor/parser"
|
3
3
|
|
4
4
|
describe Thor::Arguments do
|
5
|
-
def create(opts={})
|
5
|
+
def create(opts = {})
|
6
6
|
arguments = opts.map do |type, default|
|
7
7
|
options = {:required => default.nil?, :type => type, :default => default}
|
8
8
|
Thor::Argument.new(type.to_s, options)
|
9
9
|
end
|
10
10
|
|
11
|
-
arguments.sort!{ |a,b| b.name <=> a.name }
|
11
|
+
arguments.sort! { |a, b| b.name <=> a.name }
|
12
12
|
@opt = Thor::Arguments.new(arguments)
|
13
13
|
end
|
14
14
|
|
@@ -26,14 +26,14 @@ describe Thor::Arguments do
|
|
26
26
|
it "accepts hashes" do
|
27
27
|
create :string => nil, :hash => nil
|
28
28
|
expect(parse("product", "title:string", "age:integer")["string"]).to eq("product")
|
29
|
-
expect(parse("product", "title:string", "age:integer")["hash"]).to eq(
|
30
|
-
expect(parse("product", "url:http://www.amazon.com/gp/product/123")["hash"]).to eq(
|
29
|
+
expect(parse("product", "title:string", "age:integer")["hash"]).to eq("title" => "string", "age" => "integer")
|
30
|
+
expect(parse("product", "url:http://www.amazon.com/gp/product/123")["hash"]).to eq("url" => "http://www.amazon.com/gp/product/123")
|
31
31
|
end
|
32
32
|
|
33
33
|
it "accepts arrays" do
|
34
34
|
create :string => nil, :array => nil
|
35
35
|
expect(parse("product", "title", "age")["string"]).to eq("product")
|
36
|
-
expect(parse("product", "title", "age")["array"]).to eq(%w
|
36
|
+
expect(parse("product", "title", "age")["array"]).to eq(%w[title age])
|
37
37
|
end
|
38
38
|
|
39
39
|
describe "with no inputs" do
|
@@ -44,23 +44,23 @@ describe Thor::Arguments do
|
|
44
44
|
|
45
45
|
it "and required arguments raises an error" do
|
46
46
|
create :string => nil, :numeric => nil
|
47
|
-
expect{ parse }.to raise_error(Thor::RequiredArgumentMissingError, "No value provided for required arguments 'string', 'numeric'")
|
47
|
+
expect { parse }.to raise_error(Thor::RequiredArgumentMissingError, "No value provided for required arguments 'string', 'numeric'")
|
48
48
|
end
|
49
49
|
|
50
50
|
it "and default arguments returns default values" do
|
51
51
|
create :string => "name", :numeric => 13
|
52
|
-
expect(parse).to eq(
|
52
|
+
expect(parse).to eq("string" => "name", "numeric" => 13)
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
56
|
it "returns the input if it's already parsed" do
|
57
57
|
create :string => nil, :hash => nil, :array => nil, :numeric => nil
|
58
|
-
expect(parse("", 0, {}, [])).to eq(
|
58
|
+
expect(parse("", 0, {}, [])).to eq("string" => "", "numeric" => 0, "hash" => {}, "array" => [])
|
59
59
|
end
|
60
60
|
|
61
61
|
it "returns the default value if none is provided" do
|
62
62
|
create :string => "foo", :numeric => 3.0
|
63
|
-
expect(parse("bar")).to eq(
|
63
|
+
expect(parse("bar")).to eq("string" => "bar", "numeric" => 3.0)
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
data/spec/parser/option_spec.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "helper"
|
2
|
+
require "thor/parser"
|
3
3
|
|
4
4
|
describe Thor::Option do
|
5
5
|
def parse(key, value)
|
6
6
|
Thor::Option.parse(key, value)
|
7
7
|
end
|
8
8
|
|
9
|
-
def option(name, options={})
|
9
|
+
def option(name, options = {})
|
10
10
|
@option ||= Thor::Option.new(name, options)
|
11
11
|
end
|
12
12
|
|
@@ -19,9 +19,9 @@ describe Thor::Option do
|
|
19
19
|
expect(parse(:foo, :numeric).type).to eq(:numeric)
|
20
20
|
end
|
21
21
|
|
22
|
-
it "has
|
23
|
-
expect(parse(:foo, :string).default).to
|
24
|
-
expect(parse(:foo, :numeric).default).to
|
22
|
+
it "has no default value" do
|
23
|
+
expect(parse(:foo, :string).default).to be nil
|
24
|
+
expect(parse(:foo, :numeric).default).to be nil
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
@@ -31,17 +31,17 @@ describe Thor::Option do
|
|
31
31
|
end
|
32
32
|
|
33
33
|
it "has no default value" do
|
34
|
-
expect(parse(:foo, :required).default).to
|
34
|
+
expect(parse(:foo, :required).default).to be nil
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
describe "and symbol is not a reserved key" do
|
39
|
-
it "has type
|
39
|
+
it "has type equal to :string" do
|
40
40
|
expect(parse(:foo, :bar).type).to eq(:string)
|
41
41
|
end
|
42
42
|
|
43
43
|
it "has no default value" do
|
44
|
-
expect(parse(:foo, :bar).default).to
|
44
|
+
expect(parse(:foo, :bar).default).to be nil
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
@@ -51,8 +51,8 @@ describe Thor::Option do
|
|
51
51
|
expect(parse(:foo, :a => :b).type).to eq(:hash)
|
52
52
|
end
|
53
53
|
|
54
|
-
it "has default value
|
55
|
-
expect(parse(:foo, :a => :b).default).to eq(
|
54
|
+
it "has default value equal to the hash" do
|
55
|
+
expect(parse(:foo, :a => :b).default).to eq(:a => :b)
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
@@ -61,7 +61,7 @@ describe Thor::Option do
|
|
61
61
|
expect(parse(:foo, [:a, :b]).type).to eq(:array)
|
62
62
|
end
|
63
63
|
|
64
|
-
it "has default value
|
64
|
+
it "has default value equal to the array" do
|
65
65
|
expect(parse(:foo, [:a, :b]).default).to eq([:a, :b])
|
66
66
|
end
|
67
67
|
end
|
@@ -71,7 +71,7 @@ describe Thor::Option do
|
|
71
71
|
expect(parse(:foo, "bar").type).to eq(:string)
|
72
72
|
end
|
73
73
|
|
74
|
-
it "has default value
|
74
|
+
it "has default value equal to the string" do
|
75
75
|
expect(parse(:foo, "bar").default).to eq("bar")
|
76
76
|
end
|
77
77
|
end
|
@@ -81,7 +81,7 @@ describe Thor::Option do
|
|
81
81
|
expect(parse(:foo, 2.0).type).to eq(:numeric)
|
82
82
|
end
|
83
83
|
|
84
|
-
it "has default value
|
84
|
+
it "has default value equal to the numeric" do
|
85
85
|
expect(parse(:foo, 2.0).default).to eq(2.0)
|
86
86
|
end
|
87
87
|
end
|
@@ -92,14 +92,14 @@ describe Thor::Option do
|
|
92
92
|
expect(parse(:foo, false).type).to eq(:boolean)
|
93
93
|
end
|
94
94
|
|
95
|
-
it "has default value
|
95
|
+
it "has default value equal to the boolean" do
|
96
96
|
expect(parse(:foo, true).default).to eq(true)
|
97
97
|
expect(parse(:foo, false).default).to eq(false)
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
101
101
|
describe "with key as a symbol" do
|
102
|
-
it "sets the name
|
102
|
+
it "sets the name equal to the key" do
|
103
103
|
expect(parse(:foo, true).name).to eq("foo")
|
104
104
|
end
|
105
105
|
end
|
@@ -135,10 +135,10 @@ describe Thor::Option do
|
|
135
135
|
expect(option).to be_required
|
136
136
|
end
|
137
137
|
|
138
|
-
it "cannot be required
|
139
|
-
expect
|
138
|
+
it "boolean options cannot be required" do
|
139
|
+
expect do
|
140
140
|
option("foo", :required => true, :type => :boolean)
|
141
|
-
|
141
|
+
end.to raise_error(ArgumentError, "An option cannot be boolean and required.")
|
142
142
|
end
|
143
143
|
|
144
144
|
it "allows type predicates" do
|
@@ -148,9 +148,9 @@ describe Thor::Option do
|
|
148
148
|
end
|
149
149
|
|
150
150
|
it "raises an error on method missing" do
|
151
|
-
expect
|
151
|
+
expect do
|
152
152
|
parse(:foo, :string).unknown?
|
153
|
-
|
153
|
+
end.to raise_error(NoMethodError)
|
154
154
|
end
|
155
155
|
|
156
156
|
describe "#usage" do
|
@@ -172,18 +172,22 @@ describe Thor::Option do
|
|
172
172
|
end
|
173
173
|
|
174
174
|
it "returns usage for boolean types" do
|
175
|
-
expect(parse(:foo, :boolean).usage).to eq("[--foo]")
|
175
|
+
expect(parse(:foo, :boolean).usage).to eq("[--foo], [--no-foo]")
|
176
|
+
end
|
177
|
+
|
178
|
+
it "does not use padding when no aliases are given" do
|
179
|
+
expect(parse(:foo, :boolean).usage).to eq("[--foo], [--no-foo]")
|
176
180
|
end
|
177
181
|
|
178
|
-
it "
|
179
|
-
expect(parse(:foo, :boolean).usage
|
182
|
+
it "documents a negative option when boolean" do
|
183
|
+
expect(parse(:foo, :boolean).usage).to include("[--no-foo]")
|
180
184
|
end
|
181
185
|
|
182
186
|
it "uses banner when supplied" do
|
183
187
|
expect(option(:foo, :required => false, :type => :string, :banner => "BAR").usage).to eq("[--foo=BAR]")
|
184
188
|
end
|
185
189
|
|
186
|
-
it "
|
190
|
+
it "checks when banner is an empty string" do
|
187
191
|
expect(option(:foo, :required => false, :type => :string, :banner => "").usage).to eq("[--foo]")
|
188
192
|
end
|
189
193
|
|
@@ -197,6 +201,10 @@ describe Thor::Option do
|
|
197
201
|
it "does not show the usage between brackets" do
|
198
202
|
expect(parse([:foo, "-f", "-b"], :required).usage).to eq("-f, -b, --foo=FOO")
|
199
203
|
end
|
204
|
+
|
205
|
+
it "does not negate the aliases" do
|
206
|
+
expect(parse([:foo, "-f", "-b"], :boolean).usage).to eq("-f, -b, [--foo], [--no-foo]")
|
207
|
+
end
|
200
208
|
end
|
201
209
|
end
|
202
210
|
end
|
data/spec/parser/options_spec.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "helper"
|
2
|
+
require "thor/parser"
|
3
3
|
|
4
4
|
describe Thor::Options do
|
5
|
-
def create(opts, defaults={}, stop_on_unknown=false)
|
5
|
+
def create(opts, defaults = {}, stop_on_unknown = false)
|
6
6
|
opts.each do |key, value|
|
7
7
|
opts[key] = Thor::Option.parse(key, value) unless value.is_a?(Thor::Option)
|
8
8
|
end
|
@@ -40,12 +40,12 @@ describe Thor::Options do
|
|
40
40
|
end
|
41
41
|
|
42
42
|
it "joins several values" do
|
43
|
-
switches = Thor::Options.to_switches(:color => true, :foo => "bar").split(
|
44
|
-
expect(switches).to eq([
|
43
|
+
switches = Thor::Options.to_switches(:color => true, :foo => "bar").split(" ").sort
|
44
|
+
expect(switches).to eq(%w["bar" --color --foo])
|
45
45
|
end
|
46
46
|
|
47
47
|
it "accepts arrays" do
|
48
|
-
expect(Thor::Options.to_switches(:count => [1,2,3])).to eq("--count 1 2 3")
|
48
|
+
expect(Thor::Options.to_switches(:count => [1, 2, 3])).to eq("--count 1 2 3")
|
49
49
|
end
|
50
50
|
|
51
51
|
it "accepts hashes" do
|
@@ -60,7 +60,7 @@ describe Thor::Options do
|
|
60
60
|
|
61
61
|
describe "#parse" do
|
62
62
|
it "allows multiple aliases for a given switch" do
|
63
|
-
create [
|
63
|
+
create %w[--foo --bar --baz] => :string
|
64
64
|
expect(parse("--foo", "12")["foo"]).to eq("12")
|
65
65
|
expect(parse("--bar", "12")["foo"]).to eq("12")
|
66
66
|
expect(parse("--baz", "12")["foo"]).to eq("12")
|
@@ -68,27 +68,27 @@ describe Thor::Options do
|
|
68
68
|
|
69
69
|
it "allows custom short names" do
|
70
70
|
create "-f" => :string
|
71
|
-
expect(parse("-f", "12")).to eq(
|
71
|
+
expect(parse("-f", "12")).to eq("f" => "12")
|
72
72
|
end
|
73
73
|
|
74
74
|
it "allows custom short-name aliases" do
|
75
|
-
create [
|
76
|
-
expect(parse("-f", "12")).to eq(
|
75
|
+
create %w[--bar -f] => :string
|
76
|
+
expect(parse("-f", "12")).to eq("bar" => "12")
|
77
77
|
end
|
78
78
|
|
79
79
|
it "accepts conjoined short switches" do
|
80
|
-
create [
|
80
|
+
create %w[--foo -f] => true, %w[--bar -b] => true, %w[--app -a] => true
|
81
81
|
opts = parse("-fba")
|
82
|
-
expect(opts["foo"]).to
|
83
|
-
expect(opts["bar"]).to
|
84
|
-
expect(opts["app"]).to
|
82
|
+
expect(opts["foo"]).to be true
|
83
|
+
expect(opts["bar"]).to be true
|
84
|
+
expect(opts["app"]).to be true
|
85
85
|
end
|
86
86
|
|
87
87
|
it "accepts conjoined short switches with input" do
|
88
|
-
create [
|
88
|
+
create %w[--foo -f] => true, %w[--bar -b] => true, %w[--app -a] => :required
|
89
89
|
opts = parse "-fba", "12"
|
90
|
-
expect(opts["foo"]).to
|
91
|
-
expect(opts["bar"]).to
|
90
|
+
expect(opts["foo"]).to be true
|
91
|
+
expect(opts["bar"]).to be true
|
92
92
|
expect(opts["app"]).to eq("12")
|
93
93
|
end
|
94
94
|
|
@@ -110,18 +110,18 @@ describe Thor::Options do
|
|
110
110
|
it "raises an error for unknown switches" do
|
111
111
|
create :foo => "baz", :bar => :required
|
112
112
|
parse("--bar", "baz", "--baz", "unknown")
|
113
|
-
expect{ check_unknown! }.to raise_error(Thor::UnknownArgumentError, "Unknown switches '--baz'")
|
113
|
+
expect { check_unknown! }.to raise_error(Thor::UnknownArgumentError, "Unknown switches '--baz'")
|
114
114
|
end
|
115
115
|
|
116
116
|
it "skips leading non-switches" do
|
117
117
|
create(:foo => "baz")
|
118
118
|
|
119
|
-
expect(parse("asdf", "--foo", "bar")).to eq(
|
119
|
+
expect(parse("asdf", "--foo", "bar")).to eq("foo" => "bar")
|
120
120
|
end
|
121
121
|
|
122
122
|
it "correctly recognizes things that look kind of like options, but aren't, as not options" do
|
123
123
|
create(:foo => "baz")
|
124
|
-
expect(parse("--asdf---asdf", "baz", "--foo", "--asdf---dsf--asdf")).to eq(
|
124
|
+
expect(parse("--asdf---asdf", "baz", "--foo", "--asdf---dsf--asdf")).to eq("foo" => "--asdf---dsf--asdf")
|
125
125
|
check_unknown!
|
126
126
|
end
|
127
127
|
|
@@ -139,31 +139,31 @@ describe Thor::Options do
|
|
139
139
|
|
140
140
|
it "interprets everything after -- as args instead of options" do
|
141
141
|
create(:foo => :string, :bar => :required)
|
142
|
-
expect(parse(%w[--bar abc moo -- --foo def -a])).to eq(
|
142
|
+
expect(parse(%w[--bar abc moo -- --foo def -a])).to eq("bar" => "abc")
|
143
143
|
expect(remaining).to eq(%w[moo --foo def -a])
|
144
144
|
end
|
145
145
|
|
146
146
|
it "ignores -- when looking for single option values" do
|
147
147
|
create(:foo => :string, :bar => :required)
|
148
|
-
expect(parse(%w[--bar -- --foo def -a])).to eq(
|
148
|
+
expect(parse(%w[--bar -- --foo def -a])).to eq("bar" => "--foo")
|
149
149
|
expect(remaining).to eq(%w[def -a])
|
150
150
|
end
|
151
151
|
|
152
152
|
it "ignores -- when looking for array option values" do
|
153
153
|
create(:foo => :array)
|
154
|
-
expect(parse(%w[--foo a b -- c d -e])).to eq(
|
154
|
+
expect(parse(%w[--foo a b -- c d -e])).to eq("foo" => %w[a b c d -e])
|
155
155
|
expect(remaining).to eq([])
|
156
156
|
end
|
157
157
|
|
158
158
|
it "ignores -- when looking for hash option values" do
|
159
159
|
create(:foo => :hash)
|
160
|
-
expect(parse(%w[--foo a:b -- c:d -e])).to eq(
|
160
|
+
expect(parse(%w[--foo a:b -- c:d -e])).to eq("foo" => {"a" => "b", "c" => "d"})
|
161
161
|
expect(remaining).to eq(%w[-e])
|
162
162
|
end
|
163
163
|
|
164
164
|
it "ignores trailing --" do
|
165
165
|
create(:foo => :string)
|
166
|
-
expect(parse(%w[--foo --])).to eq(
|
166
|
+
expect(parse(%w[--foo --])).to eq("foo" => nil)
|
167
167
|
expect(remaining).to eq([])
|
168
168
|
end
|
169
169
|
|
@@ -180,7 +180,7 @@ describe Thor::Options do
|
|
180
180
|
|
181
181
|
it "and a required switch raises an error" do
|
182
182
|
create "--foo" => :required
|
183
|
-
expect{ parse }.to raise_error(Thor::RequiredArgumentMissingError, "No value provided for required options '--foo'")
|
183
|
+
expect { parse }.to raise_error(Thor::RequiredArgumentMissingError, "No value provided for required options '--foo'")
|
184
184
|
end
|
185
185
|
end
|
186
186
|
|
@@ -190,21 +190,21 @@ describe Thor::Options do
|
|
190
190
|
end
|
191
191
|
|
192
192
|
it "raises an error if the required switch has no argument" do
|
193
|
-
expect{ parse("--foo") }.to raise_error(Thor::MalformattedArgumentError)
|
193
|
+
expect { parse("--foo") }.to raise_error(Thor::MalformattedArgumentError)
|
194
194
|
end
|
195
195
|
|
196
196
|
it "raises an error if the required switch isn't given" do
|
197
|
-
expect{ parse("--bar") }.to raise_error(Thor::RequiredArgumentMissingError)
|
197
|
+
expect { parse("--bar") }.to raise_error(Thor::RequiredArgumentMissingError)
|
198
198
|
end
|
199
199
|
|
200
200
|
it "raises an error if the required switch is set to nil" do
|
201
|
-
expect{ parse("--no-foo") }.to raise_error(Thor::RequiredArgumentMissingError)
|
201
|
+
expect { parse("--no-foo") }.to raise_error(Thor::RequiredArgumentMissingError)
|
202
202
|
end
|
203
203
|
|
204
204
|
it "does not raises an error if the required option has a default value" do
|
205
205
|
options = {:required => true, :type => :string, :default => "baz"}
|
206
206
|
create :foo => Thor::Option.new("foo", options), :bar => :boolean
|
207
|
-
expect{ parse("--bar") }.not_to raise_error
|
207
|
+
expect { parse("--bar") }.not_to raise_error
|
208
208
|
end
|
209
209
|
end
|
210
210
|
|
@@ -215,38 +215,38 @@ describe Thor::Options do
|
|
215
215
|
|
216
216
|
it "stops parsing on first non-option" do
|
217
217
|
expect(parse(%w[foo --verbose])).to eq({})
|
218
|
-
expect(remaining).to eq([
|
218
|
+
expect(remaining).to eq(%w[foo --verbose])
|
219
219
|
end
|
220
220
|
|
221
221
|
it "stops parsing on unknown option" do
|
222
222
|
expect(parse(%w[--bar --verbose])).to eq({})
|
223
|
-
expect(remaining).to eq([
|
223
|
+
expect(remaining).to eq(%w[--bar --verbose])
|
224
224
|
end
|
225
225
|
|
226
226
|
it "retains -- after it has stopped parsing" do
|
227
227
|
expect(parse(%w[--bar -- whatever])).to eq({})
|
228
|
-
expect(remaining).to eq([
|
228
|
+
expect(remaining).to eq(%w[--bar -- whatever])
|
229
229
|
end
|
230
230
|
|
231
231
|
it "still accepts options that are given before non-options" do
|
232
|
-
expect(parse(%w[--verbose foo])).to eq(
|
233
|
-
expect(remaining).to eq([
|
232
|
+
expect(parse(%w[--verbose foo])).to eq("verbose" => true)
|
233
|
+
expect(remaining).to eq(%w[foo])
|
234
234
|
end
|
235
235
|
|
236
236
|
it "still accepts options that require a value" do
|
237
|
-
expect(parse(%w[--foo bar baz])).to eq(
|
238
|
-
expect(remaining).to eq([
|
237
|
+
expect(parse(%w[--foo bar baz])).to eq("foo" => "bar")
|
238
|
+
expect(remaining).to eq(%w[baz])
|
239
239
|
end
|
240
240
|
|
241
241
|
it "still interprets everything after -- as args instead of options" do
|
242
242
|
expect(parse(%w[-- --verbose])).to eq({})
|
243
|
-
expect(remaining).to eq([
|
243
|
+
expect(remaining).to eq(%w[--verbose])
|
244
244
|
end
|
245
245
|
end
|
246
246
|
|
247
247
|
describe "with :string type" do
|
248
248
|
before do
|
249
|
-
create [
|
249
|
+
create %w[--foo -f] => :required
|
250
250
|
end
|
251
251
|
|
252
252
|
it "accepts a switch <value> assignment" do
|
@@ -266,12 +266,12 @@ describe Thor::Options do
|
|
266
266
|
|
267
267
|
it "accepts a --no-switch format" do
|
268
268
|
create "--foo" => "bar"
|
269
|
-
expect(parse("--no-foo")["foo"]).to
|
269
|
+
expect(parse("--no-foo")["foo"]).to be nil
|
270
270
|
end
|
271
271
|
|
272
272
|
it "does not consume an argument for --no-switch format" do
|
273
273
|
create "--cheese" => :string
|
274
|
-
expect(parse(
|
274
|
+
expect(parse("burger", "--no-cheese", "fries")["cheese"]).to be nil
|
275
275
|
end
|
276
276
|
|
277
277
|
it "accepts a --switch format on non required types" do
|
@@ -288,6 +288,13 @@ describe Thor::Options do
|
|
288
288
|
expect(parse("--foo=bar", "--foo", "12")["foo"]).to eq("12")
|
289
289
|
expect(parse("--foo", "12", "--foo", "13")["foo"]).to eq("13")
|
290
290
|
end
|
291
|
+
|
292
|
+
it "raises error when value isn't in enum" do
|
293
|
+
enum = %w[apple banana]
|
294
|
+
create :fruit => Thor::Option.new("fruit", :type => :string, :enum => enum)
|
295
|
+
expect { parse("--fruit", "orange") }.to raise_error(Thor::MalformattedArgumentError,
|
296
|
+
"Expected '--fruit' to be one of #{enum.join(', ')}; got orange")
|
297
|
+
end
|
291
298
|
end
|
292
299
|
|
293
300
|
describe "with :boolean type" do
|
@@ -336,8 +343,8 @@ describe Thor::Options do
|
|
336
343
|
|
337
344
|
it "doesn't eat the next part of the param" do
|
338
345
|
create :foo => :boolean
|
339
|
-
expect(parse("--foo", "bar")).to eq(
|
340
|
-
expect(@opt.remaining).to eq([
|
346
|
+
expect(parse("--foo", "bar")).to eq("foo" => true)
|
347
|
+
expect(@opt.remaining).to eq(%w[bar])
|
341
348
|
end
|
342
349
|
end
|
343
350
|
|
@@ -347,15 +354,15 @@ describe Thor::Options do
|
|
347
354
|
end
|
348
355
|
|
349
356
|
it "accepts a switch=<value> assignment" do
|
350
|
-
expect(parse("--attributes=name:string", "age:integer")["attributes"]).to eq(
|
357
|
+
expect(parse("--attributes=name:string", "age:integer")["attributes"]).to eq("name" => "string", "age" => "integer")
|
351
358
|
end
|
352
359
|
|
353
360
|
it "accepts a switch <value> assignment" do
|
354
|
-
expect(parse("--attributes", "name:string", "age:integer")["attributes"]).to eq(
|
361
|
+
expect(parse("--attributes", "name:string", "age:integer")["attributes"]).to eq("name" => "string", "age" => "integer")
|
355
362
|
end
|
356
363
|
|
357
364
|
it "must not mix values with other switches" do
|
358
|
-
expect(parse("--attributes", "name:string", "age:integer", "--baz", "cool")["attributes"]).to eq(
|
365
|
+
expect(parse("--attributes", "name:string", "age:integer", "--baz", "cool")["attributes"]).to eq("name" => "string", "age" => "integer")
|
359
366
|
end
|
360
367
|
end
|
361
368
|
|
@@ -365,15 +372,15 @@ describe Thor::Options do
|
|
365
372
|
end
|
366
373
|
|
367
374
|
it "accepts a switch=<value> assignment" do
|
368
|
-
expect(parse("--attributes=a", "b", "c")["attributes"]).to eq([
|
375
|
+
expect(parse("--attributes=a", "b", "c")["attributes"]).to eq(%w[a b c])
|
369
376
|
end
|
370
377
|
|
371
378
|
it "accepts a switch <value> assignment" do
|
372
|
-
expect(parse("--attributes", "a", "b", "c")["attributes"]).to eq([
|
379
|
+
expect(parse("--attributes", "a", "b", "c")["attributes"]).to eq(%w[a b c])
|
373
380
|
end
|
374
381
|
|
375
382
|
it "must not mix values with other switches" do
|
376
|
-
expect(parse("--attributes", "a", "b", "c", "--baz", "cool")["attributes"]).to eq([
|
383
|
+
expect(parse("--attributes", "a", "b", "c", "--baz", "cool")["attributes"]).to eq(%w[a b c])
|
377
384
|
end
|
378
385
|
end
|
379
386
|
|
@@ -387,12 +394,19 @@ describe Thor::Options do
|
|
387
394
|
end
|
388
395
|
|
389
396
|
it "converts values to numeric types" do
|
390
|
-
expect(parse("-n", "3", "-m", ".5")).to eq(
|
397
|
+
expect(parse("-n", "3", "-m", ".5")).to eq("n" => 3, "m" => 0.5)
|
391
398
|
end
|
392
399
|
|
393
400
|
it "raises error when value isn't numeric" do
|
394
|
-
expect{ parse("-n", "foo") }.to raise_error(Thor::MalformattedArgumentError,
|
395
|
-
|
401
|
+
expect { parse("-n", "foo") }.to raise_error(Thor::MalformattedArgumentError,
|
402
|
+
"Expected numeric value for '-n'; got \"foo\"")
|
403
|
+
end
|
404
|
+
|
405
|
+
it "raises error when value isn't in enum" do
|
406
|
+
enum = [1, 2]
|
407
|
+
create :limit => Thor::Option.new("limit", :type => :numeric, :enum => enum)
|
408
|
+
expect { parse("--limit", "3") }.to raise_error(Thor::MalformattedArgumentError,
|
409
|
+
"Expected '--limit' to be one of #{enum.join(', ')}; got 3")
|
396
410
|
end
|
397
411
|
end
|
398
412
|
|