Skip to content

Commit

Permalink
2007-05-11 Laurent Sansonetti <lsansonetti@apple.com>
Browse files Browse the repository at this point in the history
  * bin/rdoc-osa:
  Better generator, can now handle scripting additions.


git-svn-id: http://rubyosa.rubyforge.org/svn/trunk@205 0d7f026f-1217-0410-b43a-e108cceea134
  • Loading branch information
lrz committed Apr 11, 2007
1 parent effa368 commit b6887b3
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 76 deletions.
3 changes: 3 additions & 0 deletions ChangeLog
@@ -1,5 +1,8 @@
2007-05-11 Laurent Sansonetti <lsansonetti@apple.com> 2007-05-11 Laurent Sansonetti <lsansonetti@apple.com>


* bin/rdoc-osa:
Better generator, can now handle scripting additions.

* AUTHORS: * AUTHORS:
Added Mike and Carlos. Added Mike and Carlos.


Expand Down
195 changes: 119 additions & 76 deletions bin/rdoc-osa
Expand Up @@ -33,138 +33,181 @@ require 'rbconfig'
require 'rbosa' require 'rbosa'


def usage def usage
STDERR.puts <<-EOS STDERR.puts <<-EOS
Usage: #{$0} [--name | --path | --bundle_id | --signature] <criterion> [rdoc-options...] Usage: #{$0} [--addition] [--name | --path | --bundle_id | --signature] <criterion> [rdoc-options...]
Examples: Examples:
# Generate HTML documentation for iTunes: # Generate HTML documentation for iTunes:
#{$0} --name iTunes #{$0} --name iTunes
# Generate RI documentation for iTunes: # Generate RI documentation for iTunes:
#{$0} --name iTunes --ri #{$0} --name iTunes --ri
# Generate HTML documentation for the StandardAdditions scriptable addition:
#{$0} --addition --name StandardAdditions
See rdoc --help for additional options. See rdoc --help for additional options.
EOS EOS
exit 1 exit 1
end end


def unique_tmp_path(base, extension='', dir=Dir.tmpdir) def unique_tmp_path(base, extension='', dir=Dir.tmpdir)
i = 0 i = 0
loop do loop do
p = File.join(dir, "#{base}-#{i}-#{Process.pid}" + extension) p = File.join(dir, "#{base}-#{i}-#{Process.pid}" + extension)
return p unless File.exists?(p) return p unless File.exists?(p)
i += 1 i += 1
end end
end end


usage unless ARGV.length >= 2 usage unless ARGV.length >= 2

addition = key = criterion = nil
key = case ARGV.first while arg = ARGV.shift
when '--name' case arg
:name when '--addition'
when '--path' addition = true
:path when '--name', '--path', '--bundle_id', '--signature'
when '--bundle_id' if key
:bundle_id $stderr.puts "You cannot use --name, --path, --bundle_id or --signature more than once."
when '--signature' exit 1
:signature end
else key = arg[2..-1].intern
usage criterion = ARGV.shift
usage if criterion.nil?
else
if key and criterion
ARGV.unshift(arg)
break
end
usage
end
end end


DOC_NOT_AVAILABLE = 'Documentation not available.' DOC_NOT_AVAILABLE = 'Documentation not available.'


app = OSA.app(key => ARGV[1]) app = app_name = nil
app_name = if app.respond_to?(:name)
app.name if addition
app_name = criterion if key == :name
mod = Module.new
OSA.const_set('TheApplication', mod)
klass = Class.new(OSA::Element)
mod.const_set('Application', klass)
klass.class_eval do
include OSA::EventDispatcher
METHODS_DESCRIPTION = []
DESCRIPTION = 'The application class.'
end
app = klass.new.merge(key => criterion)
else else
app = OSA.app(key => criterion)
app_name = if app.respond_to?(:name)
app.name
else
if key != :name if key != :name
STDERR.puts "Can't guess the application name, because the application doesn't have a #name method. Please use `--name' instead." STDERR.puts "Can't guess the application name, because the application doesn't have a #name method. Please use `--name' instead."
exit 1 exit 1
else else
ARGV[1] criterion
end end
end
end end


