Skip to content

Commit

Permalink
Added rdoc task and checked if a good documentation will be generated.
Browse files Browse the repository at this point in the history
  • Loading branch information
josevalim committed Aug 1, 2009
1 parent c0bc615 commit a659385
Show file tree
Hide file tree
Showing 26 changed files with 162 additions and 150 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,3 +1,4 @@
/pkg
/coverage
/spec/sandbox
/rdoc
75 changes: 31 additions & 44 deletions README.markdown → README.rdoc
@@ -1,5 +1,4 @@
thor
====
= thor

Map options to a class. Simply create a class with the appropriate annotations
and have options automatically map to functions and parameters.
Expand Down Expand Up @@ -34,26 +33,18 @@ That gets converted to:
App.new.install("myname")
# with {'force' => true} as options hash

1. Inherit from Thor to turn a class into an option mapper
2. Map additional non-valid identifiers to specific methods. In this case, convert -L to :list
3. Describe the method immediately below. The first parameter is the usage information, and the second parameter is the description
4. Provide any additional options that will be available the instance method options.

Types for `method_options`
--------------------------

<dl>
<dt><code>:boolean</code></dt>
<dd>is parsed as --option or --option=true</dd>
<dt><code>:string</code></dt>
<dd>is parsed as --option=VALUE</dd>
<dt><code>:numeric</code></dt>
<dd>is parsed as --option=N</dd>
<dt><code>:array</code></dt>
<dd>is parsed as --option=one two three</dd>
<dt><code>:hash</code></dt>
<dd>is parsed as --option=key:value key:value key:value</dd>
</dl>
1. Inherit from Thor to turn a class into an option mapper
2. Map additional non-valid identifiers to specific methods. In this case, convert -L to :list
3. Describe the method immediately below. The first parameter is the usage information, and the second parameter is the description
4. Provide any additional options that will be available the instance method options.

== Types for <tt>method_options</tt>

* :boolean - is parsed as <tt>--option</tt> or <tt>--option=true</tt>
* :string - is parsed as <tt>--option=VALUE</tt>
* :numeric - is parsed as <tt>--option=N</tt>
* :array - is parsed as <tt>--option=one two three</tt>
* :hash - is parsed as <tt>--option=name:string age:integer</tt>

Besides, method_option allows a default value to be given, examples:

Expand All @@ -66,9 +57,9 @@ Besides, method_option allows a default value to be given, examples:
method_options :threshold => 3.0
#=> Creates a numeric option with default value 3.0

You can also supply :option => :required to mark an option as required. The
You can also supply <tt>:option => :required</tt> to mark an option as required. The
type is assumed to be string. If you want a required hash with default values
as option, you can use `method_option` which uses a more declarative style:
as option, you can use <tt>method_option</tt> which uses a more declarative style:

method_option :attributes, :type => :hash, :default => {}, :required => true

Expand All @@ -91,8 +82,7 @@ You can supply as many aliases as you want.

NOTE: Type :optional available in Thor 0.9.0 was deprecated. Use :string or :boolean instead.

Namespaces
----------
== Namespaces

By default, your Thor tasks are invoked using Ruby namespace. In the example
above, tasks are invoked as:
Expand Down Expand Up @@ -124,8 +114,7 @@ And then your tasks hould be invoked as:

thor myapp:install name --force

Invocations
-----------
== Invocations

Thor comes with a invocation-dependency system as well which allows a task to be
invoked only once. For example:
Expand Down Expand Up @@ -158,8 +147,7 @@ The output is "1 2 3", which means that the three task was invoked only once.
You can even invoke tasks from another class, so be sure to check the
documentation.

Thor::Group
-----------
== Thor::Group

Thor has a special class called Thor::Group. The main difference to Thor class
is that it invokes all tasks at once. The example above could be rewritten in
Expand All @@ -185,10 +173,10 @@ When invoked:

thor counter

