thor 0.11.5 → 0.11.6
Sign up to get free protection for your applications and to get access to all the features.
- data/Thorfile +0 -1
- data/VERSION +1 -1
- data/lib/thor.rb +1 -1
- data/lib/thor/actions.rb +16 -15
- data/lib/thor/actions/file_manipulation.rb +41 -17
- data/lib/thor/actions/inject_into_file.rb +43 -20
- data/lib/thor/base.rb +7 -0
- data/lib/thor/invocation.rb +1 -1
- data/lib/thor/runner.rb +4 -0
- data/lib/thor/shell/basic.rb +2 -3
- data/lib/thor/task.rb +13 -7
- data/lib/thor/util.rb +8 -7
- data/spec/actions/file_manipulation_spec.rb +25 -18
- data/spec/actions/inject_into_file_spec.rb +30 -4
- data/spec/fixtures/application.rb +2 -0
- data/spec/runner_spec.rb +2 -2
- data/spec/shell/basic_spec.rb +5 -0
- data/spec/task_spec.rb +10 -4
- metadata +4 -3
data/Thorfile
CHANGED
@@ -34,7 +34,6 @@ class Default < Thor
|
|
34
34
|
require 'jeweler'
|
35
35
|
Jeweler::Tasks.new do |s|
|
36
36
|
s.name = GEM_NAME
|
37
|
-
s.version = "0.11.4"
|
38
37
|
s.rubyforge_project = "textmate"
|
39
38
|
s.platform = Gem::Platform::RUBY
|
40
39
|
s.summary = "A scripting framework that replaces rake, sake and rubigen"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.11.
|
1
|
+
0.11.6
|
data/lib/thor.rb
CHANGED
data/lib/thor/actions.rb
CHANGED
@@ -8,23 +8,8 @@ class Thor
|
|
8
8
|
module Actions
|
9
9
|
attr_accessor :behavior
|
10
10
|
|
11
|
-
# On inclusion, add some options to base.
|
12
|
-
#
|
13
11
|
def self.included(base) #:nodoc:
|
14
12
|
base.extend ClassMethods
|
15
|
-
return unless base.respond_to?(:class_option)
|
16
|
-
|
17
|
-
base.class_option :pretend, :type => :boolean, :aliases => "-p", :group => :runtime,
|
18
|
-
:desc => "Run but do not make any changes"
|
19
|
-
|
20
|
-
base.class_option :force, :type => :boolean, :aliases => "-f", :group => :runtime,
|
21
|
-
:desc => "Overwrite files that already exist"
|
22
|
-
|
23
|
-
base.class_option :skip, :type => :boolean, :aliases => "-s", :group => :runtime,
|
24
|
-
:desc => "Skip files that already exist"
|
25
|
-
|
26
|
-
base.class_option :quiet, :type => :boolean, :aliases => "-q", :group => :runtime,
|
27
|
-
:desc => "Supress status output"
|
28
13
|
end
|
29
14
|
|
30
15
|
module ClassMethods
|
@@ -49,6 +34,22 @@ class Thor
|
|
49
34
|
paths += from_superclass(:source_paths, [])
|
50
35
|
paths
|
51
36
|
end
|
37
|
+
|
38
|
+
# Add runtime options that help actions execution.
|
39
|
+
#
|
40
|
+
def add_runtime_options!
|
41
|
+
class_option :pretend, :type => :boolean, :aliases => "-p", :group => :runtime,
|
42
|
+
:desc => "Run but do not make any changes"
|
43
|
+
|
44
|
+
class_option :force, :type => :boolean, :aliases => "-f", :group => :runtime,
|
45
|
+
:desc => "Overwrite files that already exist"
|
46
|
+
|
47
|
+
class_option :skip, :type => :boolean, :aliases => "-s", :group => :runtime,
|
48
|
+
:desc => "Skip files that already exist"
|
49
|
+
|
50
|
+
class_option :quiet, :type => :boolean, :aliases => "-q", :group => :runtime,
|
51
|
+
:desc => "Supress status output"
|
52
|
+
end
|
52
53
|
end
|
53
54
|
|
54
55
|
# Extends initializer to add more configuration options.
|
@@ -100,7 +100,7 @@ class Thor
|
|
100
100
|
FileUtils.chmod_R(mode, path) unless options[:pretend]
|
101
101
|
end
|
102
102
|
|
103
|
-
# Prepend text to a file.
|
103
|
+
# Prepend text to a file. Since it depends on inject_into_file, it's reversible.
|
104
104
|
#
|
105
105
|
# ==== Parameters
|
106
106
|
# path<String>:: path of the file to be changed
|
@@ -111,19 +111,17 @@ class Thor
|
|
111
111
|
#
|
112
112
|
# prepend_file 'config/environments/test.rb', 'config.gem "rspec"'
|
113
113
|
#
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
File.open(path, 'wb') { |file| file.write(content) }
|
123
|
-
end
|
114
|
+
# prepend_file 'config/environments/test.rb' do
|
115
|
+
# 'config.gem "rspec"'
|
116
|
+
# end
|
117
|
+
#
|
118
|
+
def prepend_file(path, *args, &block)
|
119
|
+
config = args.last.is_a?(Hash) ? args.pop : {}
|
120
|
+
config.merge!(:after => /\A/)
|
121
|
+
inject_into_file(path, *(args << config), &block)
|
124
122
|
end
|
125
123
|
|
126
|
-
# Append text to a file.
|
124
|
+
# Append text to a file. Since it depends on inject_into_file, it's reversible.
|
127
125
|
#
|
128
126
|
# ==== Parameters
|
129
127
|
# path<String>:: path of the file to be changed
|
@@ -134,11 +132,37 @@ class Thor
|
|
134
132
|
#
|
135
133
|
# append_file 'config/environments/test.rb', 'config.gem "rspec"'
|
136
134
|
#
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
135
|
+
# append_file 'config/environments/test.rb' do
|
136
|
+
# 'config.gem "rspec"'
|
137
|
+
# end
|
138
|
+
#
|
139
|
+
def append_file(path, *args, &block)
|
140
|
+
config = args.last.is_a?(Hash) ? args.pop : {}
|
141
|
+
config.merge!(:before => /\z/)
|
142
|
+
inject_into_file(path, *(args << config), &block)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Injects text right after the class definition. Since it depends on
|
146
|
+
# inject_into_file, it's reversible.
|
147
|
+
#
|
148
|
+
# ==== Parameters
|
149
|
+
# path<String>:: path of the file to be changed
|
150
|
+
# klass<String|Class>:: the class to be manipulated
|
151
|
+
# data<String>:: the data to append to the class, can be also given as a block.
|
152
|
+
# config<Hash>:: give :verbose => false to not log the status.
|
153
|
+
#
|
154
|
+
# ==== Examples
|
155
|
+
#
|
156
|
+
# inject_into_class "app/controllers/application_controller.rb", " filter_parameter :password\n"
|
157
|
+
#
|
158
|
+
# inject_into_class "app/controllers/application_controller.rb", ApplicationController do
|
159
|
+
# " filter_parameter :password\n"
|
160
|
+
# end
|
161
|
+
#
|
162
|
+
def inject_into_class(path, klass, *args, &block)
|
163
|
+
config = args.last.is_a?(Hash) ? args.pop : {}
|
164
|
+
config.merge!(:after => /class #{klass}\n|class #{klass} .*\n/)
|
165
|
+
inject_into_file(path, *(args << config), &block)
|
142
166
|
end
|
143
167
|
|
144
168
|
# Run a regular expression replacement on a file.
|
@@ -3,10 +3,8 @@ require 'thor/actions/empty_directory'
|
|
3
3
|
class Thor
|
4
4
|
module Actions
|
5
5
|
|
6
|
-
# Injects the given content into a file. Different from
|
7
|
-
#
|
8
|
-
# the flag can only be strings. gsub_file is your friend if you need to
|
9
|
-
# deal with more complex cases.
|
6
|
+
# Injects the given content into a file. Different from gsub_file, this
|
7
|
+
# method is reversible.
|
10
8
|
#
|
11
9
|
# ==== Parameters
|
12
10
|
# destination<String>:: Relative path to the destination root
|
@@ -16,11 +14,11 @@ class Thor
|
|
16
14
|
#
|
17
15
|
# ==== Examples
|
18
16
|
#
|
19
|
-
# inject_into_file "config/environment.rb", "config.gem thor", :after => "Rails::Initializer.run do |config|\n"
|
17
|
+
# inject_into_file "config/environment.rb", "config.gem :thor", :after => "Rails::Initializer.run do |config|\n"
|
20
18
|
#
|
21
19
|
# inject_into_file "config/environment.rb", :after => "Rails::Initializer.run do |config|\n" do
|
22
20
|
# gems = ask "Which gems would you like to add?"
|
23
|
-
# gems.split(" ").map{ |gem| " config.gem
|
21
|
+
# gems.split(" ").map{ |gem| " config.gem :#{gem}" }.join("\n")
|
24
22
|
# end
|
25
23
|
#
|
26
24
|
def inject_into_file(destination, *args, &block)
|
@@ -29,40 +27,65 @@ class Thor
|
|
29
27
|
else
|
30
28
|
data, config = args.shift, args.shift
|
31
29
|
end
|
32
|
-
|
33
|
-
log_status = args.empty? || args.pop
|
34
30
|
action InjectIntoFile.new(self, destination, data, config)
|
35
31
|
end
|
36
32
|
|
37
33
|
class InjectIntoFile < EmptyDirectory #:nodoc:
|
38
|
-
attr_reader :flag, :
|
34
|
+
attr_reader :replacement, :flag, :behavior
|
39
35
|
|
40
36
|
def initialize(base, destination, data, config)
|
41
37
|
super(base, destination, { :verbose => true }.merge(config))
|
42
38
|
|
43
|
-
|
44
|
-
|
45
|
-
@replacement = if @config.key?(:after)
|
46
|
-
@flag = @config.delete(:after)
|
47
|
-
@flag + data
|
39
|
+
@behavior, @flag = if @config.key?(:after)
|
40
|
+
[:after, @config.delete(:after)]
|
48
41
|
else
|
49
|
-
|
50
|
-
data + @flag
|
42
|
+
[:before, @config.delete(:before)]
|
51
43
|
end
|
44
|
+
|
45
|
+
@replacement = data.is_a?(Proc) ? data.call : data
|
46
|
+
@flag = Regexp.escape(@flag) unless @flag.is_a?(Regexp)
|
52
47
|
end
|
53
48
|
|
54
49
|
def invoke!
|
55
|
-
say_status :
|
56
|
-
|
50
|
+
say_status :invoke
|
51
|
+
|
52
|
+
content = if @behavior == :after
|
53
|
+
'\0' + replacement
|
54
|
+
else
|
55
|
+
replacement + '\0'
|
56
|
+
end
|
57
|
+
|
58
|
+
replace!(/#{flag}/, content)
|
57
59
|
end
|
58
60
|
|
59
61
|
def revoke!
|
60
|
-
say_status :
|
61
|
-
|
62
|
+
say_status :revoke
|
63
|
+
|
64
|
+
regexp = if @behavior == :after
|
65
|
+
content = '\1\2'
|
66
|
+
/(#{flag})(.*)(#{Regexp.escape(replacement)})/m
|
67
|
+
else
|
68
|
+
content = '\2\3'
|
69
|
+
/(#{Regexp.escape(replacement)})(.*)(#{flag})/m
|
70
|
+
end
|
71
|
+
|
72
|
+
replace!(regexp, content)
|
62
73
|
end
|
63
74
|
|
64
75
|
protected
|
65
76
|
|
77
|
+
def say_status(behavior)
|
78
|
+
status = if flag == /\A/
|
79
|
+
behavior == :invoke ? :prepend : :unprepend
|
80
|
+
elsif flag == /\z/
|
81
|
+
behavior == :invoke ? :append : :unappend
|
82
|
+
else
|
83
|
+
behavior == :invoke ? :inject : :deinject
|
84
|
+
end
|
85
|
+
|
86
|
+
super(status, config[:verbose])
|
87
|
+
end
|
88
|
+
|
66
89
|
# Adds the content to the file.
|
67
90
|
#
|
68
91
|
def replace!(regexp, string)
|
data/lib/thor/base.rb
CHANGED
@@ -355,6 +355,7 @@ class Thor
|
|
355
355
|
else
|
356
356
|
config[:shell].error e.message
|
357
357
|
end
|
358
|
+
exit(1) if exit_on_failure?
|
358
359
|
end
|
359
360
|
|
360
361
|
protected
|
@@ -491,6 +492,12 @@ class Thor
|
|
491
492
|
end
|
492
493
|
end
|
493
494
|
|
495
|
+
# A flag that makes the process exit with status 1 if any error happens.
|
496
|
+
#
|
497
|
+
def exit_on_failure?
|
498
|
+
false
|
499
|
+
end
|
500
|
+
|
494
501
|
# SIGNATURE: Sets the baseclass. This is where the superclass lookup
|
495
502
|
# finishes.
|
496
503
|
def baseclass #:nodoc:
|
data/lib/thor/invocation.rb
CHANGED
@@ -153,7 +153,7 @@ class Thor
|
|
153
153
|
raise "Expected Thor class, got #{klass}" unless klass <= Thor::Base
|
154
154
|
|
155
155
|
task ||= klass.default_task if klass <= Thor
|
156
|
-
task = klass.all_tasks[task.to_s] || Task.
|
156
|
+
task = klass.all_tasks[task.to_s] || Thor::Task::Dynamic.new(task) if task && !task.is_a?(Thor::Task)
|
157
157
|
task
|
158
158
|
end
|
159
159
|
|
data/lib/thor/runner.rb
CHANGED
@@ -175,6 +175,10 @@ class Thor::Runner < Thor #:nodoc:
|
|
175
175
|
File.open(yaml_file, "w") { |f| f.puts yaml.to_yaml }
|
176
176
|
end
|
177
177
|
|
178
|
+
def self.exit_on_failure?
|
179
|
+
true
|
180
|
+
end
|
181
|
+
|
178
182
|
# Load the thorfiles. If relevant_to is supplied, looks for specific files
|
179
183
|
# in the thor_root instead of loading them all.
|
180
184
|
#
|
data/lib/thor/shell/basic.rb
CHANGED
@@ -34,12 +34,11 @@ class Thor
|
|
34
34
|
# ==== Example
|
35
35
|
# say("I know you knew that.")
|
36
36
|
#
|
37
|
-
def say(message="", color=nil, force_new_line=
|
37
|
+
def say(message="", color=nil, force_new_line=(message.to_s !~ /( |\t)$/))
|
38
38
|
message = message.to_s
|
39
|
-
new_line = force_new_line || !(message[-1, 1] == " " || message[-1, 1] == "\t")
|
40
39
|
message = set_color(message, color) if color
|
41
40
|
|
42
|
-
if
|
41
|
+
if force_new_line
|
43
42
|
$stdout.puts(message)
|
44
43
|
else
|
45
44
|
$stdout.print(message)
|
data/lib/thor/task.rb
CHANGED
@@ -1,11 +1,19 @@
|
|
1
1
|
class Thor
|
2
2
|
class Task < Struct.new(:name, :description, :usage, :options)
|
3
3
|
|
4
|
-
#
|
5
|
-
# missing calls (since a method missing does not have a task object for it).
|
4
|
+
# A dynamic task that handles method missing scenarios.
|
6
5
|
#
|
7
|
-
|
8
|
-
|
6
|
+
class Dynamic < Task
|
7
|
+
def initialize(name)
|
8
|
+
super(name.to_s, "A dynamically-generated task", name.to_s)
|
9
|
+
end
|
10
|
+
|
11
|
+
def run(instance, args=[])
|
12
|
+
unless (instance.methods & [name.to_s, name.to_sym]).empty?
|
13
|
+
raise Error, "could not find Thor class or task '#{name}'"
|
14
|
+
end
|
15
|
+
super
|
16
|
+
end
|
9
17
|
end
|
10
18
|
|
11
19
|
def initialize(name, description, usage, options=nil)
|
@@ -37,8 +45,6 @@ class Thor
|
|
37
45
|
# injected in the usage.
|
38
46
|
#
|
39
47
|
def formatted_usage(klass=nil, namespace=false, show_options=true)
|
40
|
-
formatted = ''
|
41
|
-
|
42
48
|
formatted = if namespace.is_a?(String)
|
43
49
|
"#{namespace}:"
|
44
50
|
elsif klass && namespace
|
@@ -77,7 +83,7 @@ class Thor
|
|
77
83
|
#
|
78
84
|
def public_method?(instance) #:nodoc:
|
79
85
|
collection = instance.private_methods + instance.protected_methods
|
80
|
-
|
86
|
+
(collection & [name.to_s, name.to_sym]).empty?
|
81
87
|
end
|
82
88
|
|
83
89
|
# Clean everything that comes from the Thor gempath and remove the caller.
|
data/lib/thor/util.rb
CHANGED
@@ -137,17 +137,18 @@ class Thor
|
|
137
137
|
# inherit from Thor or Thor::Group.
|
138
138
|
#
|
139
139
|
def self.namespace_to_thor_class_and_task(namespace, raise_if_nil=true)
|
140
|
-
|
140
|
+
if namespace.include?(?:)
|
141
|
+
pieces = namespace.split(":")
|
142
|
+
task = pieces.pop
|
143
|
+
klass = Thor::Util.find_by_namespace(pieces.join(":"))
|
144
|
+
end
|
141
145
|
|
142
|
-
|
143
|
-
|
144
|
-
task_name = namespace.pop
|
145
|
-
klass = Thor::Util.find_by_namespace(namespace.join(":"))
|
146
|
+
unless klass
|
147
|
+
klass, task = Thor::Util.find_by_namespace(namespace), nil
|
146
148
|
end
|
147
149
|
|
148
150
|
raise Error, "could not find Thor class or task '#{namespace}'" if raise_if_nil && klass.nil?
|
149
|
-
|
150
|
-
return klass, task_name
|
151
|
+
return klass, task
|
151
152
|
end
|
152
153
|
|
153
154
|
# Receives a path and load the thor file in the path. The file is evaluated
|
@@ -1,5 +1,7 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
2
|
|
3
|
+
class Application; end
|
4
|
+
|
3
5
|
describe Thor::Actions do
|
4
6
|
def runner(options={})
|
5
7
|
@runner ||= MyCounter.new([1], options, { :destination_root => destination_root })
|
@@ -193,12 +195,6 @@ describe Thor::Actions do
|
|
193
195
|
File.open(file).read.must == "__start__\nREADME\n__end__\nEND\n"
|
194
196
|
end
|
195
197
|
|
196
|
-
it "does not append if pretending" do
|
197
|
-
runner(:pretend => true)
|
198
|
-
action :append_file, "doc/README", "END\n"
|
199
|
-
File.open(file).read.must == "__start__\nREADME\n__end__\n"
|
200
|
-
end
|
201
|
-
|
202
198
|
it "accepts a block" do
|
203
199
|
action(:append_file, "doc/README"){ "END\n" }
|
204
200
|
File.open(file).read.must == "__start__\nREADME\n__end__\nEND\n"
|
@@ -207,10 +203,6 @@ describe Thor::Actions do
|
|
207
203
|
it "logs status" do
|
208
204
|
action(:append_file, "doc/README", "END").must == " append doc/README\n"
|
209
205
|
end
|
210
|
-
|
211
|
-
it "does not log status if required" do
|
212
|
-
action(:append_file, "doc/README", nil, :verbose => false){ "END" }.must be_empty
|
213
|
-
end
|
214
206
|
end
|
215
207
|
|
216
208
|
describe "#prepend_file" do
|
@@ -219,12 +211,6 @@ describe Thor::Actions do
|
|
219
211
|
File.open(file).read.must == "START\n__start__\nREADME\n__end__\n"
|
220
212
|
end
|
221
213
|
|
222
|
-
it "does not prepend if pretending" do
|
223
|
-
runner(:pretend => true)
|
224
|
-
action :prepend_file, "doc/README", "START\n"
|
225
|
-
File.open(file).read.must == "__start__\nREADME\n__end__\n"
|
226
|
-
end
|
227
|
-
|
228
214
|
it "accepts a block" do
|
229
215
|
action(:prepend_file, "doc/README"){ "START\n" }
|
230
216
|
File.open(file).read.must == "START\n__start__\nREADME\n__end__\n"
|
@@ -233,9 +219,30 @@ describe Thor::Actions do
|
|
233
219
|
it "logs status" do
|
234
220
|
action(:prepend_file, "doc/README", "START").must == " prepend doc/README\n"
|
235
221
|
end
|
222
|
+
end
|
236
223
|
|
237
|
-
|
238
|
-
|
224
|
+
describe "#inject_into_class" do
|
225
|
+
def file
|
226
|
+
File.join(destination_root, "application.rb")
|
227
|
+
end
|
228
|
+
|
229
|
+
it "appends content to a class" do
|
230
|
+
action :inject_into_class, "application.rb", Application, " filter_parameters :password\n"
|
231
|
+
File.open(file).read.must == "class Application < Base\n filter_parameters :password\nend\n"
|
232
|
+
end
|
233
|
+
|
234
|
+
it "accepts a block" do
|
235
|
+
action(:inject_into_class, "application.rb", Application){ " filter_parameters :password\n" }
|
236
|
+
File.open(file).read.must == "class Application < Base\n filter_parameters :password\nend\n"
|
237
|
+
end
|
238
|
+
|
239
|
+
it "logs status" do
|
240
|
+
action(:inject_into_class, "application.rb", Application, " filter_parameters :password\n").must == " inject application.rb\n"
|
241
|
+
end
|
242
|
+
|
243
|
+
it "does not append if class name does not match" do
|
244
|
+
action :inject_into_class, "application.rb", "App", " filter_parameters :password\n"
|
245
|
+
File.open(file).read.must == "class Application < Base\nend\n"
|
239
246
|
end
|
240
247
|
end
|
241
248
|
end
|
@@ -61,17 +61,43 @@ describe Thor::Actions::InjectIntoFile do
|
|
61
61
|
it "deinjects the destination file after injection" do
|
62
62
|
invoke! "doc/README", "\nmore content", :after => "__start__"
|
63
63
|
revoke! "doc/README", "\nmore content", :after => "__start__"
|
64
|
-
|
65
64
|
File.read(file).must == "__start__\nREADME\n__end__\n"
|
66
65
|
end
|
67
66
|
|
68
67
|
it "deinjects the destination file before injection" do
|
69
|
-
invoke! "doc/README", "
|
70
|
-
revoke! "doc/README", "
|
71
|
-
|
68
|
+
invoke! "doc/README", "more content\n", :before => "__start__"
|
69
|
+
revoke! "doc/README", "more content\n", :before => "__start__"
|
72
70
|
File.read(file).must == "__start__\nREADME\n__end__\n"
|
73
71
|
end
|
74
72
|
|
73
|
+
it "deinjects even with double after injection" do
|
74
|
+
invoke! "doc/README", "\nmore content", :after => "__start__"
|
75
|
+
invoke! "doc/README", "\nanother stuff", :after => "__start__"
|
76
|
+
revoke! "doc/README", "\nmore content", :after => "__start__"
|
77
|
+
File.read(file).must == "__start__\nanother stuff\nREADME\n__end__\n"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "deinjects even with double before injection" do
|
81
|
+
invoke! "doc/README", "more content\n", :before => "__start__"
|
82
|
+
invoke! "doc/README", "another stuff\n", :before => "__start__"
|
83
|
+
revoke! "doc/README", "more content\n", :before => "__start__"
|
84
|
+
File.read(file).must == "another stuff\n__start__\nREADME\n__end__\n"
|
85
|
+
end
|
86
|
+
|
87
|
+
it "deinjects when prepending" do
|
88
|
+
invoke! "doc/README", "more content\n", :after => /\A/
|
89
|
+
invoke! "doc/README", "another stuff\n", :after => /\A/
|
90
|
+
revoke! "doc/README", "more content\n", :after => /\A/
|
91
|
+
File.read(file).must == "another stuff\n__start__\nREADME\n__end__\n"
|
92
|
+
end
|
93
|
+
|
94
|
+
it "deinjects when appending" do
|
95
|
+
invoke! "doc/README", "more content\n", :before => /\z/
|
96
|
+
invoke! "doc/README", "another stuff\n", :before => /\z/
|
97
|
+
revoke! "doc/README", "more content\n", :before => /\z/
|
98
|
+
File.read(file).must == "__start__\nREADME\n__end__\nanother stuff\n"
|
99
|
+
end
|
100
|
+
|
75
101
|
it "shows progress information to the user" do
|
76
102
|
invoke!("doc/README", "\nmore content", :after => "__start__")
|
77
103
|
revoke!("doc/README", "\nmore content", :after => "__start__").must == " deinject doc/README\n"
|
data/spec/runner_spec.rb
CHANGED
@@ -30,6 +30,7 @@ describe Thor::Runner do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
it "raises error if a class/task cannot be found" do
|
33
|
+
mock(Thor::Runner).exit(1)
|
33
34
|
content = capture(:stderr){ Thor::Runner.start(["help", "unknown"]) }
|
34
35
|
content.must =~ /could not find Thor class or task 'unknown'/
|
35
36
|
end
|
@@ -67,6 +68,7 @@ describe Thor::Runner do
|
|
67
68
|
end
|
68
69
|
|
69
70
|
it "raises an error if class/task can't be found" do
|
71
|
+
mock(Thor::Runner).exit(1)
|
70
72
|
ARGV.replace ["unknown"]
|
71
73
|
capture(:stderr){ Thor::Runner.start }.must =~ /could not find Thor class or task 'unknown'/
|
72
74
|
end
|
@@ -180,10 +182,8 @@ describe Thor::Runner do
|
|
180
182
|
|
181
183
|
it "displays the modules installed in a pretty way" do
|
182
184
|
stdout = capture(:stdout) { Thor::Runner.start(["installed"]) }
|
183
|
-
|
184
185
|
stdout.must =~ /random\s*amazing/
|
185
186
|
stdout.must =~ /amazing:describe NAME \[\-\-forcefully\]\s+# say that someone is amazing/m
|
186
|
-
stdout.must =~ /amazing:hello\s+# say hello/m
|
187
187
|
end
|
188
188
|
end
|
189
189
|
|
data/spec/shell/basic_spec.rb
CHANGED
@@ -57,6 +57,11 @@ describe Thor::Shell::Basic do
|
|
57
57
|
mock($stdout).print("Running... ")
|
58
58
|
shell.say("Running... ")
|
59
59
|
end
|
60
|
+
|
61
|
+
it "prints a message to the user without new line" do
|
62
|
+
mock($stdout).print("Running...")
|
63
|
+
shell.say("Running...", nil, false)
|
64
|
+
end
|
60
65
|
end
|
61
66
|
|
62
67
|
describe "#say_status" do
|
data/spec/task_spec.rb
CHANGED
@@ -41,10 +41,16 @@ describe Thor::Task do
|
|
41
41
|
|
42
42
|
describe "#dynamic" do
|
43
43
|
it "creates a dynamic task with the given name" do
|
44
|
-
Thor::Task.
|
45
|
-
Thor::Task.
|
46
|
-
Thor::Task.
|
47
|
-
Thor::Task.
|
44
|
+
Thor::Task::Dynamic.new('task').name.must == 'task'
|
45
|
+
Thor::Task::Dynamic.new('task').description.must == 'A dynamically-generated task'
|
46
|
+
Thor::Task::Dynamic.new('task').usage.must == 'task'
|
47
|
+
Thor::Task::Dynamic.new('task').options.must == {}
|
48
|
+
end
|
49
|
+
|
50
|
+
it "does not invoke an existing method" do
|
51
|
+
lambda {
|
52
|
+
Thor::Task::Dynamic.new('to_s').run([])
|
53
|
+
}.must raise_error(Thor::Error, "could not find Thor class or task 'to_s'")
|
48
54
|
end
|
49
55
|
end
|
50
56
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.
|
4
|
+
version: 0.11.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yehuda Katz
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2009-
|
13
|
+
date: 2009-09-09 00:00:00 +02:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|
@@ -84,7 +84,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
84
84
|
requirements: []
|
85
85
|
|
86
86
|
rubyforge_project: textmate
|
87
|
-
rubygems_version: 1.3.
|
87
|
+
rubygems_version: 1.3.5
|
88
88
|
signing_key:
|
89
89
|
specification_version: 3
|
90
90
|
summary: A scripting framework that replaces rake, sake and rubigen
|
@@ -105,6 +105,7 @@ test_files:
|
|
105
105
|
- spec/shell/color_spec.rb
|
106
106
|
- spec/group_spec.rb
|
107
107
|
- spec/thor_spec.rb
|
108
|
+
- spec/fixtures/application.rb
|
108
109
|
- spec/fixtures/doc/config.rb
|
109
110
|
- spec/fixtures/bundle/execute.rb
|
110
111
|
- spec/util_spec.rb
|