thor 0.17.0 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/{CHANGELOG.rdoc → CHANGELOG.md} +30 -36
  2. data/README.md +10 -3
  3. data/lib/thor.rb +205 -180
  4. data/lib/thor/actions.rb +5 -5
  5. data/lib/thor/actions/create_link.rb +3 -0
  6. data/lib/thor/actions/directory.rb +2 -0
  7. data/lib/thor/actions/file_manipulation.rb +1 -1
  8. data/lib/thor/base.rb +84 -95
  9. data/lib/thor/{task.rb → command.rb} +17 -13
  10. data/lib/thor/core_ext/io_binary_read.rb +12 -0
  11. data/lib/thor/error.rb +4 -7
  12. data/lib/thor/group.rb +30 -33
  13. data/lib/thor/invocation.rb +28 -26
  14. data/lib/thor/parser/options.rb +3 -1
  15. data/lib/thor/runner.rb +21 -20
  16. data/lib/thor/shell/basic.rb +5 -1
  17. data/lib/thor/shell/color.rb +4 -0
  18. data/lib/thor/shell/html.rb +4 -0
  19. data/lib/thor/util.rb +214 -210
  20. data/lib/thor/version.rb +1 -1
  21. data/spec/actions/create_file_spec.rb +1 -1
  22. data/spec/actions/create_link_spec.rb +15 -1
  23. data/spec/actions/directory_spec.rb +18 -5
  24. data/spec/actions/empty_directory_spec.rb +1 -1
  25. data/spec/actions/file_manipulation_spec.rb +13 -13
  26. data/spec/actions/inject_into_file_spec.rb +1 -1
  27. data/spec/actions_spec.rb +1 -1
  28. data/spec/base_spec.rb +40 -24
  29. data/spec/command_spec.rb +80 -0
  30. data/spec/core_ext/hash_with_indifferent_access_spec.rb +1 -1
  31. data/spec/core_ext/ordered_hash_spec.rb +1 -1
  32. data/spec/exit_condition_spec.rb +3 -3
  33. data/spec/fixtures/{task.thor → command.thor} +0 -0
  34. data/spec/fixtures/doc/%file_name%.rb.tt +1 -0
  35. data/spec/fixtures/doc/COMMENTER +11 -0
  36. data/spec/fixtures/doc/README +3 -0
  37. data/spec/fixtures/doc/block_helper.rb +3 -0
  38. data/spec/fixtures/doc/config.rb +1 -0
  39. data/spec/fixtures/doc/config.yaml.tt +1 -0
  40. data/spec/fixtures/doc/excluding/%file_name%.rb.tt +1 -0
  41. data/spec/fixtures/group.thor +24 -10
  42. data/spec/fixtures/invoke.thor +3 -3
  43. data/spec/fixtures/script.thor +40 -15
  44. data/spec/fixtures/subcommand.thor +17 -0
  45. data/spec/group_spec.rb +13 -13
  46. data/spec/{spec_helper.rb → helper.rb} +11 -7
  47. data/spec/invocation_spec.rb +16 -16
  48. data/spec/parser/argument_spec.rb +4 -4
  49. data/spec/parser/arguments_spec.rb +1 -1
  50. data/spec/parser/option_spec.rb +1 -1
  51. data/spec/parser/options_spec.rb +6 -1
  52. data/spec/rake_compat_spec.rb +1 -1
  53. data/spec/register_spec.rb +12 -12
  54. data/spec/runner_spec.rb +36 -36
  55. data/spec/shell/basic_spec.rb +9 -10
  56. data/spec/shell/color_spec.rb +16 -2
  57. data/spec/shell/html_spec.rb +1 -1
  58. data/spec/shell_spec.rb +1 -1
  59. data/spec/subcommand_spec.rb +30 -0
  60. data/spec/thor_spec.rb +81 -78
  61. data/spec/util_spec.rb +10 -10
  62. data/thor.gemspec +22 -18
  63. metadata +49 -38
  64. data/.gitignore +0 -44
  65. data/.rspec +0 -3
  66. data/.travis.yml +0 -8
  67. data/Gemfile +0 -19
  68. data/bin/rake2thor +0 -86
  69. data/lib/thor/core_ext/file_binary_read.rb +0 -9
  70. data/spec/task_spec.rb +0 -80