It prints "1 2 3" as well. Notice you should described (desc) only the class
and not each task anymore. Thor::Group is a great tool to create generators,
since you can define several steps which are invoked in the order they are
defined (Thor::Group is the tool use in generators in Rails 3.0).
It prints "1 2 3" as well. Notice you should describe (using the method <tt>desc</tt>)
only the class and not each task anymore. Thor::Group is a great tool to create
generators, since you can define several steps which are invoked in the order they
are defined (Thor::Group is the tool use in generators in Rails 3.0).

Besides, Thor::Group can parse arguments and options as Thor tasks:

Expand Down Expand Up @@ -218,17 +206,17 @@ The counter above expects one parameter and has the folling outputs:
thor counter 11
# Prints "11 12 13"

You can also give options to Thor::Group, but instead of using `method_option` and
`method_options`, you should use `class_option` and `class_options`. Both argument
and class_options methods are available to Thor class as well.
You can also give options to Thor::Group, but instead of using <tt>method_option</tt>
and <tt>method_options</tt>, you should use <tt>class_option</tt> and <tt>class_options</tt>.
Both argument and class_options methods are available to Thor class as well.

Actions
-------
== Actions

Thor comes with several actions which helps with script and generator tasks. You
might be familiar with them since some came from Rails Templates. They are: `say`,
`ask`, `yes?`, `no?`, `add_file`, `remove_file`, `copy_file`, `template`,
`directory`, `inside`, `run`, `inject_into_file` and a couple more.
might be familiar with them since some came from Rails Templates. They are:
<tt>say</tt>, <tt>ask</tt>, <tt>yes?</tt>, <tt>no?</tt>, <tt>add_file</tt>,
<tt>remove_file</tt>, <tt>copy_file</tt>, <tt>template</tt>, <tt>directory</tt>,
<tt>inside</tt>, <tt>run</tt>, <tt>inject_into_file</tt> and a couple more.

To use them, you just need to include Thor::Actions in your Thor classes:

Expand All @@ -241,7 +229,6 @@ Some actions like copy file requires that a class method called source_root is
defined in your class. This is the directory where your templates should be
placed. Be sure to check the documentation.

License
-------
== License

See MIT LICENSE.
33 changes: 30 additions & 3 deletions Thorfile
Expand Up @@ -2,6 +2,9 @@ require 'rubygems'
require 'rubygems/specification'
require 'thor/tasks'

require 'rubygems'
require 'rdoc/rdoc'

GEM = "thor"
GEM_VERSION = "0.11.3"
AUTHOR = "Yehuda Katz"
Expand Down Expand Up @@ -30,15 +33,39 @@ SPEC = Gem::Specification.new do |s|
end

class Default < Thor
include Thor::Actions

# Set up standard Thortasks
spec_task(Dir["spec/**/*_spec.rb"])
spec_task(Dir["spec/**/*_spec.rb"], :name => "rcov", :rcov => {:exclude => %w(spec task.thor Thorfile)})
install_task SPEC

desc "gemspec", "make a gemspec file"
def gemspec
File.open("#{GEM}.gemspec", "w") do |file|
file.puts SPEC.to_ruby
end
create_file "#{GEM}.gemspec", SPEC.to_ruby, :force => true
end

desc "rdoc PATH", "generate rdoc for the path passed as an argument"
def rdoc(path=File.dirname(__FILE__))
path = File.expand_path(path)
readme = File.join(path, "README.rdoc")

destination = File.join(Dir.pwd, 'rdoc')
remove_dir(destination)

# get all the files to process
files = Dir.glob("#{path}/lib/**/*.rb")
files += ["#{path}/README.rdoc", "#{path}/CHANGELOG.rdoc", "#{path}/LICENSE"]

# rdoc args
project = File.basename(path)
arguments = [
"-t", project,
"-m", readme,
"--op", destination
]

say_status :rdoc, "#{project} (#{files.size} files) to: #{destination}"
RDoc::RDoc.new.document(arguments + files)
end
end
8 changes: 4 additions & 4 deletions lib/thor.rb
Expand Up @@ -187,11 +187,11 @@ def help(shell, meth=nil, options={})
protected

