Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 306 lines (212 sloc) 9.68 kb
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
1 # Thor
a8de418 @wycats Initial checkin of Hermes
wycats authored
2
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
3 ## Description
606d108 @seeflanigan Add description & installation instructions
seeflanigan authored
4
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
5 Thor is a simple and efficient tool for building self-documenting command line utilities. It removes the pain of parsing command line options, writing "USAGE:" banners, and can also be used as an alternative to the [Rake](http://github.com/jimweirich/rake) build tool. The syntax is Rake-like, so it should be familiar to most Rake users.
606d108 @seeflanigan Add description & installation instructions
seeflanigan authored
6
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
7 ## Installation
606d108 @seeflanigan Add description & installation instructions
seeflanigan authored
8
9 $ gem install thor
10
11 or
12
13 $ gem install wycats-thor -s http://gems.github.com
14
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
15 ## Usage
16
17 Map options to a class. Simply create a class with the appropriate annotations
18 and have options automatically map to functions and parameters.
a8de418 @wycats Initial checkin of Hermes
wycats authored
19
c0cb7aa @mislav allow specifying optional args with default values: method_options(:u…
mislav authored
20 Example:
a8de418 @wycats Initial checkin of Hermes
wycats authored
21
3289ca8 @josevalim Updated README
josevalim authored
22 class App < Thor # [1]
23 map "-L" => :list # [2]
24
25 desc "install APP_NAME", "install one of the available apps" # [3]
26 method_options :force => :boolean, :alias => :string # [4]
a699ed7 @mislav update (incorrect) README and task.thor sample file
mislav authored
27 def install(name)
28 user_alias = options[:alias]
29 if options.force?
a8de418 @wycats Initial checkin of Hermes
wycats authored
30 # do something
31 end
3289ca8 @josevalim Updated README
josevalim authored
32 # other code
a8de418 @wycats Initial checkin of Hermes
wycats authored
33 end
34
35 desc "list [SEARCH]", "list all of the available apps, limited by SEARCH"
3289ca8 @josevalim Updated README
josevalim authored
36 def list(search="")
a8de418 @wycats Initial checkin of Hermes
wycats authored
37 # list everything
38 end
39 end
3289ca8 @josevalim Updated README
josevalim authored
40
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
41 Thor automatically maps commands as such:
a8de418 @wycats Initial checkin of Hermes
wycats authored
42
3289ca8 @josevalim Updated README
josevalim authored
43 thor app:install myname --force
44
a8de418 @wycats Initial checkin of Hermes
wycats authored
45 That gets converted to:
46
3289ca8 @josevalim Updated README
josevalim authored
47 App.new.install("myname")
a699ed7 @mislav update (incorrect) README and task.thor sample file
mislav authored
48 # with {'force' => true} as options hash
a8de418 @wycats Initial checkin of Hermes
wycats authored
49
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
50 1. Inherit from Thor to turn a class into an option mapper.
51 2. Map additional non-valid identifiers to specific methods. In this case, convert -L to :list
52 3. Describe the method immediately below. The first parameter is the usage information, and the second parameter is the description.
53 4. Provide any additional options that will be available the instance method options.
a659385 @josevalim Added rdoc task and checked if a good documentation will be generated.
josevalim authored
54
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
55 ## Types for <tt>method_options</tt>
a659385 @josevalim Added rdoc task and checked if a good documentation will be generated.
josevalim authored
56
57 * :boolean - is parsed as <tt>--option</tt> or <tt>--option=true</tt>
58 * :string - is parsed as <tt>--option=VALUE</tt>
59 * :numeric - is parsed as <tt>--option=N</tt>
60 * :array - is parsed as <tt>--option=one two three</tt>
61 * :hash - is parsed as <tt>--option=name:string age:integer</tt>
a699ed7 @mislav update (incorrect) README and task.thor sample file
mislav authored
62
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
63 Besides, method_option allows a default value to be given. Examples:
3289ca8 @josevalim Updated README
josevalim authored
64
fef8852 @josevalim Improve markdown.
josevalim authored
65 method_options :force => false
66 #=> Creates a boolean option with default value false
3289ca8 @josevalim Updated README
josevalim authored
67
fef8852 @josevalim Improve markdown.
josevalim authored
68 method_options :alias => "bar"
69 #=> Creates a string option with default value "bar"
3289ca8 @josevalim Updated README
josevalim authored
70
fef8852 @josevalim Improve markdown.
josevalim authored
71 method_options :threshold => 3.0
72 #=> Creates a numeric option with default value 3.0
3289ca8 @josevalim Updated README
josevalim authored
73
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
74 You can also supply <tt>:option => :required</tt> to mark an option as required. The
75 type is assumed to be string. If you want a required hash with default values
a659385 @josevalim Added rdoc task and checked if a good documentation will be generated.
josevalim authored
76 as option, you can use <tt>method_option</tt> which uses a more declarative style:
3289ca8 @josevalim Updated README
josevalim authored
77
fef8852 @josevalim Improve markdown.
josevalim authored
78 method_option :attributes, :type => :hash, :default => {}, :required => true
3289ca8 @josevalim Updated README
josevalim authored
79
80 All arguments can be set to nil (except required arguments), by suppling a no or
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
81 skip variant. For example:
3289ca8 @josevalim Updated README
josevalim authored
82
fef8852 @josevalim Improve markdown.
josevalim authored
83 thor app name --no-attributes
3289ca8 @josevalim Updated README
josevalim authored
84
85 In previous versions, aliases for options were created automatically, but now
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
86 they should be explicit. You can supply aliases in both short and declarative
3289ca8 @josevalim Updated README
josevalim authored
87 styles:
88
fef8852 @josevalim Improve markdown.
josevalim authored
89 method_options %w( force -f ) => :boolean
3289ca8 @josevalim Updated README
josevalim authored
90
91 Or:
92
fef8852 @josevalim Improve markdown.
josevalim authored
93 method_option :force, :type => :boolean, :aliases => "-f"
3289ca8 @josevalim Updated README
josevalim authored
94
95 You can supply as many aliases as you want.
96
97 NOTE: Type :optional available in Thor 0.9.0 was deprecated. Use :string or :boolean instead.
98
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
99 ## Namespaces
3289ca8 @josevalim Updated README
josevalim authored
100
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
101 By default, your Thor tasks are invoked using Ruby namespace. In the example
3289ca8 @josevalim Updated README
josevalim authored
102 above, tasks are invoked as:
103
fef8852 @josevalim Improve markdown.
josevalim authored
104 thor app:install name --force
3289ca8 @josevalim Updated README
josevalim authored
105
106 However, you could namespace your class as:
107
fef8852 @josevalim Improve markdown.
josevalim authored
108 module Sinatra
109 class App < Thor
110 # tasks
111 end
112 end
3289ca8 @josevalim Updated README
josevalim authored
113
114 And then you should invoke your tasks as:
115
fef8852 @josevalim Improve markdown.
josevalim authored
116 thor sinatra:app:install name --force
3289ca8 @josevalim Updated README
josevalim authored
117
118 If desired, you can change the namespace:
119
fef8852 @josevalim Improve markdown.
josevalim authored
120 module Sinatra
121 class App < Thor
122 namespace :myapp
123 # tasks
124 end
125 end
3289ca8 @josevalim Updated README
josevalim authored
126
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
127 And then your tasks should be invoked as:
3289ca8 @josevalim Updated README
josevalim authored
128
fef8852 @josevalim Improve markdown.
josevalim authored
129 thor myapp:install name --force
3289ca8 @josevalim Updated README
josevalim authored
130
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
131 ## Invocations
3289ca8 @josevalim Updated README
josevalim authored
132
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
133 Thor comes with a invocation-dependency system as well, which allows a task to be invoked only once. For example:
3289ca8 @josevalim Updated README
josevalim authored
134
fef8852 @josevalim Improve markdown.
josevalim authored
135 class Counter < Thor
136 desc "one", "Prints 1, 2, 3"
137 def one
138 puts 1
139 invoke :two
140 invoke :three
141 end
142
143 desc "two", "Prints 2, 3"
144 def two
145 puts 2
146 invoke :three
147 end
148
149 desc "three", "Prints 3"
150 def three
151 puts 3
152 end
153 end
3289ca8 @josevalim Updated README
josevalim authored
154
155 When invoking the task one:
156
fef8852 @josevalim Improve markdown.
josevalim authored
157 thor counter:one
3289ca8 @josevalim Updated README
josevalim authored
158
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
159 The output is "1 2 3", which means that the three task was invoked only once.
3289ca8 @josevalim Updated README
josevalim authored
160 You can even invoke tasks from another class, so be sure to check the
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
161 [documentation](http://rdoc.info/rdoc/wycats/thor/blob/f939a3e8a854616784cac1dcff04ef4f3ee5f7ff/Thor.html).
3289ca8 @josevalim Updated README
josevalim authored
162
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
163 ## Thor::Group
3289ca8 @josevalim Updated README
josevalim authored
164
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
165 Thor has a special class called Thor::Group. The main difference to Thor class
166 is that it invokes all tasks at once. The example above could be rewritten in
3289ca8 @josevalim Updated README
josevalim authored
167 Thor::Group as this:
168
fef8852 @josevalim Improve markdown.
josevalim authored
169 class Counter < Thor::Group
170 desc "Prints 1, 2, 3"
171
172 def one
173 puts 1
174 end
175
176 def two
177 puts 2
178 end
179
180 def three
181 puts 3
182 end
183 end
3289ca8 @josevalim Updated README
josevalim authored
184
185 When invoked:
186
fef8852 @josevalim Improve markdown.
josevalim authored
187 thor counter
3289ca8 @josevalim Updated README
josevalim authored
188
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
189 It prints "1 2 3" as well. Notice you should describe (using the method <tt>desc</tt>)
190 only the class and not each task anymore. Thor::Group is a great tool to create
a659385 @josevalim Added rdoc task and checked if a good documentation will be generated.
josevalim authored
191 generators, since you can define several steps which are invoked in the order they
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
192 are defined (Thor::Group is the tool use in generators in Rails 3.0).
3289ca8 @josevalim Updated README
josevalim authored
193
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
194 Besides, Thor::Group can parse arguments and options as Thor tasks:
3289ca8 @josevalim Updated README
josevalim authored
195
fef8852 @josevalim Improve markdown.
josevalim authored
196 class Counter < Thor::Group
197 # number will be available as attr_accessor
198 argument :number, :type => :numeric, :desc => "The number to start counting"
199 desc "Prints the 'number' given upto 'number+2'"
200
201 def one
202 puts number + 0
203 end
204
205 def two
206 puts number + 1
207 end
208
209 def three
210 puts number + 2
211 end
212 end
3289ca8 @josevalim Updated README
josevalim authored
213
214 The counter above expects one parameter and has the folling outputs:
215
fef8852 @josevalim Improve markdown.
josevalim authored
216 thor counter 5
217 # Prints "5 6 7"
3289ca8 @josevalim Updated README
josevalim authored
218
fef8852 @josevalim Improve markdown.
josevalim authored
219 thor counter 11
220 # Prints "11 12 13"
3289ca8 @josevalim Updated README
josevalim authored
221
a659385 @josevalim Added rdoc task and checked if a good documentation will be generated.
josevalim authored
222 You can also give options to Thor::Group, but instead of using <tt>method_option</tt>
223 and <tt>method_options</tt>, you should use <tt>class_option</tt> and <tt>class_options</tt>.
224 Both argument and class_options methods are available to Thor class as well.
3289ca8 @josevalim Updated README
josevalim authored
225
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
226 ## Actions
3289ca8 @josevalim Updated README
josevalim authored
227
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
228 Thor comes with several actions which helps with script and generator tasks. You
229 might be familiar with them since some came from Rails Templates. They are:
a659385 @josevalim Added rdoc task and checked if a good documentation will be generated.
josevalim authored
230 <tt>say</tt>, <tt>ask</tt>, <tt>yes?</tt>, <tt>no?</tt>, <tt>add_file</tt>,
231 <tt>remove_file</tt>, <tt>copy_file</tt>, <tt>template</tt>, <tt>directory</tt>,
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
232 <tt>inside</tt>, <tt>run</tt>, <tt>inject_into_file</tt> and a couple more.
3289ca8 @josevalim Updated README
josevalim authored
233
234 To use them, you just need to include Thor::Actions in your Thor classes:
235
fef8852 @josevalim Improve markdown.
josevalim authored
236 class App < Thor
237 include Thor::Actions
238 # tasks
239 end
3289ca8 @josevalim Updated README
josevalim authored
240
241 Some actions like copy file requires that a class method called source_root is
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
242 defined in your class. This is the directory where your templates should be
243 placed. Be sure to check the documentation on [actions](http://rdoc.info/rdoc/wycats/thor/blob/f939a3e8a854616784cac1dcff04ef4f3ee5f7ff/Thor/Actions.html).
f91c69b Adding an example generator, a section on further reading about
Jonathan Hicks authored
244
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
245 ## Generators
f91c69b Adding an example generator, a section on further reading about
Jonathan Hicks authored
246
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
247 A great use for Thor is creating custom generators. Combining Thor::Group,
248 Thor::Actions and ERB templates makes this very easy. Here is an example:
f91c69b Adding an example generator, a section on further reading about
Jonathan Hicks authored
249
649a50e @josevalim Wrap up README changes.
josevalim authored
250 class Newgem < Thor::Group
8287cf6 Spacing
Jonathan Hicks authored
251 include Thor::Actions
252
253 # Define arguments and options
254 argument :name
255 class_option :test_framework, :default => :test_unit
256
257 def self.source_root
258 File.dirname(__FILE__)
259 end
260
261 def create_lib_file
262 template('templates/newgem.tt', "#{name}/lib/#{name}.rb")
263 end
264
265 def create_test_file
266 test = options[:test_framework] == "rspec" ? :spec : :test
267 create_file "#{name}/#{test}/#{name}_#{test}.rb"
268 end
269
270 def copy_licence
649a50e @josevalim Wrap up README changes.
josevalim authored
271 if yes?("Use MIT license?")
8287cf6 Spacing
Jonathan Hicks authored
272 # Make a copy of the MITLICENSE file at the source root
273 copy_file "MITLICENSE", "#{name}/MITLICENSE"
274 else
275 say "Shame on you…", :red
276 end
277 end
278 end
f91c69b Adding an example generator, a section on further reading about
Jonathan Hicks authored
279
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
280 Doing a <tt>thor -T</tt> will show how to run our generator. It should read:
281 <tt>thor newgem NAME</tt>. This shows that we have to supply a NAME
f91c69b Adding an example generator, a section on further reading about
Jonathan Hicks authored
282 argument for our generator to run.
283
284 The <tt>create_lib_file</tt> uses an ERB template. This is what it looks like:
285
ee5d9b5 @josevalim camelize is added by ActiveSupport, so don't use it.
josevalim authored
286 class <%= name.capitalize %>
8287cf6 Spacing
Jonathan Hicks authored
287 end
f91c69b Adding an example generator, a section on further reading about
Jonathan Hicks authored
288
289 The arguments that you set in your generator will automatically be passed in
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
290 when <tt>template</tt> gets called. Be sure to read the [documentation](http://rdoc.info/rdoc/wycats/thor/blob/f939a3e8a854616784cac1dcff04ef4f3ee5f7ff/Thor/Actions.html) for
f91c69b Adding an example generator, a section on further reading about
Jonathan Hicks authored
291 more options.
292
649a50e @josevalim Wrap up README changes.
josevalim authored
293 Running the generator with <tt>thor newgem devise</tt> will
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
294 create two files: "devise/lib/devise.rb", and "devise/test/devise_test.rb". The user will then be asked (via a prompt by the <tt>yes?</tt> method) whether or not they would like to copy the MIT License. If you want to change the test framework, you can add the option: <tt>thor newgem devise --test-framework=rspec</tt>
295
296 This will generate two files - "devise/lib/devise.rb" and "devise/spec/devise_spec.rb".
f91c69b Adding an example generator, a section on further reading about
Jonathan Hicks authored
297
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
298 ## Further Reading
f91c69b Adding an example generator, a section on further reading about
Jonathan Hicks authored
299
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
300 Thor offers many scripting possibilities beyond these examples. Be sure to read
301 through the [documentation](http://rdoc.info/rdoc/wycats/thor/blob/f939a3e8a854616784cac1dcff04ef4f3ee5f7ff/Thor.html) and [specs](http://github.com/wycats/thor/tree/master/spec/) to get a better understanding of the options available.
f91c69b Adding an example generator, a section on further reading about
Jonathan Hicks authored
302
3cf7db3 @seeflanigan Minor documentation tweaks
seeflanigan authored
303 ## License
a699ed7 @mislav update (incorrect) README and task.thor sample file
mislav authored
304
606d108 @seeflanigan Add description & installation instructions
seeflanigan authored
305 Released under the MIT License. See the LICENSE file for further details.
Something went wrong with that request. Please try again.