@@ -0,0 +1,3 @@
1
+ <% world do -%>
2
+ Hello
3
+ <% end -%>
@@ -0,0 +1 @@
1
+ class <%= @klass %>; end
@@ -0,0 +1 @@
1
+ --- Hi from yaml
@@ -0,0 +1 @@
1
+ BAR = <%= "BAR" %>
@@ -9,16 +9,18 @@ class MyCounter < Thor::Group
9
9
  source_root File.expand_path(File.dirname(__FILE__))
10
10
  source_paths << File.expand_path("broken", File.dirname(__FILE__))
11
11
 
12
- argument :first, :type => :numeric
13
- argument :second, :type => :numeric, :default => 2
12
+ argument :first, :type => :numeric
13
+ argument :second, :type => :numeric, :default => 2
14
14
 
15
- class_option :third, :type => :numeric, :desc => "The third argument", :default => 3,
16
- :banner => "THREE", :aliases => "-t"
17
- class_option :fourth, :type => :numeric, :desc => "The fourth argument"
15
+ class_option :third, :type => :numeric, :desc => "The third argument", :default => 3,
16
+ :banner => "THREE", :aliases => "-t"
17
+ class_option :fourth, :type => :numeric, :desc => "The fourth argument"
18
+ class_option :simple, :type => :numeric, :aliases => 'z'
19
+ class_option :symbolic, :type => :numeric, :aliases => [:y, :r]
18
20
 
19
21
  desc <<-FOO
20
22
  Description:
21
- This generator runs three tasks: one, two and three.
23
+ This generator runs three commands: one, two and three.
22
24
  FOO
23
25
 
24
26
  def one
@@ -33,12 +35,24 @@ FOO
33
35
  options[:third]
34
36
  end
35
37
 
38
+ def four
39
+ options[:fourth]
40
+ end
41
+
42
+ def five
43
+ options[:simple]
44
+ end
45
+
46
+ def six
47
+ options[:symbolic]
48
+ end
49
+
36
50
  def self.inherited(base)
37
51
  super
38
52
  base.source_paths.unshift(File.expand_path(File.join(File.dirname(__FILE__), "doc")))
39
53
  end
40
54
 
41
- no_tasks do
55
+ no_commands do
42
56
  def world(&block)
43
57
  result = capture(&block)
44
58
  concat(result.strip + " world!")
@@ -87,8 +101,8 @@ class WhinyGenerator < Thor::Group
87
101
  end
88
102
  end
89
103
 
90
- class TaskConflict < Thor::Group
91
- desc "A group with the same name as a default task"
104
+ class CommandConflict < Thor::Group
105
+ desc "A group with the same name as a default command"
92
106
  def group
93
107
  puts "group"
94
108
  end
@@ -110,5 +124,5 @@ class ChildGroup < ParentGroup
110
124
  "bar"
111
125
  end
112
126
 
113
- public_task :foo, :baz
127
+ public_command :foo, :baz
114
128
  end
@@ -30,7 +30,7 @@ class A < Thor
30
30
  number == 5
31
31
  end
32
32
 
33
- desc "invoker", "invoke a b task"
33
+ desc "invoker", "invoke a b command"
34
34
  def invoker(*args)
35
35
  invoke :b, :one, ["Jose"]
36
36
  end
@@ -96,8 +96,8 @@ class E < Thor::Group
96
96
  end
97
97
 
98
98
  class F < Thor::Group
99
- invoke "b:one" do |instance, klass, task|
100
- instance.invoke klass, task, [ "Jose" ], :last_name => "Valim"
99
+ invoke "b:one" do |instance, klass, command|
100
+ instance.invoke klass, command, [ "Jose" ], :last_name => "Valim"
101
101
  end
