thor 0.11.5 → 0.11.8

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 CHANGED
@@ -1,4 +1,6 @@
1
- require 'rubygems'
1
+ # enconding: utf-8
2
+
3
+ require File.join(File.dirname(__FILE__), "lib", "thor", "version")
2
4
  require 'thor/rake_compat'
3
5
  require 'spec/rake/spectask'
4
6
  require 'rdoc/task'
@@ -10,11 +12,13 @@ class Default < Thor
10
12
  include Thor::RakeCompat
11
13
 
12
14
  Spec::Rake::SpecTask.new(:spec) do |t|
15
+ t.libs << 'lib'
13
16
  t.spec_opts = ['--options', "spec/spec.opts"]
14
17
  t.spec_files = FileList['spec/**/*_spec.rb']
15
18
  end
16
19
 
17
20
  Spec::Rake::SpecTask.new(:rcov) do |t|
21
+ t.libs << 'lib'
18
22
  t.spec_opts = ['--options', "spec/spec.opts"]
19
23
  t.spec_files = FileList['spec/**/*_spec.rb']
20
24
  t.rcov = true
@@ -34,7 +38,7 @@ class Default < Thor
34
38
  require 'jeweler'
35
39
  Jeweler::Tasks.new do |s|
36
40
  s.name = GEM_NAME
37
- s.version = "0.11.4"
41
+ s.version = Thor::VERSION
38
42
  s.rubyforge_project = "textmate"
39
43
  s.platform = Gem::Platform::RUBY
40
44
  s.summary = "A scripting framework that replaces rake, sake and rubigen"
@@ -51,6 +55,8 @@ class Default < Thor
51
55
  s.files.exclude 'spec/sandbox/**/*'
52
56
  s.test_files.exclude 'spec/sandbox/**/*'
53
57
  end
58
+
59
+ Jeweler::RubyforgeTasks.new
54
60
  rescue LoadError
55
61
  puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
56
62
  end
data/bin/rake2thor CHANGED
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'rubygems'
4
3
  require 'ruby2ruby'
5
4
  require 'parse_tree'
6
5
  if Ruby2Ruby::VERSION >= "1.2.0"
data/bin/thor CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # -*- mode: ruby -*-
3
3
 
4
- require File.join(File.dirname(__FILE__), '..', 'lib', 'thor')
4
+ require 'thor'
5
5
  require 'thor/runner'
6
6
 
7
7
  Thor::Runner.start
@@ -73,7 +73,9 @@ class Thor
73
73
 
74
74
  case file_source
75
75
  when /\.empty_directory$/
76
- base.empty_directory(File.dirname(file_destination), config)
76
+ dirname = File.dirname(file_destination).gsub(/\/\.$/, '')
77
+ next if dirname == given_destination
78
+ base.empty_directory(dirname, config)
77
79
  when /\.tt$/
78
80
  base.template(file_source, file_destination[0..-4], config)
79
81
  else