mod = OSA.const_get(app.class.name.scan(/^OSA::(.+)::Application$/).to_s) mod = OSA.const_get(app.class.name.scan(/^OSA::(.+)::Application$/).to_s)
fake_ruby_src = mod.constants.map do |const_name| fake_ruby_src = mod.constants.map do |const_name|
obj = mod.const_get(const_name) obj = mod.const_get(const_name)
case obj case obj
when Class when Class
# Class. # Class.
methods_desc = obj.const_get('METHODS_DESCRIPTION').map do |method| methods_desc = obj.const_get('METHODS_DESCRIPTION').map do |method|
args_doc, args_def, args_def_opt = '', '', '' args_doc, args_def, args_def_opt = '', '', ''
if method.args and !method.args.empty? if method.args and !method.args.empty?
args_doc_ary, args_def_ary, args_def_opt_ary = [], [], [] args_doc_ary, args_def_ary, args_def_opt_ary = [], [], []
method.args.each do |x| method.args.each do |x|
arg = x.name arg = x.name
desc = x.description desc = x.description
desc = DOC_NOT_AVAILABLE if desc.empty? desc = DOC_NOT_AVAILABLE if desc.empty?
args_doc_ary << " # #{arg}::\n # #{desc}" + (x.optional? ? ' Optional. Can be passed as a Hash key/value.' : '') args_doc_ary << " # #{arg}::\n # #{desc}" + (x.optional? ? ' Optional. Can be passed as a Hash key/value.' : '')
if x.optional? if x.optional?
args_def_ary << x.name + '=nil' args_def_ary << x.name + '=nil'
args_def_opt_ary << ':' + x.name + ' => nil' args_def_opt_ary << ':' + x.name + ' => nil'
else else
args_def_ary << x.name args_def_ary << x.name
args_def_opt_ary << x.name args_def_opt_ary << x.name
end end
end end
args_doc = args_doc_ary.join("\n") args_doc = args_doc_ary.join("\n")
args_def = '(' + args_def_ary.join(', ') + ')' args_def = '(' + args_def_ary.join(', ') + ')'
args_def_opt = '(' + args_def_opt_ary.join(', ') + ')' args_def_opt = '(' + args_def_opt_ary.join(', ') + ')'
end end
if method.result if method.result
args_doc << "\n" unless args_doc.empty? args_doc << "\n" unless args_doc.empty?
desc = method.result.description desc = method.result.description
desc = DOC_NOT_AVAILABLE if desc.empty? desc = DOC_NOT_AVAILABLE if desc.empty?
args_doc << " # Returns::\n # #{desc}\n" args_doc << " # Returns::\n # #{desc}\n"
end end
<<EOS <<EOS
# call-seq: # call-seq:
# #{method.name + args_def} # #{method.name + args_def}
# #{args_def_opt != args_def ? method.name + args_def_opt : ''} # #{args_def_opt != args_def ? method.name + args_def_opt : ''}
# #
# #{method.description} # #{method.description}
#{args_doc} #{args_doc}
def #{method.name}#{args_def}; end def #{method.name}#{args_def}; end
EOS EOS
end end
<<EOS <<EOS
# #{(obj.const_get('DESCRIPTION') || 'n/a')} # #{(obj.const_get('DESCRIPTION') || 'n/a')}
class #{obj.name} < #{obj.superclass} class #{obj.name} < #{obj.superclass}
#{methods_desc.join.rstrip} #{methods_desc.join.rstrip}
end end
EOS EOS
when Module when Module
# Enumeration group. # Enumeration group.
next unless obj.const_defined?(:DESCRIPTION) next unless obj.const_defined?(:DESCRIPTION)
enums_desc = obj.const_get(:DESCRIPTION).map do |item| enums_desc = obj.const_get(:DESCRIPTION).map do |item|
<<EOS <<EOS
# #{item.description} # #{item.description}
#{item.name} = '#{obj.const_get(item.name).code}' #{item.name} = '#{obj.const_get(item.name).code}'
EOS EOS
end end
<<EOS <<EOS
module #{mod.name}::#{const_name} module #{mod.name}::#{const_name}
#{enums_desc} #{enums_desc}
end end
EOS EOS
end end
end. end.
join join


fake_ruby_src = <<EOS + fake_ruby_src header = if addition
<<EOS
# This documentation describes the RubyOSA API for the #{criterion} scriptable addition. It has been automatically generated.
#
# In order to use this API you have to merge the scriptable addition into an application object. For instance:
#
# OSA.app('iTunes').merge(#{app_name ? "'#{app_name}'" : ":#{key} => '#{criterion}'"})
#
# The module OSA::TheApplication is fake, everything inside will be defined in the module of the application you are controlling (for iTunes, in OSA::ITunes).
EOS
else
<<EOS
# This documentation describes the RubyOSA API for the #{app_name} application. It has been automatically generated. # This documentation describes the RubyOSA API for the #{app_name} application. It has been automatically generated.
# #
# The main class is #{mod.name}::Application, of which an instance is created likewise: # The main class is #{mod.name}::Application, of which an instance is created likewise:
# #
# OSA.app('#{app_name}') # OSA.app('#{app_name}')
EOS
end

header << <<EOS
# #
# For more information about RubyOSA, please visit the project homepage: http://rubyosa.rubyforge.org. # For more information about RubyOSA, please visit the project homepage: http://rubyosa.rubyforge.org.
module OSA; end module OSA; end
# The #{app_name} module. # The #{app_name} module.
module #{mod.name}; end module #{mod.name}; end
EOS EOS


fake_ruby_src = header << fake_ruby_src

rdoc_flags = '' rdoc_flags = ''
datadir = if Config.respond_to?(:datadir) datadir = if Config.respond_to?(:datadir)
Config.datadir('rubyosa') Config.datadir('rubyosa')
Expand All @@ -173,17 +216,17 @@ else
end end
template = File.join(datadir, 'rdoc_html.rb') template = File.join(datadir, 'rdoc_html.rb')
if File.exists?(template) if File.exists?(template)
rdoc_flags << " --template '#{template}' " rdoc_flags << " --template '#{template}' "
end end
rdoc_flags << " --title '#{app_name} RubyOSA API' " rdoc_flags << " --title '#{app_name} RubyOSA API' "
rdoc_flags << ' --main OSA ' rdoc_flags << ' --main OSA '
rdoc_flags << ARGV[2..-1].join(' ') rdoc_flags << ARGV.join(' ')


path = unique_tmp_path(app_name, '.rb') path = unique_tmp_path(app_name, '.rb')
File.open(path, 'w') { |io| io.puts fake_ruby_src } File.open(path, 'w') { |io| io.puts fake_ruby_src }
line = "rdoc #{rdoc_flags} \"#{path}\"" line = "rdoc #{rdoc_flags} \"#{path}\""
unless system(line) unless system(line)
STDERR.puts "Error when executing `#{line}' : #{$?}" STDERR.puts "Error when executing `#{line}' : #{$?}"
exit 1 exit 1
end end
File.unlink(path) File.unlink(path)

0 comments on commit b6887b3

Please sign in to comment.