102
102
  end
103
103
 
@@ -5,8 +5,12 @@ class MyScript < Thor
5
5
  attr_writer :another_attribute
6
6
  attr_reader :another_attribute
7
7
 
8
+ private
9
+ attr_reader :private_attribute
10
+
11
+ public
8
12
  group :script
9
- default_task :example_default_task
13
+ default_command :example_default_command
10
14
 
11
15
  map "-T" => :animal, ["-f", "--foo"] => :foo
12
16
 
@@ -19,8 +23,8 @@ class MyScript < Thor
19
23
 
20
24
  desc "animal TYPE", "horse around"
21
25
 
22
- no_tasks do
23
- def this_is_not_a_task
26
+ no_commands do
27
+ def this_is_not_a_command
24
28
  end
25
29
  end
26
30
 
@@ -47,10 +51,10 @@ END
47
51
  [bar, options]
48
52
  end
49
53
 
50
- desc "example_default_task", "example!"
54
+ desc "example_default_command", "example!"
51
55
  method_options :with => :string
52
- def example_default_task
53
- options.empty? ? "default task" : options
56
+ def example_default_command
57
+ options.empty? ? "default command" : options
54
58
  end
55
59
 
56
60
  desc "call_myself_with_wrong_arity", "get the right error"
@@ -58,7 +62,7 @@ END
58
62
  call_myself_with_wrong_arity(4)
59
63
  end
60
64
 
61
- desc "call_unexistent_method", "Call unexistent method inside a task"
65
+ desc "call_unexistent_method", "Call unexistent method inside a command"
62
66
  def call_unexistent_method
63
67
  boom!
64
68
  end
@@ -73,7 +77,7 @@ END
73
77
  def long_description
74
78
  end
75
79
 
76
- desc "name-with-dashes", "Ensure normalization of task names"
80
+ desc "name-with-dashes", "Ensure normalization of command names"
77
81
  def name_with_dashes
78
82
  end
79
83
 
@@ -93,7 +97,7 @@ END
93
97
  end
94
98
  end
95
99
 
96
- desc "send", "send as a task name"
100
+ desc "send", "send as a command name"
97
101
  def send
98
102
  true
99
103
  end
@@ -114,7 +118,7 @@ END
114
118
  end
115
119
 
116
120
  class MyChildScript < MyScript
117
- remove_task :bar
121
+ remove_command :bar
118
122
 
119
123
  method_options :force => :boolean, :param => :numeric
120
124
  def initialize(*args)
@@ -138,7 +142,7 @@ class MyChildScript < MyScript
138
142
  def boom
139
143
  end
140
144
 
141
- remove_task :boom, :undefine => true
145
+ remove_command :boom, :undefine => true
142
146
  end
143
147
 
144
148
  class Barn < Thor
@@ -156,14 +160,17 @@ class Barn < Thor
156
160
  def paint(color='red')
157
161
  puts "#{options[:coats]} coats of #{color} paint"
158
162
  end
163
+ end
159
164
 
165
+ class PackageNameScript < Thor
166
+ package_name "Baboon"
160
167
  end
161
168
 
162
169
  module Scripts
163
170
  class MyScript < MyChildScript
164
171
  argument :accessor, :type => :string
165
172
  class_options :force => :boolean
166
- method_option :new_option, :type => :string, :for => :example_default_task
173
+ method_option :new_option, :type => :string, :for => :example_default_command
167
174
 
168
175
  def zoo
169
176
  self.accessor
@@ -179,9 +186,9 @@ module Scripts
179
186
  puts "moo"
180
187
  end
181
188
 
182
- desc "task_conflict", "only gets called when prepended with a colon"
183
- def task_conflict
184
- puts "task"
189
+ desc "command_conflict", "only gets called when prepended with a colon"
190
+ def command_conflict
191
+ puts "command"
185
192
  end
