Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 230 lines (199 sloc) 6.783 kB
1b58d9d @josevalim Start to deal with generators on Runner.
josevalim authored
1 $:.unshift File.expand_path(File.dirname(__FILE__))
2 require 'thor/base'
006324b @josevalim Simplifying how files are required.
josevalim authored
3 require 'thor/group'
38e4e2f @josevalim Added common Action options as configuration.
josevalim authored
4 require 'thor/actions'
82ff27a @wycats Change name to thor. Last commit to hermes repo.
wycats authored
5
6 class Thor
0e8485c @josevalim Remove most of invokation logic from tasks and bumped up tasks tests.
josevalim authored
7
bdb1eef @josevalim Add argument and option as methods to setup options.
josevalim authored
8 class << self
6d8c59d @josevalim Started to move specific Script implementations to Thor and specific …
josevalim authored
9
10 # Sets the default task when thor is executed without an explicit task to be called.
11 #
12 # ==== Parameters
13 # meth<Symbol>:: name of the defaut task
14 #
15 def default_task(meth=nil)
16 case meth
17 when :none
18 @default_task = 'help'
19 when nil
20 @default_task ||= from_superclass(:default_task, 'help')
21 else
22 @default_task = meth.to_s
23 end
24 end
25
26 # Defines the usage and the description of the next task.
27 #
28 # ==== Parameters
29 # usage<String>
30 # description<String>
31 #
5ebe094 @josevalim Added :for support to desc as well.
josevalim authored
32 def desc(usage, description, options={})
33 if options[:for]
34 task = find_and_refresh_task(options[:for])
35 task.usage = usage if usage
36 task.description = description if description
37 else
38 @usage, @desc = usage, description
39 end
6d8c59d @josevalim Started to move specific Script implementations to Thor and specific …
josevalim authored
40 end
41
42 # Maps an input to a task. If you define:
43 #
44 # map "-T" => "list"
bdb1eef @josevalim Add argument and option as methods to setup options.
josevalim authored
45 #
6d8c59d @josevalim Started to move specific Script implementations to Thor and specific …
josevalim authored
46 # Running:
47 #
48 # thor -T
49 #
50 # Will invoke the list task.
51 #
52 # ==== Parameters
2212ae3 @josevalim Add description to Thor::Group.
josevalim authored
53 # Hash[String|Array => Symbol]:: Maps the string or the strings in the array to the given task.
6d8c59d @josevalim Started to move specific Script implementations to Thor and specific …
josevalim authored
54 #
55 def map(mappings=nil)
56 @map ||= from_superclass(:map, {})
57
58 if mappings
59 mappings.each do |key, value|
60 if key.respond_to?(:each)
61 key.each {|subkey| @map[subkey] = value}
62 else
63 @map[key] = value
64 end
65 end
66 end
67
68 @map
bdb1eef @josevalim Add argument and option as methods to setup options.
josevalim authored
69 end
6d8c59d @josevalim Started to move specific Script implementations to Thor and specific …
josevalim authored
70
206b464 @josevalim Renaming methods as discussed with Yehuda.
josevalim authored
71 # Declares the options for the next task to be declared.
6d8c59d @josevalim Started to move specific Script implementations to Thor and specific …
josevalim authored
72 #
73 # ==== Parameters
206b464 @josevalim Renaming methods as discussed with Yehuda.
josevalim authored
74 # Hash[Symbol => Object]:: The hash key is the name of the option and the value
6d8c59d @josevalim Started to move specific Script implementations to Thor and specific …
josevalim authored
75 # is the type of the option. Can be :optional, :required, :boolean or :numeric.
76 #
77 def method_options(options=nil)
78 @method_options ||= Thor::CoreExt::OrderedHash.new
206b464 @josevalim Renaming methods as discussed with Yehuda.
josevalim authored
79 build_options(options, @method_options) if options
80 @method_options
81 end
6d8c59d @josevalim Started to move specific Script implementations to Thor and specific …
josevalim authored
82
206b464 @josevalim Renaming methods as discussed with Yehuda.
josevalim authored
83 # Adds an option to the set of class options. If :for is given as option,
84 # it allows you to change the options from a previous defined task.
85 #
86 # def previous_task
87 # # magic
88 # end
89 #
01e2ef9 @josevalim Added #help as a class method to be used by both self#help and runner…
josevalim authored
90 # method_options :foo => :bar, :for => :previous_task
206b464 @josevalim Renaming methods as discussed with Yehuda.
josevalim authored
91 #
92 # def next_task
a52d778 @josevalim Put the initialization process that is common to scripts and generato…
josevalim authored
93 # # magic
206b464 @josevalim Renaming methods as discussed with Yehuda.
josevalim authored
94 # end
95 #
96 # ==== Parameters
97 # name<Symbol>:: The name of the argument.
f3cc428 @josevalim Options can be grouped. This allows a better output when several opti…
josevalim authored
98 # options<Hash>:: Described below.
99 #
100 # ==== Options
101 # :desc - Description for the argument.
102 # :required - If the argument is required or not.
103 # :default - Default value for this argument. It cannot be required and have default values.
104 # :aliases - Aliases for this option.
105 # :type - The type of the argument, can be :string, :hash, :array, :numeric, :boolean or :default.
106 # Default accepts arguments as booleans (--switch) or as strings (--switch=VALUE).
206b464 @josevalim Renaming methods as discussed with Yehuda.
josevalim authored
107 #
108 def method_option(name, options)
109 scope = if options[:for]
110 find_and_refresh_task(options[:for]).options
111 else
112 method_options
6d8c59d @josevalim Started to move specific Script implementations to Thor and specific …
josevalim authored
113 end
114
206b464 @josevalim Renaming methods as discussed with Yehuda.
josevalim authored
115 build_option(name, options, scope)
6d8c59d @josevalim Started to move specific Script implementations to Thor and specific …
josevalim authored
116 end
117
67d98ca @josevalim More documentation.
josevalim authored
118 # Parses the task and options from the given args, instantiate the class
119 # and invoke the task. This method is used when the arguments must be parsed
120 # from an array. If you are inside Ruby and want to use a Thor class, you
121 # can simply initialize it:
7c90470 @josevalim Make difference between arguments and options obvious.
josevalim authored
122 #
123 # script = MyScript.new(args, options, config)
ca57d97 @josevalim Created methods to invoke tasks. You can still run a task directly, b…
josevalim authored
124 # script.invoke(:task, first_arg, second_arg, third_arg)
76383c7 @josevalim More specs, more documentation.
josevalim authored
125 #
68f8ed5 @josevalim Shells should be instantiated and can be given as arguments to start.
josevalim authored
126 def start(args=ARGV, config={})
6bacd1b @josevalim Errors are sent to the shell.
josevalim authored
127 config[:shell] ||= Thor::Base.shell.new
128
76383c7 @josevalim More specs, more documentation.
josevalim authored
129 meth = normalize_task_name(args.shift)
130 task = self[meth]
f7d9cc6 @josevalim Adding more logic to initializer, so we ensure that instantiated Thor…
josevalim authored
131
132 options = class_options.merge(task.options)
133 opts = Thor::Options.new(options)
134 opts.parse(args)
135
136 instance = new(opts.arguments, opts.options, config)
ca57d97 @josevalim Created methods to invoke tasks. You can still run a task directly, b…
josevalim authored
137 instance.invoke(task.name, *opts.trailing)
08eb0c1 @josevalim Improving error handling.
josevalim authored
138 rescue Thor::Error => e
6bacd1b @josevalim Errors are sent to the shell.
josevalim authored
139 config[:shell].error e.message
76383c7 @josevalim More specs, more documentation.
josevalim authored
140 end
141
50a6f71 @josevalim Thor::Generator is now Thor::Group.
josevalim authored
142 # Prints help information. If a task name is given, it shows information
143 # only about the specific task.
1754f44 @josevalim Improving #help coverage.
josevalim authored
144 #
145 # ==== Parameters
146 # meth<String>:: An optional task name to print usage information about.
147 #
148 # ==== Options
149 # namespace:: When true, shows the namespace in the output before the usage.
150 # skip_inherited:: When true, does not show tasks from superclass.
01e2ef9 @josevalim Added #help as a class method to be used by both self#help and runner…
josevalim authored
151 #
14ee577 @josevalim Added table to Thor::Shells::Basic.
josevalim authored
152 def help(shell, meth=nil, options={})
9434c8f @josevalim Runner uses #help methods from classes.
josevalim authored
153 meth, options = nil, meth if meth.is_a?(Hash)
01e2ef9 @josevalim Added #help as a class method to be used by both self#help and runner…
josevalim authored
154
3acd153 @josevalim Moving task list responsabilities to one place.
josevalim authored
155 if meth
01e2ef9 @josevalim Added #help as a class method to be used by both self#help and runner…
josevalim authored
156 task = self.all_tasks[meth]
08eb0c1 @josevalim Improving error handling.
josevalim authored
157 raise UndefinedTaskError, "task '#{meth}' could not be found in namespace '#{self.namespace}'" unless task
3acd153 @josevalim Moving task list responsabilities to one place.
josevalim authored
158
14ee577 @josevalim Added table to Thor::Shells::Basic.
josevalim authored
159 shell.say "Usage:"
38e8f36 @josevalim Created a hook called banner to allow description customization for t…
josevalim authored
160 shell.say " #{banner(task, options[:namespace])}"
14ee577 @josevalim Added table to Thor::Shells::Basic.
josevalim authored
161 shell.say
b57b497 @josevalim Arguments are injected into usage for better usage information.
josevalim authored
162 class_options_help(shell, "Class")
14ee577 @josevalim Added table to Thor::Shells::Basic.
josevalim authored
163 shell.say task.description
3acd153 @josevalim Moving task list responsabilities to one place.
josevalim authored
164 else
f3cc428 @josevalim Options can be grouped. This allows a better output when several opti…
josevalim authored
165 list = (options[:short] ? tasks : all_tasks).map do |_, task|
38e8f36 @josevalim Created a hook called banner to allow description customization for t…
josevalim authored
166 [ banner(task, options[:namespace]), task.short_description || '' ]
f3cc428 @josevalim Options can be grouped. This allows a better output when several opti…
josevalim authored
167 end
9434c8f @josevalim Runner uses #help methods from classes.
josevalim authored
168
f3cc428 @josevalim Options can be grouped. This allows a better output when several opti…
josevalim authored
169 if options[:short]
5ba80df @josevalim More print actions.
josevalim authored
170 shell.print_table(list, :emphasize_last => true)
ad71b5b @josevalim More formatting on thor list.
josevalim authored
171 else
14ee577 @josevalim Added table to Thor::Shells::Basic.
josevalim authored
172 shell.say "Tasks:"
5ba80df @josevalim More print actions.
josevalim authored
173 shell.print_table(list, :ident => 2, :emphasize_last => true)
f3cc428 @josevalim Options can be grouped. This allows a better output when several opti…
josevalim authored
174 shell.say
175
b57b497 @josevalim Arguments are injected into usage for better usage information.
josevalim authored
176 class_options_help(shell, "Class")
ad71b5b @josevalim More formatting on thor list.
josevalim authored
177 end
3acd153 @josevalim Moving task list responsabilities to one place.
josevalim authored
178 end
179 end
180
6d8c59d @josevalim Started to move specific Script implementations to Thor and specific …
josevalim authored
181 protected
182
38e8f36 @josevalim Created a hook called banner to allow description customization for t…
josevalim authored
183 # The banner for this class. You can customize it if you are invoking the
184 # thor class by another means which is not the Thor::Runner. It receives
185 # the task that is going to be invoked and if the namespace should be
186 # displayed.
187 #
188 def banner(task, namespace=true) #:nodoc:
189 task.formatted_usage(self, namespace)
190 end
191
46fb577 @josevalim Tidying up Thor and Thor::Generator classes.
josevalim authored
192 def baseclass #:nodoc:
193 Thor
194 end
195
196 def valid_task?(meth) #:nodoc:
197 public_instance_methods.include?(meth) && @usage && @desc
198 end
199
200 def create_task(meth) #:nodoc:
201 tasks[meth.to_s] = Thor::Task.new(meth, @desc, @usage, method_options)
202 @usage, @desc, @method_options = nil
203 end
204
205 def initialize_added #:nodoc:
206 class_options.merge!(method_options)
207 @method_options = nil
208 end
209
6d8c59d @josevalim Started to move specific Script implementations to Thor and specific …
josevalim authored
210 # Receives a task name (can be nil), and try to get a map from it.
211 # If a map can't be found use the sent name or the default task.
212 #
46fb577 @josevalim Tidying up Thor and Thor::Generator classes.
josevalim authored
213 def normalize_task_name(meth) #:nodoc:
6d8c59d @josevalim Started to move specific Script implementations to Thor and specific …
josevalim authored
214 mapping = map[meth.to_s]
215 meth = mapping || meth || default_task
216 meth.to_s.gsub('-','_') # treat foo-bar > foo_bar
217 end
218
46fb577 @josevalim Tidying up Thor and Thor::Generator classes.
josevalim authored
219 end
ad71b5b @josevalim More formatting on thor list.
josevalim authored
220
46fb577 @josevalim Tidying up Thor and Thor::Generator classes.
josevalim authored
221 include Thor::Base
222
bb35d61 @josevalim Arguments can be optional too (the main difference from options then …
josevalim authored
223 map HELP_MAPPINGS => :help
614326a @josevalim Moved Thor DSL to lib/thor/dsl
josevalim authored
224
3acd153 @josevalim Moving task list responsabilities to one place.
josevalim authored
225 desc "help [TASK]", "Describe available tasks or one specific task"
226 def help(task=nil)
14ee577 @josevalim Added table to Thor::Shells::Basic.
josevalim authored
227 self.class.help(shell, task, :namespace => task && task.include?(?:))
b522f05 @wycats First pass of Thor::Runner
wycats authored
228 end
5dbab4e @nex3 Preserve metadata for tasks defined in superclasses.
nex3 authored
229 end
Something went wrong with that request. Please try again.