thor 0.13.4 → 0.14.3

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.
Files changed (45) hide show
  1. data/CHANGELOG.rdoc +5 -3
  2. data/{README.rdoc → README.md} +65 -55
  3. data/Thorfile +3 -2
  4. data/lib/thor/actions/create_file.rb +3 -1
  5. data/lib/thor/actions/directory.rb +4 -2
  6. data/lib/thor/actions/file_manipulation.rb +30 -7
  7. data/lib/thor/actions.rb +31 -9
  8. data/lib/thor/base.rb +38 -15
  9. data/lib/thor/core_ext/hash_with_indifferent_access.rb +1 -1
  10. data/lib/thor/group.rb +22 -20
  11. data/lib/thor/invocation.rb +45 -57
  12. data/lib/thor/parser/argument.rb +15 -15
  13. data/lib/thor/parser/arguments.rb +14 -3
  14. data/lib/thor/parser/option.rb +38 -46
  15. data/lib/thor/parser/options.rb +26 -22
  16. data/lib/thor/runner.rb +11 -16
  17. data/lib/thor/shell/basic.rb +48 -12
  18. data/lib/thor/shell/html.rb +121 -0
  19. data/lib/thor/shell.rb +7 -2
  20. data/lib/thor/task.rb +63 -51
  21. data/lib/thor/util.rb +15 -16
  22. data/lib/thor/version.rb +1 -1
  23. data/lib/thor.rb +118 -45
  24. data/spec/actions/directory_spec.rb +2 -2
  25. data/spec/actions/file_manipulation_spec.rb +7 -0
  26. data/spec/actions_spec.rb +21 -3
  27. data/spec/base_spec.rb +9 -3
  28. data/spec/fixtures/doc/block_helper.rb +3 -0
  29. data/spec/fixtures/doc/components/.empty_directory +0 -0
  30. data/spec/fixtures/group.thor +16 -4
  31. data/spec/fixtures/path with spaces +0 -0
  32. data/spec/fixtures/script.thor +48 -4
  33. data/spec/group_spec.rb +3 -3
  34. data/spec/invocation_spec.rb +1 -8
  35. data/spec/parser/option_spec.rb +2 -2
  36. data/spec/parser/options_spec.rb +27 -0
  37. data/spec/runner_spec.rb +16 -8
  38. data/spec/shell/basic_spec.rb +13 -4
  39. data/spec/shell/html_spec.rb +27 -0
  40. data/spec/shell_spec.rb +13 -0
  41. data/spec/spec_helper.rb +4 -3
  42. data/spec/task_spec.rb +7 -7
  43. data/spec/thor_spec.rb +103 -6
  44. data/spec/util_spec.rb +3 -7
  45. metadata +63 -7
@@ -27,11 +27,11 @@ describe Thor::Shell::Basic do
27
27
  it "asks the user and returns true if the user replies yes" do
28
28
  $stdout.should_receive(:print).with("Should I overwrite it? ")
29
29
  $stdin.should_receive(:gets).and_return('y')
30
- shell.yes?("Should I overwrite it?").must be_true
30
+ shell.yes?("Should I overwrite it?").must === true
31
31
 
32
32
  $stdout.should_receive(:print).with("Should I overwrite it? ")
33
33
  $stdin.should_receive(:gets).and_return('n')
34
- shell.yes?("Should I overwrite it?").must_not be_true
34
+ shell.yes?("Should I overwrite it?").must_not === true
35
35
  end
36
36
  end
37
37
 
@@ -39,11 +39,11 @@ describe Thor::Shell::Basic do
39
39
  it "asks the user and returns true if the user replies no" do
40
40
  $stdout.should_receive(:print).with("Should I overwrite it? ")
41
41
  $stdin.should_receive(:gets).and_return('n')
42
- shell.no?("Should I overwrite it?").must be_true
42
+ shell.no?("Should I overwrite it?").must === true
43
43
 
44
44
  $stdout.should_receive(:print).with("Should I overwrite it? ")
45
45
  $stdin.should_receive(:gets).and_return('Yes')