186
193
 
187
194
  desc "barn", "commands to manage the barn"
@@ -191,5 +198,23 @@ module Scripts
191
198
  class ChildDefault < Thor
192
199
  namespace "default:child"
193
200
  end
201
+
202
+ class Arities < Thor
203
+ desc "zero_args", "takes zero args"
204
+ def zero_args
205
+ end
206
+
207
+ desc "one_arg ARG", "takes one arg"
208
+ def one_arg(arg)
209
+ end
210
+
211
+ desc "two_args ARG1 ARG2", "takes two args"
212
+ def two_args(arg1, arg2)
213
+ end
214
+
215
+ desc "optional_arg [ARG]", "takes an optional arg"
216
+ def optional_arg(arg='default')
217
+ end
218
+ end
194
219
  end
195
220
 
@@ -0,0 +1,17 @@
1
+ module TestSubcommands
2
+
3
+ class Subcommand < Thor
4
+ desc "print_opt", "My method"
5
+ def print_opt
6
+ print options["opt"]
7
+ end
8
+ end
9
+
10
+ class Parent < Thor
11
+ class_option "opt"
12
+
13
+ desc "sub", "My subcommand"
14
+ subcommand "sub", Subcommand
15
+ end
16
+
17
+ end
@@ -1,24 +1,24 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
1
+ require 'helper'
2
2
 
3
3
  describe Thor::Group do
4
- describe "task" do
5
- it "allows to use private methods from parent class as tasks" do
4
+ describe "command" do
5
+ it "allows to use private methods from parent class as commands" do
6
6
  expect(ChildGroup.start).to eq(["bar", "foo", "baz"])
7
7
  expect(ChildGroup.new.baz("bar")).to eq("bar")
8
8
  end
9
9
  end
10
10
 
11
11
  describe "#start" do
12
- it "invokes all the tasks under the Thor group" do
13
- expect(MyCounter.start(["1", "2", "--third", "3"])).to eq([ 1, 2, 3 ])
12
+ it "invokes all the commands under the Thor group" do
13
+ expect(MyCounter.start(["1", "2", "--third", "3"])).to eq([ 1, 2, 3, nil, nil, nil ])
14
14
  end
15
15
 
16
16
  it "uses argument default value" do
17
- expect(MyCounter.start(["1", "--third", "3"])).to eq([ 1, 2, 3 ])
17
+ expect(MyCounter.start(["1", "--third", "3"])).to eq([ 1, 2, 3, nil, nil, nil ])
18
18
  end
19
19
 
20
- it "invokes all the tasks in the Thor group and his parents" do
21
- expect(BrokenCounter.start(["1", "2", "--third", "3"])).to eq([ nil, 2, 3, false, 5 ])
20
+ it "invokes all the commands in the Thor group and its parents" do
21
+ expect(BrokenCounter.start(["1", "2", "--third", "3"])).to eq([ nil, 2, 3, false, 5, nil ])
22
22
  end
23
23
 
24
24
  it "raises an error if a required argument is added after a non-required" do
@@ -27,11 +27,11 @@ describe Thor::Group do
27
27
  }.to raise_error(ArgumentError, 'You cannot have "foo" as required argument after the non-required argument "second".')
28
28
  end
29
29
 
30
- it "raises when an exception happens within the task call" do
30
+ it "raises when an exception happens within the command call" do
31
31
  expect{ BrokenCounter.start(["1", "2", "--fail"]) }.to raise_error
32
32
  end
33
33
 
34
- it "raises an error when a Thor group task expects arguments" do
34
+ it "raises an error when a Thor group command expects arguments" do
35
35
  expect{ WhinyGenerator.start }.to raise_error(ArgumentError, /thor wrong_arity takes 1 argument, but it should not/)
36
36
  end
37
37
 
@@ -43,11 +43,11 @@ describe Thor::Group do
43
43
 
44
44
  describe "#desc" do
45
45
  it "sets the description for a given class" do