@@ -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
- def prepend_file(path, data=nil, config={}, &block)
115
- return unless behavior == :invoke
116
- path = File.expand_path(path, destination_root)
117
- say_status :prepend, relative_to_original_destination_root(path), config.fetch(:verbose, true)
118
-
119
- unless options[:pretend]
120
- content = data || block.call
121
- content << File.read(path)
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
- def append_file(path, data=nil, config={}, &block)
138
- return unless behavior == :invoke
139
- path = File.expand_path(path, destination_root)
140
- say_status :append, relative_to_original_destination_root(path), config.fetch(:verbose, true)
141
- File.open(path, 'ab') { |file| file.write(data || block.call) } unless options[:pretend]
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 append_file,
7
- # prepend_file and gsub_file, this method is reversible. By this reason,
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 #{gem}" }.join("\n")
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, :replacement
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
- data = data.call if data.is_a?(Proc)
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
- @flag = @config.delete(:before)
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 :inject, config[:verbose]
56
- replace!(flag, replacement)
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 :deinject, config[:verbose]
61
- replace!(replacement, flag)
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/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.
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:
@@ -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.dynamic(task) if task && !task.is_a?(Thor::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
 
@@ -22,7 +22,8 @@ class Thor
22
22
 
23
23
  def self.included(base)
24
24
  # Hack. Make rakefile point to invoker, so rdoc task is generated properly.
25
- Rake.application.instance_variable_set(:@rakefile, caller[0].match(/(.*):\d+/)[1])
25
+ rakefile = File.basename(caller[0].match(/(.*):\d+/)[1])
26
+ Rake.application.instance_variable_set(:@rakefile, rakefile)
26
27
  self.rake_classes << base
27
28
  end
28
29
  end
@@ -43,11 +44,9 @@ class Object #:nodoc:
43
44
  description.strip!
44
45
 
45
46
  klass.desc description, task.comment || non_namespaced_name
46
- klass.class_eval <<-METHOD
47
- def #{non_namespaced_name}(#{task.arg_names.join(', ')})
48
- Rake::Task[#{task.name.to_sym.inspect}].invoke(#{task.arg_names.join(', ')})
49
- end
50
- METHOD
47
+ klass.send :define_method, non_namespaced_name do |*args|
48
+ Rake::Task[task.name.to_sym].invoke(*args)
49
+ end
51
50
  end
52
51
 
53
52
  task
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
  #
@@ -211,7 +215,7 @@ class Thor::Runner < Thor #:nodoc:
211
215
  # 5. c:\ <-- no Thorfiles found!
212
216
  #
213
217
  def thorfiles(relevant_to=nil, skip_lookup=false)
214
- # Deal with deprecated thor when :namespaces: is available as constants
218
+ # TODO Remove this dealing with deprecated thor when :namespaces: is available as constants
215
219
  save_yaml(thor_yaml) if Thor::Util.convert_constants_to_namespaces(thor_yaml)
216
220
 
217
221
  thorfiles = []
@@ -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=false)
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 new_line
41
+ if force_new_line
43
42
  $stdout.puts(message)
44
43
  else
45
44
  $stdout.print(message)
data/lib/thor/shell.rb CHANGED
@@ -1,11 +1,17 @@
1
+ require 'rbconfig'
1
2
  require 'thor/shell/color'
2
3
 
3
4
  class Thor
4
5
  module Base
5
- # Returns the shell used in all Thor classes. Default to color one.
6
+ # Returns the shell used in all Thor classes. If you are in a Unix platform
7
+ # it will use a colored log, otherwise it will use a basic one without color.
6
8
  #
7
9
  def self.shell
8
- @shell ||= Thor::Shell::Color
10
+ @shell ||= if Config::CONFIG['host_os'] =~ /mswin|mingw/
11
+ Thor::Shell::Basic
12
+ else
13
+ Thor::Shell::Color
14
+ end
9
15
  end
10
16
 
11
17
  # Sets the shell used in all Thor classes.
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
- # Creates a dynamic task. Dynamic tasks are created on demand to allow method
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
- def self.dynamic(name)
8
- new(name, "A dynamically-generated task", name.to_s)
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
- !(collection).include?(name.to_s) && !(collection).include?(name.to_sym) # For Ruby 1.9
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
- klass, task_name = Thor::Util.find_by_namespace(namespace), nil
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
- if klass.nil? && namespace.include?(?:)
143
- namespace = namespace.split(":")
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
@@ -208,7 +209,7 @@ class Thor
208
209
  # Returns the root where thor files are located, dependending on the OS.
209
210
  #
210
211
  def self.thor_root
211
- File.join(user_home, ".thor")
212
+ File.join(user_home, ".thor").gsub(/\\/, '/')
212
213
  end
213
214
 
214
215
  # Returns the files in the thor root. On Windows thor_root will be something
@@ -219,7 +220,7 @@ class Thor
219
220
  # If we don't #gsub the \ character, Dir.glob will fail.
220
221
  #
221
222
  def self.thor_root_glob
222
- files = Dir["#{thor_root.gsub(/\\/, '/')}/*"]
223
+ files = Dir["#{thor_root}/*"]
223
224
 
224
225
  files.map! do |file|
225
226
  File.directory?(file) ? File.join(file, "main.thor") : file
@@ -0,0 +1,3 @@
1
+ class Thor
2
+ VERSION = "0.11.8".freeze
3
+ end
data/lib/thor.rb CHANGED
@@ -1,4 +1,3 @@
1
- $:.unshift File.expand_path(File.dirname(__FILE__))
2
1
  require 'thor/base'
3
2
  require 'thor/group'
4
3
  require 'thor/actions'
@@ -135,7 +134,7 @@ class Thor
135
134
  args, opts = given_args, {}
136
135
  end
137
136
 
138
- task ||= Task.dynamic(meth)
137
+ task ||= Thor::Task::Dynamic.new(meth)
139
138
  trailing = args[Range.new(arguments.size, -1)]
140
139
  new(args, opts, config).invoke(task, trailing || [])
141
140
  end
@@ -96,6 +96,11 @@ describe Thor::Actions::Directory do
96
96
  File.exists?(file).must be_true
97
97
  end
98
98
 
99
+ it "does not copy empty directories twice" do
100
+ content = invoke!("doc/components", "docs/components")
101
+ content.must_not =~ /exist/
102
+ end
103
+
99
104
  it "logs status" do
100
105
  content = invoke!("doc")
101
106
  content.must =~ /create doc\/README/
@@ -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
- it "does not log status if required" do
238
- action(:prepend_file, "doc/README", "START", :verbose => false).must be_empty
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", "\nmore content", :before => "__start__"
70
- revoke! "doc/README", "\nmore content", :before => "__start__"
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"
@@ -0,0 +1,2 @@
1
+ class Application < Base
2
+ end
@@ -27,6 +27,10 @@ class ThorTask < Thor
27
27
  end
28
28
 
29
29
  describe Thor::RakeCompat do
30
+ it "sets the rakefile application" do
31
+ ["rake_compat_spec.rb", "Thorfile"].must include(Rake.application.rakefile)
32
+ end
33
+
30
34
  it "adds rake tasks to thor classes too" do
31
35
  task = ThorTask.tasks["cool"]
32
36
  task.must be
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
 
@@ -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/spec_helper.rb CHANGED
@@ -1,9 +1,9 @@
1
1
  $TESTING=true
2
2
 
3
- $:.unshift File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
4
-
3
+ $:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
5
4
  require 'thor'
6
5
  require 'stringio'
6
+
7
7
  require 'rubygems'
8
8
  require 'rr'
9
9
  require 'diff/lcs' # You need diff/lcs installed to run specs (but not to run Thor).
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.dynamic('task').name.must == 'task'
45
- Thor::Task.dynamic('task').description.must == 'A dynamically-generated task'
46
- Thor::Task.dynamic('task').usage.must == 'task'
47
- Thor::Task.dynamic('task').options.must == {}
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.5
4
+ version: 0.11.8
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-08-05 00:00:00 +02:00
13
+ date: 2009-10-21 00:00:00 -02:00
14
14
  default_executable:
15
15
  dependencies: []
16
16
 
@@ -26,13 +26,11 @@ extra_rdoc_files:
26
26
  - LICENSE
27
27
  - README.rdoc
28
28
  - Thorfile
29
- - VERSION
30
29
  files:
31
30
  - CHANGELOG.rdoc
32
31
  - LICENSE
33
32
  - README.rdoc
34
33
  - Thorfile
35
- - VERSION
36
34
  - bin/rake2thor
37
35
  - bin/thor
38
36
  - lib/thor.rb
@@ -60,6 +58,7 @@ files:
60
58
  - lib/thor/shell/color.rb
61
59
  - lib/thor/task.rb
62
60
  - lib/thor/util.rb
61
+ - lib/thor/version.rb
63
62
  has_rdoc: true
64
63
  homepage: http://yehudakatz.com
65
64
  licenses: []
@@ -84,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
84
83
  requirements: []
85
84
 
86
85
  rubyforge_project: textmate
87
- rubygems_version: 1.3.2
86
+ rubygems_version: 1.3.5
88
87
  signing_key:
89
88
  specification_version: 3
90
89
  summary: A scripting framework that replaces rake, sake and rubigen
@@ -105,6 +104,7 @@ test_files:
105
104
  - spec/shell/color_spec.rb
106
105
  - spec/group_spec.rb
107
106
  - spec/thor_spec.rb
107
+ - spec/fixtures/application.rb
108
108
  - spec/fixtures/doc/config.rb
109
109
  - spec/fixtures/bundle/execute.rb
110
110
  - spec/util_spec.rb
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.11.5