# The banner for this class. You can customize it if you are invoking the
# thor class by another means which is not the Thor::Runner. It receives
# the task that is going to be invoked and if the namespace should be
# displayed.
# thor class by another ways which is not the Thor::Runner. It receives
# the task that is going to be invoked and a boolean which indicates if
# the namespace should be displayed as arguments.
#
def banner(task, namespace=true) #:nodoc:
def banner(task, namespace=true)
task.formatted_usage(self, namespace)
end

Expand Down
5 changes: 2 additions & 3 deletions lib/thor/actions.rb
Expand Up @@ -58,8 +58,7 @@ def source_paths_for_search
# It also accepts :force, :skip and :pretend to set the behavior
# and the respective option.
#
# destination_root<String>:: The root directory needed for some actions. It's also known
# as destination root.
# destination_root<String>:: The root directory needed for some actions.
#
def initialize(args=[], options={}, config={})
self.behavior = case config[:behavior].to_s
Expand All @@ -78,7 +77,7 @@ def initialize(args=[], options={}, config={})

# Wraps an action object and call it accordingly to the thor class behavior.
#
def action(instance)
def action(instance) #:nodoc:
if behavior == :revoke
instance.revoke!
else
Expand Down
2 changes: 1 addition & 1 deletion lib/thor/actions/directory.rb
Expand Up @@ -3,7 +3,7 @@
class Thor
module Actions

# Copies interactively the files from source directory to root directory.
# Copies recursively the files from source directory to root directory.
# If any of the files finishes with .tt, it's considered to be a template
# and is placed in the destination without the extension .tt. If any
# empty directory is found, it's copied and all .empty_directory files are
Expand Down
2 changes: 1 addition & 1 deletion lib/thor/actions/inject_into_file.rb
Expand Up @@ -34,7 +34,7 @@ def inject_into_file(destination, *args, &block)
action InjectIntoFile.new(self, destination, data, config)
end

class InjectIntoFile < EmptyDirectory
class InjectIntoFile < EmptyDirectory #:nodoc:
attr_reader :flag, :replacement

def initialize(base, destination, data, config)
Expand Down
37 changes: 14 additions & 23 deletions lib/thor/base.rb
Expand Up @@ -78,7 +78,6 @@ def subclass_files

# Whenever a class inherits from Thor or Thor::Group, we should track the
# class and the file on Thor::Base. This is the method responsable for it.
# Also adds the source root to the source paths if the klass respond to it.
#
def register_klass_file(klass) #:nodoc:
file = caller[1].match(/(.*):\d+/)[1]
Expand Down Expand Up @@ -246,7 +245,8 @@ def group(name=nil)
# Returns the tasks for this Thor class.
#
# ==== Returns
# OrderedHash:: An ordered hash with this class tasks.
# OrderedHash:: An ordered hash with tasks names as keys and Thor::Task
# objects as values.
#
def tasks
@tasks ||= Thor::CoreExt::OrderedHash.new
Expand All @@ -255,7 +255,8 @@ def tasks
# Returns the tasks for this Thor class and all subclasses.
#
# ==== Returns
# OrderedHash
# OrderedHash:: An ordered hash with tasks names as keys and Thor::Task
# objects as values.
#
def all_tasks
@all_tasks ||= from_superclass(:all_tasks, Thor::CoreExt::OrderedHash.new)
Expand Down Expand Up @@ -342,7 +343,7 @@ def namespace(name=nil)

# Default way to start generators from the command line.
#
def start(given_args=ARGV, config={}) #:nodoc:
def start(given_args=ARGV, config={})
config[:shell] ||= Thor::Base.shell.new
yield
rescue Thor::Error => e
Expand All @@ -360,7 +361,7 @@ def start(given_args=ARGV, config={}) #:nodoc:
# hooks to add extra options, one of them if the third argument called
# extra_group that should be a hash in the format :group => Array[Options].
#
# The second is by returning a lamda used to print values. The lambda
# The second is by returning a lambda used to print values. The lambda
# requires two options: the group name and the array of options.
#
def class_options_help(shell, ungrouped_name=nil, extra_group=nil) #:nodoc:
Expand All @@ -377,24 +378,14 @@ def class_options_help(shell, ungrouped_name=nil, extra_group=nil) #:nodoc:

options.each do |option|
item = [ option.usage(padding) ]

item << if option.description
"# #{option.description}"
else
""
end
item.push(option.description ? "# #{option.description}" : "")

list << item
list << [ "", "# Default: #{option.default}" ] if option.show_default?
end

unless list.empty?
if group_name
shell.say "#{group_name} options:"
else
shell.say "Options:"
end

shell.say(group_name ? "#{group_name} options:" : "Options:")
shell.print_table(list, :ident => 2)
shell.say ""
end
Expand All @@ -412,7 +403,7 @@ def class_options_help(shell, ungrouped_name=nil, extra_group=nil) #:nodoc:

# Raises an error if the word given is a Thor reserved word.
#
def is_thor_reserved_word?(word, type)
def is_thor_reserved_word?(word, type) #:nodoc:
return false unless THOR_RESERVED_WORDS.include?(word.to_s)
raise "#{word.inspect} is a Thor reserved word and cannot be defined as #{type}"
end
Expand All @@ -423,7 +414,7 @@ def is_thor_reserved_word?(word, type)
# name<Symbol>:: The name of the argument.
# options<Hash>:: Described in both class_option and method_option.
#
def build_option(name, options, scope)
def build_option(name, options, scope) #:nodoc:
scope[name] = Thor::Option.new(name, options[:desc], options[:required],
options[:type], options[:default], options[:banner],
options[:group], options[:aliases])
Expand All @@ -437,7 +428,7 @@ def build_option(name, options, scope)
# ==== Parameters
# Hash[Symbol => Object]
#
def build_options(options, scope)
def build_options(options, scope) #:nodoc:
options.each do |key, value|
scope[key] = Thor::Option.parse(key, value)
end
Expand All @@ -447,7 +438,7 @@ def build_options(options, scope)
# class, just return it, otherwise dup it and add the fresh copy to the
# current task hash.
#
def find_and_refresh_task(name)
def find_and_refresh_task(name) #:nodoc:
task = if task = tasks[name.to_s]
task
elsif task = all_tasks[name.to_s]
Expand All @@ -465,7 +456,7 @@ def inherited(klass)
end

# Fire this callback whenever a method is added. Added methods are
# tracked as tasks if the requirements set by valid_task? are valid.
# tracked as tasks by invoking the create_task method.
#
def method_added(meth)
meth = meth.to_s
Expand All @@ -486,7 +477,7 @@ def method_added(meth)
end

# Retrieves a value from superclass. If it reaches the baseclass,
# returns nil.
# returns default.
#
def from_superclass(method, default=nil)
if self == baseclass || !superclass.respond_to?(method, true)
Expand Down
4 changes: 2 additions & 2 deletions lib/thor/core_ext/hash_with_indifferent_access.rb
@@ -1,5 +1,5 @@
class Thor
module CoreExt
module CoreExt #:nodoc:

# A hash with indifferent access and magic predicates.
#
Expand All @@ -9,7 +9,7 @@ module CoreExt
# hash['foo'] #=> 'bar'
# hash.foo? #=> true
#
class HashWithIndifferentAccess < ::Hash
class HashWithIndifferentAccess < ::Hash #:nodoc:

def initialize(hash={})
super()
Expand Down
4 changes: 1 addition & 3 deletions lib/thor/core_ext/ordered_hash.rb
@@ -1,6 +1,4 @@
require 'forwardable'

class Thor #:nodoc:
class Thor
module CoreExt #:nodoc:

if RUBY_VERSION >= '1.9'
Expand Down

0 comments on commit a659385

Please sign in to comment.