46
- expect(MyCounter.desc).to eq("Description:\n This generator runs three tasks: one, two and three.\n")
46
+ expect(MyCounter.desc).to eq("Description:\n This generator runs three commands: one, two and three.\n")
47
47
  end
48
48
 
49
49
  it "can be inherited" do
50
- expect(BrokenCounter.desc).to eq("Description:\n This generator runs three tasks: one, two and three.\n")
50
+ expect(BrokenCounter.desc).to eq("Description:\n This generator runs three commands: one, two and three.\n")
51
51
  end
52
52
 
53
53
  it "can be nil" do
@@ -66,7 +66,7 @@ describe Thor::Group do
66
66
 
67
67
  it "shows description" do
68
68
  expect(@content).to match(/Description:/)
69
- expect(@content).to match(/This generator runs three tasks: one, two and three./)
69
+ expect(@content).to match(/This generator runs three commands: one, two and three./)
70
70
  end
71
71
 
72
72
  it "shows options information" do
@@ -1,10 +1,13 @@
1
1
  $TESTING=true
2
2
 
3
3
  require 'simplecov'
4
- SimpleCov.start do
5
- add_group 'Libraries', 'lib'
6
- add_group 'Specs', 'spec'
7
- end
4
+ require 'coveralls'
5
+
6
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
7
+ SimpleCov::Formatter::HTMLFormatter,
8
+ Coveralls::SimpleCov::Formatter
9
+ ]
10
+ SimpleCov.start
8
11
 
9
12
  $:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
10
13
  require 'thor'
@@ -23,11 +26,12 @@ ARGV.clear
23
26
  Thor::Base.shell = Thor::Shell::Basic
24
27
 
25
28
  # Load fixtures
26
- load File.join(File.dirname(__FILE__), "fixtures", "task.thor")
29
+ load File.join(File.dirname(__FILE__), "fixtures", "enum.thor")
27
30
  load File.join(File.dirname(__FILE__), "fixtures", "group.thor")
28
- load File.join(File.dirname(__FILE__), "fixtures", "script.thor")
29
31
  load File.join(File.dirname(__FILE__), "fixtures", "invoke.thor")
30
- load File.join(File.dirname(__FILE__), "fixtures", "enum.thor")
32
+ load File.join(File.dirname(__FILE__), "fixtures", "script.thor")
33
+ load File.join(File.dirname(__FILE__), "fixtures", "subcommand.thor")
34
+ load File.join(File.dirname(__FILE__), "fixtures", "command.thor")
31
35
 
32
36
  RSpec.configure do |config|
33
37
  config.before do
@@ -1,38 +1,38 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
1
+ require 'helper'
2
2
  require 'thor/base'
3
3
 
4
4
  describe Thor::Invocation do
5
5
  describe "#invoke" do
6
- it "invokes a task inside another task" do
6
+ it "invokes a command inside another command" do
7
7
  expect(capture(:stdout) { A.new.invoke(:two) }).to eq("2\n3\n")
8
8
  end
9
9
 
10
- it "invokes a task just once" do
10
+ it "invokes a command just once" do
11
11
  expect(capture(:stdout) { A.new.invoke(:one) }).to eq("1\n2\n3\n")
12
12
  end
13
13
 
14
- it "invokes a task just once even if they belongs to different classes" do
14
+ it "invokes a command just once even if they belongs to different classes" do
15
15
  expect(capture(:stdout) { Defined.new.invoke(:one) }).to eq("1\n2\n3\n4\n5\n")
16
16
  end
17
17
 
18
- it "invokes a task with arguments" do
18
+ it "invokes a command with arguments" do
19
19
  expect(A.new.invoke(:five, [5])).to be_true
20
20
  expect(A.new.invoke(:five, [7])).to be_false
21
21
  end
22
22
 
23
- it "invokes the default task if none is given to a Thor class" do
23
+ it "invokes the default command if none is given to a Thor class" do
24
24
  content = capture(:stdout) { A.new.invoke("b") }
