thor 0.11.5 → 0.11.6
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.
- 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
|