46
- shell.no?("Should I overwrite it?").must be_false
46
+ shell.no?("Should I overwrite it?").must === false
47
47
  end
48
48
  end
49
49
 
@@ -129,6 +129,15 @@ TABLE
129
129
  abc #123 firs...
130
130
  #0 empty
131
131
  xyz #786 last...
132
+ TABLE
133
+ end
134
+
135
+ it "honors the colwidth option" do
136
+ content = capture(:stdout){ shell.print_table(@table, :colwidth => 10)}
137
+ content.must == <<-TABLE
138
+ abc #123 first three
139
+ #0 empty
140
+ xyz #786 last three
132
141
  TABLE
133
142
  end
134
143
  end
@@ -0,0 +1,27 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Thor::Shell::HTML do
4
+ def shell
5
+ @shell ||= Thor::Shell::HTML.new
6
+ end
7
+
8
+ describe "#say" do
9
+ it "set the color if specified" do
10
+ $stdout.should_receive(:puts).with('<span style="color: green;">Wow! Now we have colors!</span>')
11
+ shell.say "Wow! Now we have colors!", :green
12
+ end
13
+
14
+ it "does not use a new line even with colors" do
15
+ $stdout.should_receive(:print).with('<span style="color: green;">Wow! Now we have colors! </span>')
16
+ shell.say "Wow! Now we have colors! ", :green
17
+ end
18
+ end
19
+
20
+ describe "#say_status" do
21
+ it "uses color to say status" do
22
+ $stdout.should_receive(:puts).with('<strong><span style="color: red;"> conflict</span></strong> README')
23
+ shell.say_status :conflict, "README", :red
24
+ end
25
+ end
26
+
27
+ end
data/spec/shell_spec.rb CHANGED
@@ -21,6 +21,18 @@ describe Thor::Shell do
21
21
  it "returns the shell in use" do
22
22
  MyCounter.new([1,2]).shell.must be_kind_of(Thor::Base.shell)
23
23
  end
24
+
25
+ it "uses $THOR_SHELL" do
26
+ class Thor::Shell::TestShell < Thor::Shell::Basic; end
27
+
28
+ Thor::Base.shell.must == shell.class
29
+ ENV['THOR_SHELL'] = 'TestShell'
30
+ Thor::Base.shell = nil
31
+ Thor::Base.shell.must == Thor::Shell::TestShell
32
+ ENV['THOR_SHELL'] = ''
33
+ Thor::Base.shell = shell.class
34
+ Thor::Base.shell.must == shell.class
35
+ end
24
36
  end
25
37
 
26
38
  describe "with_padding" do
@@ -31,4 +43,5 @@ describe Thor::Shell do
31
43
  end
32
44
  end
33
45
  end
46
+
34
47
  end
data/spec/spec_helper.rb CHANGED
@@ -10,7 +10,11 @@ require 'rdoc'
10
10
  require 'diff/lcs' # You need diff/lcs installed to run specs (but not to run Thor).
11
11
  require 'fakeweb' # You need fakeweb installed to run specs (but not to run Thor).
12
12
 
13
+ # Set shell to basic
14
+ $0 = "thor"
13
15
  $thor_runner = true
16
+ ARGV.clear
17
+ Thor::Base.shell = Thor::Shell::Basic
14
18
 
15
19
  # Load fixtures
16
20
  load File.join(File.dirname(__FILE__), "fixtures", "task.thor")
@@ -18,9 +22,6 @@ load File.join(File.dirname(__FILE__), "fixtures", "group.thor")
18
22
  load File.join(File.dirname(__FILE__), "fixtures", "script.thor")
19
23
  load File.join(File.dirname(__FILE__), "fixtures", "invoke.thor")
20
24
 
21
- # Set shell to basic
22
- Thor::Base.shell = Thor::Shell::Basic
23
-
24
25
  Kernel.module_eval do
25
26
  alias_method :must, :should
26
27
  alias_method :must_not, :should_not
data/spec/task_spec.rb CHANGED
@@ -6,7 +6,7 @@ describe Thor::Task do
6
6
  options[key] = Thor::Option.parse(key, value)
7
7
  end