25
- expect(content).to match(/Tasks/)
25
+ expect(content).to match(/Commands/)
26
26
  expect(content).to match(/LAST_NAME/)
27
27
  end
28
28
 
29
- it "accepts a class as argument without a task to invoke" do
29
+ it "accepts a class as argument without a command to invoke" do
30
30
  content = capture(:stdout) { A.new.invoke(B) }
31
- expect(content).to match(/Tasks/)
31
+ expect(content).to match(/Commands/)
32
32
  expect(content).to match(/LAST_NAME/)
33
33
  end
34
34
 
35
- it "accepts a class as argument with a task to invoke" do
35
+ it "accepts a class as argument with a command to invoke" do
36
36
  base = A.new([], :last_name => "Valim")
37
37
  expect(base.invoke(B, :one, ["Jose"])).to eq("Valim, Jose")
38
38
  end
@@ -60,7 +60,7 @@ describe Thor::Invocation do
60
60
  expect(base.invoke("b:three", [], {}, :shell => shell).shell).to eq(shell)
61
61
  end
62
62
 
63
- it "invokes a Thor::Group and all of its tasks" do
63
+ it "invokes a Thor::Group and all of its commands" do
64
64
  expect(capture(:stdout) { A.new.invoke(:c) }).to eq("1\n2\n3\n")
65
65
  end
66
66
 
@@ -70,25 +70,25 @@ describe Thor::Invocation do
70
70
  expect(capture(:stdout) { base.invoke(:c) }).to be_empty
71
71
  end
72
72
 
73
- it "does not invoke any of Thor::Group tasks twice" do
73
+ it "does not invoke any of Thor::Group commands twice" do
74
74
  base = A.new
75
75
  silence(:stdout){ base.invoke(:c) }
76
76
  expect(capture(:stdout) { base.invoke("c:one") }).to be_empty
77
77
  end
78
78
 
79
- it "raises Thor::UndefinedTaskError if the task can't be found" do
79
+ it "raises Thor::UndefinedcommandError if the command can't be found" do
80
80
  expect {
81
81
  A.new.invoke("foo:bar")
82
- }.to raise_error(Thor::UndefinedTaskError)
82
+ }.to raise_error(Thor::UndefinedCommandError)
83
83
  end
84
84
 
85
- it "raises Thor::UndefinedTaskError if the task can't be found even if all tasks where already executed" do
85
+ it "raises Thor::UndefinedcommandError if the command can't be found even if all commands were already executed" do
86
86
  base = C.new
87
87
  silence(:stdout){ base.invoke_all }
88
88
 
89
89
  expect {
90
90
  base.invoke("foo:bar")
91
- }.to raise_error(Thor::UndefinedTaskError)
91
+ }.to raise_error(Thor::UndefinedCommandError)
92
92
  end
93
93
 
94
94
  it "raises an error if a non Thor class is given" do
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
1
+ require 'helper'
2
2
  require 'thor/parser'
3
3
 
4
4
  describe Thor::Argument do
@@ -16,19 +16,19 @@ describe Thor::Argument do
16
16
 
17
17
  it "raises an error if type is unknown" do
18
18
  expect {
19
- argument(:task, :type => :unknown)
19
+ argument(:command, :type => :unknown)
20
20
  }.to raise_error(ArgumentError, "Type :unknown is not valid for arguments.")
21
21
  end
22
22
 
23
23
  it "raises an error if argument is required and have default values" do
24
24
  expect {
25
- argument(:task, :type => :string, :default => "bar", :required => true)
25
+ argument(:command, :type => :string, :default => "bar", :required => true)
26
26
  }.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
30
  expect {
31
- argument(:task, :type => :string, :enum => "bar")
31
+ argument(:command, :type => :string, :enum => "bar")
32
32
  }.to raise_error(ArgumentError, "An argument cannot have an enum other than an array.")
33
33
  end
34
34
  end