Repository URL to install this package:
|
Version:
1.1 ▾
|
#
# appl.rb -- Application class
#
class Application
APPL_VERSION = "1.1".freeze
OPTIONS_ENV = nil
STOPOPT = "stop option processing"
UNKNOWN = "Unknown option"
UNPROCA = "Warning: unprocessed arguments"
class OptionError < StandardError ; end
class Done < Exception ; end
def initialize args = nil
@args = args||self.class.cmdline_arguments
self.class.each_option { |opt,desc,arg,dfl,act|
begin
send act, dfl if dfl
rescue NoMethodError
raise OptionError, "Option action `#{act}' is not defined."
end
}
while @args.first =~ /\A-/ do
opt = $'
@args.shift
if opt =~ /\A-/ then
break if $'.empty?
opt = $'
if opt =~ /=/ then opt = $` ; @args.unshift $' end
act = self.class.option_act @args, opt, nil
send *act
else
until opt.empty? do
c = opt.slice! 0, 1
act = self.class.option_act @args, c, opt
send *act
end
end
end
end
def help
c = self.class
puts c.version
puts
puts c::DESCRIPTION
puts
c.show_options
if block_given? then
puts
yield
end
raise Done
end
def version
self.class.show_version
raise Done
end
VERSION = "0"
NAME = "appl"
SUMMARY = "Dummy application"
DESCRIPTION = <<-EOT
This base class does nothing by default.
EOT
def run
end
def execute
run
if @args.any? then
u = @args.join " "
puts "#{self.class::UNPROCA}: #{u}"
end
0
rescue SignalException
raise if @debug
self.class.show_message $!.inspect
128 + ($!.signo||2) # Ruby 1.8 returns signo +nil+; assume SIGINT
rescue
raise if @debug
self.class.show_message "Error: #$!", "(#{$!.class})"
$!.to_i rescue 1
end
HASH_ORDER = RUBY_VERSION >= "1.9"
class <<self
def run args = nil
e = execute args
exit e
end
def version
if self::VERSION =~ %r/\s/ then
self::VERSION
else
"#{self::NAME} #{self::VERSION} -- #{self::SUMMARY}"
end
end
private
def execute args = nil
i = new args
i.execute
rescue Done
0
rescue OptionError
show_message $!
127
end
def inherited sub
sub.instance_eval { @options, @aliases = {}, {} }
end
def attr_bang *syms
syms.each { |sym|
define_method :"#{sym}!" do
instance_variable_set :"@#{sym}", true
end
}
nil
end
public
def define_option opt, *param
delete_option opt
act = param.shift
desc = param.pop
arg = param.shift
if arg then
if param.empty? then
arg, dfl = arg.split /:/, 2
if dfl =~ /\A:/ then
dfl = $'.to_sym
end
else
dfl = param.shift
end
end
d = param.map { |x| "#{x}#$/" }.join
desc.insert 0, d
@options[ opt.to_s] = [ desc, arg, dfl, act]
nil
end
alias def_option define_option
def alias_option orig, opt
unalias_option opt
@aliases[ opt.to_s] = orig.to_s
nil
end
def delete_option opt
self < Application or return
superclass.delete_option opt
@options.delete opt
@aliases.reject! { |k,v| v == opt }
nil
end
def unalias_option opt
self < Application or return
superclass.unalias_option opt
@aliases.delete opt
nil
end
protected
def find_option_act opt
self < Application or return
@options[ opt] || @options[ @aliases[ opt]] ||
(superclass.find_option_act opt)
end
def all_options
if self < Application then
r = superclass.all_options
r.update @options
else
{}
end
end
def all_aliases
if self < Application then
r = superclass.all_aliases
r.update @aliases
else
{}
end
end
def options_desc &block
a = Hash.new do |h,k| h[ k] = [] end
all_aliases.each { |k,v|
a[ v].push k
}
a.values.each { |v| v.sort! } unless HASH_ORDER
each_option { |opt,desc,arg,dfl,|
yield opt, arg, dfl, desc
a[ opt].each { |l|
yield l, nil, nil, nil
}
}
yield "", nil, nil, self::STOPOPT
end
public
def each_option
o = all_options
o = o.sort_by { |k,v| k.swapcase } unless HASH_ORDER
o.each { |opt,(desc,arg,dfl,act)|
case dfl
when Symbol then dfl = const_get dfl
end
yield opt, desc, arg, dfl, act
}
end
def option_act args, opt, rest
dada = find_option_act opt
dada or raise OptionError, "#{self::UNKNOWN}: `#{opt}'."
desc, arg, dfl, act = *dada
r = [ act]
if arg then
p = rest.slice! 0, rest.length if rest and not rest.empty?
r.push p||args.shift
end
r
end
def show_options
options_desc do |opt,arg,dfl,desc|
opt = opt.length == 1 ? "-#{opt}" : "--#{opt}"
arg &&= "#{arg}"
dfl &&= "[#{dfl}]"
arg << dfl if arg && dfl
puts " %-10s %-12s %s" % [ opt, arg, desc]
end
end
def show_version
puts version
puts self::COPYRIGHT if const_defined? :COPYRIGHT
puts "License: #{self::LICENSE}" if const_defined? :LICENSE
a = []
a.push self::AUTHOR if const_defined? :AUTHOR
a.concat self::AUTHORS if const_defined? :AUTHORS
if a.any? then
a.flatten!
a.uniq!
j = a.join ", "
h = a.length == 1 ? "Author" : "Authors"
puts "#{h}: #{j}"
end
end
def show_message msg, extra = nil
if $stderr.tty? then
msg = "\e[31;1m#{msg}\e[m"
if extra then
extra = "\e[31m#{extra}\e[m"
end
end
if extra then
msg = [ msg, extra].join " "
end
$stderr.puts msg
end
def cmdline_arguments
r = []
oe = self::OPTIONS_ENV
eo = ENV[ oe] if oe
if eo then
eo.scan /"((?:\\.|[^"])*")|[^" \t]+/ do
r.push $1 ? (eval $1) : $&
end
end
r.concat $*
r
end
end
end