8
8
 
9
- @task ||= Thor::Task.new(:can_has, "I can has cheezburger", "can_has", options)
9
+ @task ||= Thor::Task.new(:can_has, "I can has cheezburger", "I can has cheezburger\nLots and lots of it", "can_has", options)
10
10
  end
11
11
 
12
12
  describe "#formatted_usage" do
@@ -31,22 +31,22 @@ describe Thor::Task do
31
31
 
32
32
  describe "#dynamic" do
33
33
  it "creates a dynamic task with the given name" do
34
- Thor::Task::Dynamic.new('task').name.must == 'task'
35
- Thor::Task::Dynamic.new('task').description.must == 'A dynamically-generated task'
36
- Thor::Task::Dynamic.new('task').usage.must == 'task'
37
- Thor::Task::Dynamic.new('task').options.must == {}
34
+ Thor::DynamicTask.new('task').name.must == 'task'
35
+ Thor::DynamicTask.new('task').description.must == 'A dynamically-generated task'
36
+ Thor::DynamicTask.new('task').usage.must == 'task'
37
+ Thor::DynamicTask.new('task').options.must == {}
38
38
  end
39
39
 
40
40
  it "does not invoke an existing method" do
41
41
  mock = mock()
42
42
  mock.class.should_receive(:handle_no_task_error).with("to_s")
43
- Thor::Task::Dynamic.new('to_s').run(mock)
43
+ Thor::DynamicTask.new('to_s').run(mock)
44
44
  end
45
45
  end
46
46
 
47
47
  describe "#dup" do
48
48
  it "dup options hash" do
49
- task = Thor::Task.new("can_has", nil, nil, :foo => true, :bar => :required)
49
+ task = Thor::Task.new("can_has", nil, nil, nil, :foo => true, :bar => :required)
50
50
  task.dup.options.delete(:foo)
51
51
  task.options[:foo].must_not be_nil
52
52
  end
data/spec/thor_spec.rb CHANGED
@@ -8,6 +8,45 @@ describe Thor do
8
8
  options.must == { "force" => true }
9
9
  end
10
10
 
11
+ describe ":lazy_default" do
12
+ it "is absent when option is not specified" do
13
+ arg, options = MyScript.start(["with_optional"])
14
+ options.must == {}
15
+ end
16
+
17
+ it "sets a default that can be overridden for strings" do
18
+ arg, options = MyScript.start(["with_optional", "--lazy"])
19
+ options.must == { "lazy" => "yes" }
20
+
21
+ arg, options = MyScript.start(["with_optional", "--lazy", "yesyes!"])
22
+ options.must == { "lazy" => "yesyes!" }
23
+ end
24
+
25
+ it "sets a default that can be overridden for numerics" do
26
+ arg, options = MyScript.start(["with_optional", "--lazy-numeric"])
27
+ options.must == { "lazy_numeric" => 42 }
28
+
29
+ arg, options = MyScript.start(["with_optional", "--lazy-numeric", 20000])
30
+ options.must == { "lazy_numeric" => 20000 }
31
+ end
32
+
33
+ it "sets a default that can be overridden for arrays" do
34
+ arg, options = MyScript.start(["with_optional", "--lazy-array"])
35
+ options.must == { "lazy_array" => %w[eat at joes] }
36
+
37
+ arg, options = MyScript.start(["with_optional", "--lazy-array", "hello", "there"])
38
+ options.must == { "lazy_array" => %w[hello there] }
39
+ end
40
+
41
+ it "sets a default that can be overridden for hashes" do
42
+ arg, options = MyScript.start(["with_optional", "--lazy-hash"])
43
+ options.must == { "lazy_hash" => {'swedish' => 'meatballs'} }
44
+
45
+ arg, options = MyScript.start(["with_optional", "--lazy-hash", "polish:sausage"])
46
+ options.must == { "lazy_hash" => {'polish' => 'sausage'} }
47
+ end
48
+ end
49
+
11
50
  describe "when :for is supplied" do
12
51
  it "updates an already defined task" do
13
52
  args, options = MyChildScript.start(["animal", "horse", "--other=fish"])
