thor 0.19.1 → 0.19.2
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 +24 -0
- data/CONTRIBUTING.md +15 -0
- data/README.md +7 -1
- data/lib/thor.rb +31 -23
- data/lib/thor/actions.rb +21 -22
- data/lib/thor/actions/create_file.rb +1 -1
- data/lib/thor/actions/create_link.rb +1 -1
- data/lib/thor/actions/directory.rb +2 -2
- data/lib/thor/actions/empty_directory.rb +8 -8
- data/lib/thor/actions/file_manipulation.rb +23 -12
- data/lib/thor/actions/inject_into_file.rb +10 -14
- data/lib/thor/base.rb +33 -33
- data/lib/thor/command.rb +9 -9
- data/lib/thor/core_ext/hash_with_indifferent_access.rb +9 -1
- data/lib/thor/core_ext/io_binary_read.rb +7 -5
- data/lib/thor/core_ext/ordered_hash.rb +94 -63
- data/lib/thor/error.rb +3 -3
- data/lib/thor/group.rb +12 -12
- data/lib/thor/invocation.rb +4 -5
- data/lib/thor/parser/argument.rb +4 -7
- data/lib/thor/parser/arguments.rb +16 -16
- data/lib/thor/parser/option.rb +39 -19
- data/lib/thor/parser/options.rb +7 -5
- data/lib/thor/runner.rb +25 -25
- data/lib/thor/shell.rb +1 -1
- data/lib/thor/shell/basic.rb +41 -26
- data/lib/thor/shell/color.rb +1 -1
- data/lib/thor/shell/html.rb +4 -4
- data/lib/thor/util.rb +8 -7
- data/lib/thor/version.rb +1 -1
- data/thor.gemspec +6 -9
- metadata +6 -148
- data/Thorfile +0 -29
- data/spec/actions/create_file_spec.rb +0 -168
- data/spec/actions/create_link_spec.rb +0 -96
- data/spec/actions/directory_spec.rb +0 -169
- data/spec/actions/empty_directory_spec.rb +0 -129
- data/spec/actions/file_manipulation_spec.rb +0 -392
- data/spec/actions/inject_into_file_spec.rb +0 -135
- data/spec/actions_spec.rb +0 -331
- data/spec/base_spec.rb +0 -298
- data/spec/command_spec.rb +0 -79
- data/spec/core_ext/hash_with_indifferent_access_spec.rb +0 -48
- data/spec/core_ext/ordered_hash_spec.rb +0 -115
- data/spec/exit_condition_spec.rb +0 -19
- data/spec/fixtures/application.rb +0 -2
- data/spec/fixtures/app{1}/README +0 -3
- data/spec/fixtures/bundle/execute.rb +0 -6
- data/spec/fixtures/bundle/main.thor +0 -1
- data/spec/fixtures/command.thor +0 -10
- data/spec/fixtures/doc/%file_name%.rb.tt +0 -1
- data/spec/fixtures/doc/COMMENTER +0 -11
- data/spec/fixtures/doc/README +0 -3
- data/spec/fixtures/doc/block_helper.rb +0 -3
- data/spec/fixtures/doc/config.rb +0 -1
- data/spec/fixtures/doc/config.yaml.tt +0 -1
- data/spec/fixtures/doc/excluding/%file_name%.rb.tt +0 -1
- data/spec/fixtures/enum.thor +0 -10
- data/spec/fixtures/group.thor +0 -128
- data/spec/fixtures/invoke.thor +0 -131
- data/spec/fixtures/path with spaces b/data/spec/fixtures/path with → spaces +0 -0
- data/spec/fixtures/preserve/script.sh +0 -3
- data/spec/fixtures/script.thor +0 -220
- data/spec/fixtures/subcommand.thor +0 -17
- data/spec/group_spec.rb +0 -222
- data/spec/helper.rb +0 -80
- data/spec/invocation_spec.rb +0 -120
- data/spec/line_editor/basic_spec.rb +0 -28
- data/spec/line_editor/readline_spec.rb +0 -69
- data/spec/line_editor_spec.rb +0 -43
- data/spec/parser/argument_spec.rb +0 -53
- data/spec/parser/arguments_spec.rb +0 -66
- data/spec/parser/option_spec.rb +0 -210
- data/spec/parser/options_spec.rb +0 -414
- data/spec/quality_spec.rb +0 -75
- data/spec/rake_compat_spec.rb +0 -72
- data/spec/register_spec.rb +0 -227
- data/spec/runner_spec.rb +0 -246
- data/spec/sandbox/application.rb +0 -2
- data/spec/sandbox/app{1}/README +0 -3
- data/spec/sandbox/bundle/execute.rb +0 -6
- data/spec/sandbox/bundle/main.thor +0 -1
- data/spec/sandbox/command.thor +0 -10
- data/spec/sandbox/doc/%file_name%.rb.tt +0 -1
- data/spec/sandbox/doc/COMMENTER +0 -11
- data/spec/sandbox/doc/README +0 -3
- data/spec/sandbox/doc/block_helper.rb +0 -3
- data/spec/sandbox/doc/config.rb +0 -1
- data/spec/sandbox/doc/config.yaml.tt +0 -1
- data/spec/sandbox/doc/excluding/%file_name%.rb.tt +0 -1
- data/spec/sandbox/enum.thor +0 -10
- data/spec/sandbox/group.thor +0 -128
- data/spec/sandbox/invoke.thor +0 -131
- data/spec/sandbox/path with spaces b/data/spec/sandbox/path with → spaces +0 -0
- data/spec/sandbox/preserve/script.sh +0 -3
- data/spec/sandbox/script.thor +0 -220
- data/spec/sandbox/subcommand.thor +0 -17
- data/spec/shell/basic_spec.rb +0 -337
- data/spec/shell/color_spec.rb +0 -119
- data/spec/shell/html_spec.rb +0 -31
- data/spec/shell_spec.rb +0 -47
- data/spec/subcommand_spec.rb +0 -48
- data/spec/thor_spec.rb +0 -505
- data/spec/util_spec.rb +0 -196
@@ -1,69 +0,0 @@
|
|
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
|
data/spec/line_editor_spec.rb
DELETED
@@ -1,43 +0,0 @@
|
|
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,53 +0,0 @@
|
|
1
|
-
require "helper"
|
2
|
-
require "thor/parser"
|
3
|
-
|
4
|
-
describe Thor::Argument do
|
5
|
-
|
6
|
-
def argument(name, options = {})
|
7
|
-
@argument ||= Thor::Argument.new(name, options)
|
8
|
-
end
|
9
|
-
|
10
|
-
describe "errors" do
|
11
|
-
it "raises an error if name is not supplied" do
|
12
|
-
expect do
|
13
|
-
argument(nil)
|
14
|
-
end.to raise_error(ArgumentError, "Argument name can't be nil.")
|
15
|
-
end
|
16
|
-
|
17
|
-
it "raises an error if type is unknown" do
|
18
|
-
expect do
|
19
|
-
argument(:command, :type => :unknown)
|
20
|
-
end.to raise_error(ArgumentError, "Type :unknown is not valid for arguments.")
|
21
|
-
end
|
22
|
-
|
23
|
-
it "raises an error if argument is required and has default values" do
|
24
|
-
expect do
|
25
|
-
argument(:command, :type => :string, :default => "bar", :required => true)
|
26
|
-
end.to raise_error(ArgumentError, "An argument cannot be required and have default value.")
|
27
|
-
end
|
28
|
-
|
29
|
-
it "raises an error if enum isn't an array" do
|
30
|
-
expect do
|
31
|
-
argument(:command, :type => :string, :enum => "bar")
|
32
|
-
end.to raise_error(ArgumentError, "An argument cannot have an enum other than an array.")
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
describe "#usage" do
|
37
|
-
it "returns usage for string types" do
|
38
|
-
expect(argument(:foo, :type => :string).usage).to eq("FOO")
|
39
|
-
end
|
40
|
-
|
41
|
-
it "returns usage for numeric types" do
|
42
|
-
expect(argument(:foo, :type => :numeric).usage).to eq("N")
|
43
|
-
end
|
44
|
-
|
45
|
-
it "returns usage for array types" do
|
46
|
-
expect(argument(:foo, :type => :array).usage).to eq("one two three")
|
47
|
-
end
|
48
|
-
|
49
|
-
it "returns usage for hash types" do
|
50
|
-
expect(argument(:foo, :type => :hash).usage).to eq("key:value")
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
require "helper"
|
2
|
-
require "thor/parser"
|
3
|
-
|
4
|
-
describe Thor::Arguments do
|
5
|
-
def create(opts = {})
|
6
|
-
arguments = opts.map do |type, default|
|
7
|
-
options = {:required => default.nil?, :type => type, :default => default}
|
8
|
-
Thor::Argument.new(type.to_s, options)
|
9
|
-
end
|
10
|
-
|
11
|
-
arguments.sort! { |a, b| b.name <=> a.name }
|
12
|
-
@opt = Thor::Arguments.new(arguments)
|
13
|
-
end
|
14
|
-
|
15
|
-
def parse(*args)
|
16
|
-
@opt.parse(args)
|
17
|
-
end
|
18
|
-
|
19
|
-
describe "#parse" do
|
20
|
-
it "parses arguments in the given order" do
|
21
|
-
create :string => nil, :numeric => nil
|
22
|
-
expect(parse("name", "13")["string"]).to eq("name")
|
23
|
-
expect(parse("name", "13")["numeric"]).to eq(13)
|
24
|
-
end
|
25
|
-
|
26
|
-
it "accepts hashes" do
|
27
|
-
create :string => nil, :hash => nil
|
28
|
-
expect(parse("product", "title:string", "age:integer")["string"]).to eq("product")
|
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
|
-
end
|
32
|
-
|
33
|
-
it "accepts arrays" do
|
34
|
-
create :string => nil, :array => nil
|
35
|
-
expect(parse("product", "title", "age")["string"]).to eq("product")
|
36
|
-
expect(parse("product", "title", "age")["array"]).to eq(%w[title age])
|
37
|
-
end
|
38
|
-
|
39
|
-
describe "with no inputs" do
|
40
|
-
it "and no arguments returns an empty hash" do
|
41
|
-
create
|
42
|
-
expect(parse).to eq({})
|
43
|
-
end
|
44
|
-
|
45
|
-
it "and required arguments raises an error" do
|
46
|
-
create :string => nil, :numeric => nil
|
47
|
-
expect { parse }.to raise_error(Thor::RequiredArgumentMissingError, "No value provided for required arguments 'string', 'numeric'")
|
48
|
-
end
|
49
|
-
|
50
|
-
it "and default arguments returns default values" do
|
51
|
-
create :string => "name", :numeric => 13
|
52
|
-
expect(parse).to eq("string" => "name", "numeric" => 13)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
it "returns the input if it's already parsed" do
|
57
|
-
create :string => nil, :hash => nil, :array => nil, :numeric => nil
|
58
|
-
expect(parse("", 0, {}, [])).to eq("string" => "", "numeric" => 0, "hash" => {}, "array" => [])
|
59
|
-
end
|
60
|
-
|
61
|
-
it "returns the default value if none is provided" do
|
62
|
-
create :string => "foo", :numeric => 3.0
|
63
|
-
expect(parse("bar")).to eq("string" => "bar", "numeric" => 3.0)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
data/spec/parser/option_spec.rb
DELETED
@@ -1,210 +0,0 @@
|
|
1
|
-
require "helper"
|
2
|
-
require "thor/parser"
|
3
|
-
|
4
|
-
describe Thor::Option do
|
5
|
-
def parse(key, value)
|
6
|
-
Thor::Option.parse(key, value)
|
7
|
-
end
|
8
|
-
|
9
|
-
def option(name, options = {})
|
10
|
-
@option ||= Thor::Option.new(name, options)
|
11
|
-
end
|
12
|
-
|
13
|
-
describe "#parse" do
|
14
|
-
|
15
|
-
describe "with value as a symbol" do
|
16
|
-
describe "and symbol is a valid type" do
|
17
|
-
it "has type equals to the symbol" do
|
18
|
-
expect(parse(:foo, :string).type).to eq(:string)
|
19
|
-
expect(parse(:foo, :numeric).type).to eq(:numeric)
|
20
|
-
end
|
21
|
-
|
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
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
describe "equals to :required" do
|
29
|
-
it "has type equals to :string" do
|
30
|
-
expect(parse(:foo, :required).type).to eq(:string)
|
31
|
-
end
|
32
|
-
|
33
|
-
it "has no default value" do
|
34
|
-
expect(parse(:foo, :required).default).to be nil
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
describe "and symbol is not a reserved key" do
|
39
|
-
it "has type equal to :string" do
|
40
|
-
expect(parse(:foo, :bar).type).to eq(:string)
|
41
|
-
end
|
42
|
-
|
43
|
-
it "has no default value" do
|
44
|
-
expect(parse(:foo, :bar).default).to be nil
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
describe "with value as hash" do
|
50
|
-
it "has default type :hash" do
|
51
|
-
expect(parse(:foo, :a => :b).type).to eq(:hash)
|
52
|
-
end
|
53
|
-
|
54
|
-
it "has default value equal to the hash" do
|
55
|
-
expect(parse(:foo, :a => :b).default).to eq(:a => :b)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
describe "with value as array" do
|
60
|
-
it "has default type :array" do
|
61
|
-
expect(parse(:foo, [:a, :b]).type).to eq(:array)
|
62
|
-
end
|
63
|
-
|
64
|
-
it "has default value equal to the array" do
|
65
|
-
expect(parse(:foo, [:a, :b]).default).to eq([:a, :b])
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
describe "with value as string" do
|
70
|
-
it "has default type :string" do
|
71
|
-
expect(parse(:foo, "bar").type).to eq(:string)
|
72
|
-
end
|
73
|
-
|
74
|
-
it "has default value equal to the string" do
|
75
|
-
expect(parse(:foo, "bar").default).to eq("bar")
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
describe "with value as numeric" do
|
80
|
-
it "has default type :numeric" do
|
81
|
-
expect(parse(:foo, 2.0).type).to eq(:numeric)
|
82
|
-
end
|
83
|
-
|
84
|
-
it "has default value equal to the numeric" do
|
85
|
-
expect(parse(:foo, 2.0).default).to eq(2.0)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
describe "with value as boolean" do
|
90
|
-
it "has default type :boolean" do
|
91
|
-
expect(parse(:foo, true).type).to eq(:boolean)
|
92
|
-
expect(parse(:foo, false).type).to eq(:boolean)
|
93
|
-
end
|
94
|
-
|
95
|
-
it "has default value equal to the boolean" do
|
96
|
-
expect(parse(:foo, true).default).to eq(true)
|
97
|
-
expect(parse(:foo, false).default).to eq(false)
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
describe "with key as a symbol" do
|
102
|
-
it "sets the name equal to the key" do
|
103
|
-
expect(parse(:foo, true).name).to eq("foo")
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
describe "with key as an array" do
|
108
|
-
it "sets the first items in the array to the name" do
|
109
|
-
expect(parse([:foo, :bar, :baz], true).name).to eq("foo")
|
110
|
-
end
|
111
|
-
|
112
|
-
it "sets all other items as aliases" do
|
113
|
-
expect(parse([:foo, :bar, :baz], true).aliases).to eq([:bar, :baz])
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
it "returns the switch name" do
|
119
|
-
expect(option("foo").switch_name).to eq("--foo")
|
120
|
-
expect(option("--foo").switch_name).to eq("--foo")
|
121
|
-
end
|
122
|
-
|
123
|
-
it "returns the human name" do
|
124
|
-
expect(option("foo").human_name).to eq("foo")
|
125
|
-
expect(option("--foo").human_name).to eq("foo")
|
126
|
-
end
|
127
|
-
|
128
|
-
it "converts underscores to dashes" do
|
129
|
-
expect(option("foo_bar").switch_name).to eq("--foo-bar")
|
130
|
-
end
|
131
|
-
|
132
|
-
it "can be required and have default values" do
|
133
|
-
option = option("foo", :required => true, :type => :string, :default => "bar")
|
134
|
-
expect(option.default).to eq("bar")
|
135
|
-
expect(option).to be_required
|
136
|
-
end
|
137
|
-
|
138
|
-
it "boolean options cannot be required" do
|
139
|
-
expect do
|
140
|
-
option("foo", :required => true, :type => :boolean)
|
141
|
-
end.to raise_error(ArgumentError, "An option cannot be boolean and required.")
|
142
|
-
end
|
143
|
-
|
144
|
-
it "allows type predicates" do
|
145
|
-
expect(parse(:foo, :string)).to be_string
|
146
|
-
expect(parse(:foo, :boolean)).to be_boolean
|
147
|
-
expect(parse(:foo, :numeric)).to be_numeric
|
148
|
-
end
|
149
|
-
|
150
|
-
it "raises an error on method missing" do
|
151
|
-
expect do
|
152
|
-
parse(:foo, :string).unknown?
|
153
|
-
end.to raise_error(NoMethodError)
|
154
|
-
end
|
155
|
-
|
156
|
-
describe "#usage" do
|
157
|
-
|
158
|
-
it "returns usage for string types" do
|
159
|
-
expect(parse(:foo, :string).usage).to eq("[--foo=FOO]")
|
160
|
-
end
|
161
|
-
|
162
|
-
it "returns usage for numeric types" do
|
163
|
-
expect(parse(:foo, :numeric).usage).to eq("[--foo=N]")
|
164
|
-
end
|
165
|
-
|
166
|
-
it "returns usage for array types" do
|
167
|
-
expect(parse(:foo, :array).usage).to eq("[--foo=one two three]")
|
168
|
-
end
|
169
|
-
|
170
|
-
it "returns usage for hash types" do
|
171
|
-
expect(parse(:foo, :hash).usage).to eq("[--foo=key:value]")
|
172
|
-
end
|
173
|
-
|
174
|
-
it "returns usage for boolean types" do
|
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]")
|
180
|
-
end
|
181
|
-
|
182
|
-
it "documents a negative option when boolean" do
|
183
|
-
expect(parse(:foo, :boolean).usage).to include("[--no-foo]")
|
184
|
-
end
|
185
|
-
|
186
|
-
it "uses banner when supplied" do
|
187
|
-
expect(option(:foo, :required => false, :type => :string, :banner => "BAR").usage).to eq("[--foo=BAR]")
|
188
|
-
end
|
189
|
-
|
190
|
-
it "checks when banner is an empty string" do
|
191
|
-
expect(option(:foo, :required => false, :type => :string, :banner => "").usage).to eq("[--foo]")
|
192
|
-
end
|
193
|
-
|
194
|
-
describe "with required values" do
|
195
|
-
it "does not show the usage between brackets" do
|
196
|
-
expect(parse(:foo, :required).usage).to eq("--foo=FOO")
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
describe "with aliases" do
|
201
|
-
it "does not show the usage between brackets" do
|
202
|
-
expect(parse([:foo, "-f", "-b"], :required).usage).to eq("-f, -b, --foo=FOO")
|
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
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
data/spec/parser/options_spec.rb
DELETED
@@ -1,414 +0,0 @@
|
|
1
|
-
require "helper"
|
2
|
-
require "thor/parser"
|
3
|
-
|
4
|
-
describe Thor::Options do
|
5
|
-
def create(opts, defaults = {}, stop_on_unknown = false)
|
6
|
-
opts.each do |key, value|
|
7
|
-
opts[key] = Thor::Option.parse(key, value) unless value.is_a?(Thor::Option)
|
8
|
-
end
|
9
|
-
|
10
|
-
@opt = Thor::Options.new(opts, defaults, stop_on_unknown)
|
11
|
-
end
|
12
|
-
|
13
|
-
def parse(*args)
|
14
|
-
@opt.parse(args.flatten)
|
15
|
-
end
|
16
|
-
|
17
|
-
def check_unknown!
|
18
|
-
@opt.check_unknown!
|
19
|
-
end
|
20
|
-
|
21
|
-
def remaining
|
22
|
-
@opt.remaining
|
23
|
-
end
|
24
|
-
|
25
|
-
describe "#to_switches" do
|
26
|
-
it "turns true values into a flag" do
|
27
|
-
expect(Thor::Options.to_switches(:color => true)).to eq("--color")
|
28
|
-
end
|
29
|
-
|
30
|
-
it "ignores nil" do
|
31
|
-
expect(Thor::Options.to_switches(:color => nil)).to eq("")
|
32
|
-
end
|
33
|
-
|
34
|
-
it "ignores false" do
|
35
|
-
expect(Thor::Options.to_switches(:color => false)).to eq("")
|
36
|
-
end
|
37
|
-
|
38
|
-
it "writes --name value for anything else" do
|
39
|
-
expect(Thor::Options.to_switches(:format => "specdoc")).to eq('--format "specdoc"')
|
40
|
-
end
|
41
|
-
|
42
|
-
it "joins several values" do
|
43
|
-
switches = Thor::Options.to_switches(:color => true, :foo => "bar").split(" ").sort
|
44
|
-
expect(switches).to eq(%w["bar" --color --foo])
|
45
|
-
end
|
46
|
-
|
47
|
-
it "accepts arrays" do
|
48
|
-
expect(Thor::Options.to_switches(:count => [1, 2, 3])).to eq("--count 1 2 3")
|
49
|
-
end
|
50
|
-
|
51
|
-
it "accepts hashes" do
|
52
|
-
expect(Thor::Options.to_switches(:count => {:a => :b})).to eq("--count a:b")
|
53
|
-
end
|
54
|
-
|
55
|
-
it "accepts underscored options" do
|
56
|
-
expect(Thor::Options.to_switches(:under_score_option => "foo bar")).to eq('--under_score_option "foo bar"')
|
57
|
-
end
|
58
|
-
|
59
|
-
end
|
60
|
-
|
61
|
-
describe "#parse" do
|
62
|
-
it "allows multiple aliases for a given switch" do
|
63
|
-
create %w[--foo --bar --baz] => :string
|
64
|
-
expect(parse("--foo", "12")["foo"]).to eq("12")
|
65
|
-
expect(parse("--bar", "12")["foo"]).to eq("12")
|
66
|
-
expect(parse("--baz", "12")["foo"]).to eq("12")
|
67
|
-
end
|
68
|
-
|
69
|
-
it "allows custom short names" do
|
70
|
-
create "-f" => :string
|
71
|
-
expect(parse("-f", "12")).to eq("f" => "12")
|
72
|
-
end
|
73
|
-
|
74
|
-
it "allows custom short-name aliases" do
|
75
|
-
create %w[--bar -f] => :string
|
76
|
-
expect(parse("-f", "12")).to eq("bar" => "12")
|
77
|
-
end
|
78
|
-
|
79
|
-
it "accepts conjoined short switches" do
|
80
|
-
create %w[--foo -f] => true, %w[--bar -b] => true, %w[--app -a] => true
|
81
|
-
opts = parse("-fba")
|
82
|
-
expect(opts["foo"]).to be true
|
83
|
-
expect(opts["bar"]).to be true
|
84
|
-
expect(opts["app"]).to be true
|
85
|
-
end
|
86
|
-
|
87
|
-
it "accepts conjoined short switches with input" do
|
88
|
-
create %w[--foo -f] => true, %w[--bar -b] => true, %w[--app -a] => :required
|
89
|
-
opts = parse "-fba", "12"
|
90
|
-
expect(opts["foo"]).to be true
|
91
|
-
expect(opts["bar"]).to be true
|
92
|
-
expect(opts["app"]).to eq("12")
|
93
|
-
end
|
94
|
-
|
95
|
-
it "returns the default value if none is provided" do
|
96
|
-
create :foo => "baz", :bar => :required
|
97
|
-
expect(parse("--bar", "boom")["foo"]).to eq("baz")
|
98
|
-
end
|
99
|
-
|
100
|
-
it "returns the default value from defaults hash to required arguments" do
|
101
|
-
create Hash[:bar => :required], Hash[:bar => "baz"]
|
102
|
-
expect(parse["bar"]).to eq("baz")
|
103
|
-
end
|
104
|
-
|
105
|
-
it "gives higher priority to defaults given in the hash" do
|
106
|
-
create Hash[:bar => true], Hash[:bar => false]
|
107
|
-
expect(parse["bar"]).to eq(false)
|
108
|
-
end
|
109
|
-
|
110
|
-
it "raises an error for unknown switches" do
|
111
|
-
create :foo => "baz", :bar => :required
|
112
|
-
parse("--bar", "baz", "--baz", "unknown")
|
113
|
-
expect { check_unknown! }.to raise_error(Thor::UnknownArgumentError, "Unknown switches '--baz'")
|
114
|
-
end
|
115
|
-
|
116
|
-
it "skips leading non-switches" do
|
117
|
-
create(:foo => "baz")
|
118
|
-
|
119
|
-
expect(parse("asdf", "--foo", "bar")).to eq("foo" => "bar")
|
120
|
-
end
|
121
|
-
|
122
|
-
it "correctly recognizes things that look kind of like options, but aren't, as not options" do
|
123
|
-
create(:foo => "baz")
|
124
|
-
expect(parse("--asdf---asdf", "baz", "--foo", "--asdf---dsf--asdf")).to eq("foo" => "--asdf---dsf--asdf")
|
125
|
-
check_unknown!
|
126
|
-
end
|
127
|
-
|
128
|
-
it "accepts underscores in commandline args hash for boolean" do
|
129
|
-
create :foo_bar => :boolean
|
130
|
-
expect(parse("--foo_bar")["foo_bar"]).to eq(true)
|
131
|
-
expect(parse("--no_foo_bar")["foo_bar"]).to eq(false)
|
132
|
-
end
|
133
|
-
|
134
|
-
it "accepts underscores in commandline args hash for strings" do
|
135
|
-
create :foo_bar => :string, :baz_foo => :string
|
136
|
-
expect(parse("--foo_bar", "baz")["foo_bar"]).to eq("baz")
|
137
|
-
expect(parse("--baz_foo", "foo bar")["baz_foo"]).to eq("foo bar")
|
138
|
-
end
|
139
|
-
|
140
|
-
it "interprets everything after -- as args instead of options" do
|
141
|
-
create(:foo => :string, :bar => :required)
|
142
|
-
expect(parse(%w[--bar abc moo -- --foo def -a])).to eq("bar" => "abc")
|
143
|
-
expect(remaining).to eq(%w[moo --foo def -a])
|
144
|
-
end
|
145
|
-
|
146
|
-
it "ignores -- when looking for single option values" do
|
147
|
-
create(:foo => :string, :bar => :required)
|
148
|
-
expect(parse(%w[--bar -- --foo def -a])).to eq("bar" => "--foo")
|
149
|
-
expect(remaining).to eq(%w[def -a])
|
150
|
-
end
|
151
|
-
|
152
|
-
it "ignores -- when looking for array option values" do
|
153
|
-
create(:foo => :array)
|
154
|
-
expect(parse(%w[--foo a b -- c d -e])).to eq("foo" => %w[a b c d -e])
|
155
|
-
expect(remaining).to eq([])
|
156
|
-
end
|
157
|
-
|
158
|
-
it "ignores -- when looking for hash option values" do
|
159
|
-
create(:foo => :hash)
|
160
|
-
expect(parse(%w[--foo a:b -- c:d -e])).to eq("foo" => {"a" => "b", "c" => "d"})
|
161
|
-
expect(remaining).to eq(%w[-e])
|
162
|
-
end
|
163
|
-
|
164
|
-
it "ignores trailing --" do
|
165
|
-
create(:foo => :string)
|
166
|
-
expect(parse(%w[--foo --])).to eq("foo" => nil)
|
167
|
-
expect(remaining).to eq([])
|
168
|
-
end
|
169
|
-
|
170
|
-
describe "with no input" do
|
171
|
-
it "and no switches returns an empty hash" do
|
172
|
-
create({})
|
173
|
-
expect(parse).to eq({})
|
174
|
-
end
|
175
|
-
|
176
|
-
it "and several switches returns an empty hash" do
|
177
|
-
create "--foo" => :boolean, "--bar" => :string
|
178
|
-
expect(parse).to eq({})
|
179
|
-
end
|
180
|
-
|
181
|
-
it "and a required switch raises an error" do
|
182
|
-
create "--foo" => :required
|
183
|
-
expect { parse }.to raise_error(Thor::RequiredArgumentMissingError, "No value provided for required options '--foo'")
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
describe "with one required and one optional switch" do
|
188
|
-
before do
|
189
|
-
create "--foo" => :required, "--bar" => :boolean
|
190
|
-
end
|
191
|
-
|
192
|
-
it "raises an error if the required switch has no argument" do
|
193
|
-
expect { parse("--foo") }.to raise_error(Thor::MalformattedArgumentError)
|
194
|
-
end
|
195
|
-
|
196
|
-
it "raises an error if the required switch isn't given" do
|
197
|
-
expect { parse("--bar") }.to raise_error(Thor::RequiredArgumentMissingError)
|
198
|
-
end
|
199
|
-
|
200
|
-
it "raises an error if the required switch is set to nil" do
|
201
|
-
expect { parse("--no-foo") }.to raise_error(Thor::RequiredArgumentMissingError)
|
202
|
-
end
|
203
|
-
|
204
|
-
it "does not raises an error if the required option has a default value" do
|
205
|
-
options = {:required => true, :type => :string, :default => "baz"}
|
206
|
-
create :foo => Thor::Option.new("foo", options), :bar => :boolean
|
207
|
-
expect { parse("--bar") }.not_to raise_error
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
context "when stop_on_unknown is true" do
|
212
|
-
before do
|
213
|
-
create({:foo => :string, :verbose => :boolean}, {}, true)
|
214
|
-
end
|
215
|
-
|
216
|
-
it "stops parsing on first non-option" do
|
217
|
-
expect(parse(%w[foo --verbose])).to eq({})
|
218
|
-
expect(remaining).to eq(%w[foo --verbose])
|
219
|
-
end
|
220
|
-
|
221
|
-
it "stops parsing on unknown option" do
|
222
|
-
expect(parse(%w[--bar --verbose])).to eq({})
|
223
|
-
expect(remaining).to eq(%w[--bar --verbose])
|
224
|
-
end
|
225
|
-
|
226
|
-
it "retains -- after it has stopped parsing" do
|
227
|
-
expect(parse(%w[--bar -- whatever])).to eq({})
|
228
|
-
expect(remaining).to eq(%w[--bar -- whatever])
|
229
|
-
end
|
230
|
-
|
231
|
-
it "still accepts options that are given before non-options" do
|
232
|
-
expect(parse(%w[--verbose foo])).to eq("verbose" => true)
|
233
|
-
expect(remaining).to eq(%w[foo])
|
234
|
-
end
|
235
|
-
|
236
|
-
it "still accepts options that require a value" do
|
237
|
-
expect(parse(%w[--foo bar baz])).to eq("foo" => "bar")
|
238
|
-
expect(remaining).to eq(%w[baz])
|
239
|
-
end
|
240
|
-
|
241
|
-
it "still interprets everything after -- as args instead of options" do
|
242
|
-
expect(parse(%w[-- --verbose])).to eq({})
|
243
|
-
expect(remaining).to eq(%w[--verbose])
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
describe "with :string type" do
|
248
|
-
before do
|
249
|
-
create %w[--foo -f] => :required
|
250
|
-
end
|
251
|
-
|
252
|
-
it "accepts a switch <value> assignment" do
|
253
|
-
expect(parse("--foo", "12")["foo"]).to eq("12")
|
254
|
-
end
|
255
|
-
|
256
|
-
it "accepts a switch=<value> assignment" do
|
257
|
-
expect(parse("-f=12")["foo"]).to eq("12")
|
258
|
-
expect(parse("--foo=12")["foo"]).to eq("12")
|
259
|
-
expect(parse("--foo=bar=baz")["foo"]).to eq("bar=baz")
|
260
|
-
end
|
261
|
-
|
262
|
-
it "must accept underscores switch=value assignment" do
|
263
|
-
create :foo_bar => :required
|
264
|
-
expect(parse("--foo_bar=http://example.com/under_score/")["foo_bar"]).to eq("http://example.com/under_score/")
|
265
|
-
end
|
266
|
-
|
267
|
-
it "accepts a --no-switch format" do
|
268
|
-
create "--foo" => "bar"
|
269
|
-
expect(parse("--no-foo")["foo"]).to be nil
|
270
|
-
end
|
271
|
-
|
272
|
-
it "does not consume an argument for --no-switch format" do
|
273
|
-
create "--cheese" => :string
|
274
|
-
expect(parse("burger", "--no-cheese", "fries")["cheese"]).to be nil
|
275
|
-
end
|
276
|
-
|
277
|
-
it "accepts a --switch format on non required types" do
|
278
|
-
create "--foo" => :string
|
279
|
-
expect(parse("--foo")["foo"]).to eq("foo")
|
280
|
-
end
|
281
|
-
|
282
|
-
it "accepts a --switch format on non required types with default values" do
|
283
|
-
create "--baz" => :string, "--foo" => "bar"
|
284
|
-
expect(parse("--baz", "bang", "--foo")["foo"]).to eq("bar")
|
285
|
-
end
|
286
|
-
|
287
|
-
it "overwrites earlier values with later values" do
|
288
|
-
expect(parse("--foo=bar", "--foo", "12")["foo"]).to eq("12")
|
289
|
-
expect(parse("--foo", "12", "--foo", "13")["foo"]).to eq("13")
|
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
|
298
|
-
end
|
299
|
-
|
300
|
-
describe "with :boolean type" do
|
301
|
-
before do
|
302
|
-
create "--foo" => false
|
303
|
-
end
|
304
|
-
|
305
|
-
it "accepts --opt assignment" do
|
306
|
-
expect(parse("--foo")["foo"]).to eq(true)
|
307
|
-
expect(parse("--foo", "--bar")["foo"]).to eq(true)
|
308
|
-
end
|
309
|
-
|
310
|
-
it "uses the default value if no switch is given" do
|
311
|
-
expect(parse("")["foo"]).to eq(false)
|
312
|
-
end
|
313
|
-
|
314
|
-
it "accepts --opt=value assignment" do
|
315
|
-
expect(parse("--foo=true")["foo"]).to eq(true)
|
316
|
-
expect(parse("--foo=false")["foo"]).to eq(false)
|
317
|
-
end
|
318
|
-
|
319
|
-
it "accepts --[no-]opt variant, setting false for value" do
|
320
|
-
expect(parse("--no-foo")["foo"]).to eq(false)
|
321
|
-
end
|
322
|
-
|
323
|
-
it "accepts --[skip-]opt variant, setting false for value" do
|
324
|
-
expect(parse("--skip-foo")["foo"]).to eq(false)
|
325
|
-
end
|
326
|
-
|
327
|
-
it "will prefer 'no-opt' variant over inverting 'opt' if explicitly set" do
|
328
|
-
create "--no-foo" => true
|
329
|
-
expect(parse("--no-foo")["no-foo"]).to eq(true)
|
330
|
-
end
|
331
|
-
|
332
|
-
it "will prefer 'skip-opt' variant over inverting 'opt' if explicitly set" do
|
333
|
-
create "--skip-foo" => true
|
334
|
-
expect(parse("--skip-foo")["skip-foo"]).to eq(true)
|
335
|
-
end
|
336
|
-
|
337
|
-
it "accepts inputs in the human name format" do
|
338
|
-
create :foo_bar => :boolean
|
339
|
-
expect(parse("--foo-bar")["foo_bar"]).to eq(true)
|
340
|
-
expect(parse("--no-foo-bar")["foo_bar"]).to eq(false)
|
341
|
-
expect(parse("--skip-foo-bar")["foo_bar"]).to eq(false)
|
342
|
-
end
|
343
|
-
|
344
|
-
it "doesn't eat the next part of the param" do
|
345
|
-
create :foo => :boolean
|
346
|
-
expect(parse("--foo", "bar")).to eq("foo" => true)
|
347
|
-
expect(@opt.remaining).to eq(%w[bar])
|
348
|
-
end
|
349
|
-
end
|
350
|
-
|
351
|
-
describe "with :hash type" do
|
352
|
-
before do
|
353
|
-
create "--attributes" => :hash
|
354
|
-
end
|
355
|
-
|
356
|
-
it "accepts a switch=<value> assignment" do
|
357
|
-
expect(parse("--attributes=name:string", "age:integer")["attributes"]).to eq("name" => "string", "age" => "integer")
|
358
|
-
end
|
359
|
-
|
360
|
-
it "accepts a switch <value> assignment" do
|
361
|
-
expect(parse("--attributes", "name:string", "age:integer")["attributes"]).to eq("name" => "string", "age" => "integer")
|
362
|
-
end
|
363
|
-
|
364
|
-
it "must not mix values with other switches" do
|
365
|
-
expect(parse("--attributes", "name:string", "age:integer", "--baz", "cool")["attributes"]).to eq("name" => "string", "age" => "integer")
|
366
|
-
end
|
367
|
-
end
|
368
|
-
|
369
|
-
describe "with :array type" do
|
370
|
-
before do
|
371
|
-
create "--attributes" => :array
|
372
|
-
end
|
373
|
-
|
374
|
-
it "accepts a switch=<value> assignment" do
|
375
|
-
expect(parse("--attributes=a", "b", "c")["attributes"]).to eq(%w[a b c])
|
376
|
-
end
|
377
|
-
|
378
|
-
it "accepts a switch <value> assignment" do
|
379
|
-
expect(parse("--attributes", "a", "b", "c")["attributes"]).to eq(%w[a b c])
|
380
|
-
end
|
381
|
-
|
382
|
-
it "must not mix values with other switches" do
|
383
|
-
expect(parse("--attributes", "a", "b", "c", "--baz", "cool")["attributes"]).to eq(%w[a b c])
|
384
|
-
end
|
385
|
-
end
|
386
|
-
|
387
|
-
describe "with :numeric type" do
|
388
|
-
before do
|
389
|
-
create "n" => :numeric, "m" => 5
|
390
|
-
end
|
391
|
-
|
392
|
-
it "accepts a -nXY assignment" do
|
393
|
-
expect(parse("-n12")["n"]).to eq(12)
|
394
|
-
end
|
395
|
-
|
396
|
-
it "converts values to numeric types" do
|
397
|
-
expect(parse("-n", "3", "-m", ".5")).to eq("n" => 3, "m" => 0.5)
|
398
|
-
end
|
399
|
-
|
400
|
-
it "raises error when value isn't numeric" do
|
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")
|
410
|
-
end
|
411
|
-
end
|
412
|
-
|
413
|
-
end
|
414
|
-
end
|