@@ -41,6 +80,10 @@ describe Thor do
41
80
  MyScript.start([]).must == "default task"
42
81
  end
43
82
 
83
+ it "invokes the default task if no command is specified even if switches are given" do
84
+ MyScript.start(["--with", "option"]).must == {"with"=>"option"}
85
+ end
86
+
44
87
  it "inherits the default task from parent" do
45
88
  MyChildScript.default_task.must == "example_default_task"
46
89
  end
@@ -62,12 +105,19 @@ describe Thor do
62
105
  end
63
106
 
64
107
  describe "#desc" do
65
- before(:all) do
66
- @content = capture(:stdout) { MyScript.start(["help"]) }
108
+ it "provides description for a task" do
109
+ content = capture(:stdout) { MyScript.start(["help"]) }
110
+ content.must =~ /thor my_script:zoo\s+# zoo around/m
67
111
  end
68
112
 
69
- it "provides description for a task" do
70
- @content.must =~ /zoo\s+# zoo around/m
113
+ it "provides no namespace if $thor_runner is false" do
114
+ begin
115
+ $thor_runner = false
116
+ content = capture(:stdout) { MyScript.start(["help"]) }
117
+ content.must =~ /thor zoo\s+# zoo around/m
118
+ ensure
119
+ $thor_runner = true
120
+ end
71
121
  end
72
122
 
73
123
  describe "when :for is supplied" do
@@ -75,6 +125,16 @@ describe Thor do
75
125
  capture(:stdout) { MyChildScript.start(["help"]) }.must =~ /animal KIND \s+# fish around/m
76
126
  end
77
127
  end
128
+
129
+ describe "when :hide is supplied" do
130
+ it "does not show the task in help" do
131
+ capture(:stdout) { MyScript.start(["help"]) }.must_not =~ /this is hidden/m
132
+ end
133
+
134
+ it "but the task is still invokcable not show the task in help" do
135
+ MyScript.start(["hidden", "yesyes"]).must == ["yesyes"]
136
+ end
137
+ end
78
138
  end
79
139
 
80
140
  describe "#method_options" do
@@ -112,7 +172,7 @@ describe Thor do
112
172
  end
113
173
 
114
174
  it "raises an error if a required param is not provided" do
115
- capture(:stderr) { MyScript.start(["animal"]) }.strip.must == '"animal" was called incorrectly. Call as "my_script:animal TYPE".'
175
+ capture(:stderr) { MyScript.start(["animal"]) }.strip.must == '"animal" was called incorrectly. Call as "thor my_script:animal TYPE".'
116
176
  end
117
177
 
118
178
  it "raises an error if the invoked task does not exist" do
@@ -137,6 +197,25 @@ describe Thor do
137
197
  end
138
198
  end
139
199
 
200
+ describe "#subcommand" do
201
+ it "maps a given subcommand to another Thor subclass" do
202
+ barn_help = capture(:stdout){ Scripts::MyDefaults.start(["barn"]) }
203
+ barn_help.must include("barn help [COMMAND] # Describe subcommands or one specific subcommand")
204
+ end
205
+
206
+ it "passes commands to subcommand classes" do
207
+ capture(:stdout){ Scripts::MyDefaults.start(["barn", "open"]) }.strip.must == "Open sesame!"
208
+ end
209
+
210
+ it "passes arguments to subcommand classes" do
211
+ capture(:stdout){ Scripts::MyDefaults.start(["barn", "open", "shotgun"]) }.strip.must == "That's going to leave a mark."
212
+ end
213
+
214
+ it "ignores unknown options (the subcommand class will handle them)" do
215
+ capture(:stdout){ Scripts::MyDefaults.start(["barn", "paint", "blue", "--coats", "4"])}.strip.must == "4 coats of blue paint"
216
+ end
217
+ end
218
+
140
219
  describe "#help" do
141
220
  def shell
142
221
  @shell ||= Thor::Base.shell.new
@@ -184,7 +263,7 @@ describe Thor do
184
263
 
185
264
  describe "for a specific task" do
186
265
  it "provides full help info when talking about a specific task" do
187
- capture(:stdout) { MyScript.task_help(shell, "foo") }.must == <<END
266
+ capture(:stdout) { MyScript.task_help(shell, "foo") }.must == <<-END
188
267
  Usage:
189
268
  thor my_script:foo BAR
190
269
 
@@ -206,6 +285,24 @@ END
206
285
  it "normalizes names before claiming they don't exist" do
207
286
  capture(:stdout) { MyScript.task_help(shell, "name-with-dashes") }.must =~ /thor my_script:name-with-dashes/
208
287
  end
288
+
289
+ it "uses the long description if it exists" do
290
+ capture(:stdout) { MyScript.task_help(shell, "long_description") }.must == <<-HELP
291
+ Usage:
292
+ thor my_script:long_description
293
+
294
+ Description:
295
+ This is a really really really long description. Here you go. So very long.
296
+
297
+ It even has two paragraphs.
298
+ HELP
299
+ end
300
+
301
+ it "doesn't assign the long description to the next task without one" do
302
+ capture(:stdout) do
303
+ MyScript.task_help(shell, "name_with_dashes")
304
+ end.must_not =~ /so very long/i
305
+ end
209
306
  end
210
307
 
211
308
  describe "instance method" do
data/spec/util_spec.rb CHANGED
@@ -100,18 +100,14 @@ describe Thor::Util do
100
100
  Thor::Util.find_class_and_task_by_namespace("thor:help").must == [Thor, "help"]
101
101
  end
102
102
 
103
- it "fallbacks in the namespace:task look up even if a full namespace does not match" do
103
+ it "falls back in the namespace:task look up even if a full namespace does not match" do
104
104
  Thor.const_set(:Help, Module.new)
105
105
  Thor::Util.find_class_and_task_by_namespace("thor:help").must == [Thor, "help"]
106
106
  Thor.send :remove_const, :Help
107
107
  end
108
108
 
109
- describe 'errors' do
110
- it "raises an error if the Thor class or task can't be found" do
111
- lambda {
112
- Thor::Util.find_class_and_task_by_namespace!("foobar")
113
- }.must raise_error(Thor::Error, 'Could not find namespace or task "foobar".')
114
- end
109
+ it "falls back on the default namespace class if nothing else matches" do
110
+ Thor::Util.find_class_and_task_by_namespace("test").must == [Scripts::MyDefaults, "test"]
115
111
  end
116
112
  end
117
113
 
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.4
4
+ hash: 33
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 14
9
+ - 3
10
+ version: 0.14.3
5
11
  platform: ruby
6
12
  authors:
7
13
  - Yehuda Katz
@@ -10,7 +16,7 @@ autorequire:
10
16
  bindir: bin
11
17
  cert_chain: []
12
18
 
13
- date: 2010-02-26 00:00:00 +01:00
19
+ date: 2010-10-04 00:00:00 +02:00
14
20
  default_executable:
15
21
  dependencies: []
16
22
 
@@ -24,12 +30,12 @@ extensions: []
24
30
  extra_rdoc_files:
25
31
  - CHANGELOG.rdoc
26
32
  - LICENSE
27
- - README.rdoc
33
+ - README.md
28
34
  - Thorfile
29
35
  files:
30
36
  - CHANGELOG.rdoc
31
37
  - LICENSE
32
- - README.rdoc
38
+ - README.md
33
39
  - Thorfile
34
40
  - bin/rake2thor
35
41
  - bin/thor
@@ -57,9 +63,49 @@ files:
57
63
  - lib/thor/shell.rb
58
64
  - lib/thor/shell/basic.rb
59
65
  - lib/thor/shell/color.rb
66
+ - lib/thor/shell/html.rb
60
67
  - lib/thor/task.rb
61
68
  - lib/thor/util.rb
62
69
  - lib/thor/version.rb
70
+ - spec/actions/create_file_spec.rb
71
+ - spec/actions/directory_spec.rb
72
+ - spec/actions/empty_directory_spec.rb
73
+ - spec/actions/file_manipulation_spec.rb
74
+ - spec/actions/inject_into_file_spec.rb
75
+ - spec/actions_spec.rb
76
+ - spec/base_spec.rb
77
+ - spec/core_ext/hash_with_indifferent_access_spec.rb
78
+ - spec/core_ext/ordered_hash_spec.rb
79
+ - spec/fixtures/application.rb
80
+ - spec/fixtures/bundle/execute.rb
81
+ - spec/fixtures/doc/block_helper.rb
82
+ - spec/fixtures/doc/config.rb
83
+ - spec/group_spec.rb
84
+ - spec/invocation_spec.rb
85
+ - spec/parser/argument_spec.rb
86
+ - spec/parser/arguments_spec.rb
87
+ - spec/parser/option_spec.rb
88
+ - spec/parser/options_spec.rb
89
+ - spec/rake_compat_spec.rb
90
+ - spec/runner_spec.rb
91
+ - spec/shell/basic_spec.rb
92
+ - spec/shell/color_spec.rb
93
+ - spec/shell/html_spec.rb
94
+ - spec/shell_spec.rb
95
+ - spec/spec_helper.rb
96
+ - spec/task_spec.rb
97
+ - spec/thor_spec.rb
98
+ - spec/util_spec.rb
99
+ - spec/fixtures/bundle/main.thor
100
+ - spec/fixtures/doc/%file_name%.rb.tt
101
+ - spec/fixtures/doc/README
102
+ - spec/fixtures/group.thor
103
+ - spec/fixtures/invoke.thor
104
+ - spec/fixtures/path with spaces
105
+ - spec/fixtures/script.thor
106
+ - spec/fixtures/task.thor
107
+ - spec/spec.opts
108
+ - spec/fixtures/doc/components/.empty_directory
63
109
  has_rdoc: true
64
110
  homepage: http://yehudakatz.com
65
111
  licenses: []
@@ -70,21 +116,27 @@ rdoc_options:
70
116
  require_paths:
71
117
  - lib
72
118
  required_ruby_version: !ruby/object:Gem::Requirement
119
+ none: false
73
120
  requirements:
74
121
  - - ">="
75
122
  - !ruby/object:Gem::Version
123
+ hash: 3
124
+ segments:
125
+ - 0
76
126
  version: "0"
77
- version:
78
127
  required_rubygems_version: !ruby/object:Gem::Requirement
128
+ none: false
79
129
  requirements:
80
130
  - - ">="
81
131
  - !ruby/object:Gem::Version
132
+ hash: 3
133
+ segments:
134
+ - 0
82
135
  version: "0"
83
- version:
84
136
  requirements: []
85
137
 
86
138
  rubyforge_project: textmate
87
- rubygems_version: 1.3.5
139
+ rubygems_version: 1.3.7
88
140
  signing_key:
89
141
  specification_version: 3
90
142
  summary: A scripting framework that replaces rake, sake and rubigen
@@ -100,6 +152,7 @@ test_files:
100
152
  - spec/core_ext/ordered_hash_spec.rb
101
153
  - spec/fixtures/application.rb
102
154
  - spec/fixtures/bundle/execute.rb
155
+ - spec/fixtures/doc/block_helper.rb
103
156
  - spec/fixtures/doc/config.rb
104
157
  - spec/group_spec.rb
105
158
  - spec/invocation_spec.rb
@@ -111,6 +164,7 @@ test_files:
111
164
  - spec/runner_spec.rb
112
165
  - spec/shell/basic_spec.rb
113
166
  - spec/shell/color_spec.rb
167
+ - spec/shell/html_spec.rb
114
168
  - spec/shell_spec.rb
115
169
  - spec/spec_helper.rb
116
170
  - spec/task_spec.rb
@@ -121,6 +175,8 @@ test_files:
121
175
  - spec/fixtures/doc/README
122
176
  - spec/fixtures/group.thor
123
177
  - spec/fixtures/invoke.thor
178
+ - spec/fixtures/path with spaces
124
179
  - spec/fixtures/script.thor
125
180
  - spec/fixtures/task.thor
126
181
  - spec/spec.opts
182
+ - spec/fixtures/doc/components/.empty_directory