dencli/lib/dencli/sub.rb

75 lines
1.9 KiB
Ruby

require_relative '../dencli'
class DenCli::Sub
attr_reader :parent, :name, :desc, :subs, :aliases
def initialize parent, name, desc
@parent, @name, @desc, @subs, @aliases = parent, name, "-> #{desc}", {}, {}
end
def _full_cmd( post) parent._full_cmd [@name]+post end
def full_cmd() _full_cmd [] end
def []( k) @aliases[k] end
def help n = nil, *a
if n.nil?
r = "#{full_cmd.join ' '}: #{desc}\n\n"
m = @subs.map {|k,_| k.length }.max
@subs.each do |k, c|
r += " % -#{m}s %s\n" % [k, c.desc] unless k.nil?
end
r
elsif @aliases.has_key? n
@aliases[n].help *a
else
raise UnknownCommand, "unknown command: #{_full_cmd( [n])[1..-1].join ' '}, available for #{full_cmd[1..-1].join' '}: #{@subs.keys.join ' '}"
end
end
def call *a
n, *a = *a
if @aliases.has_key? n
@aliases[n].call *a
else
raise UnknownCommand, "unknown command: #{_full_cmd( [n])[1..-1].join ' '}, available for #{full_cmd[1..-1].join' '}: #{@subs.keys.join ' '}"
end
end
def _add name, min, obj, aliases
name = name.to_s unless name.nil?
@subs[name] = obj
DenCli.gen_aliases( name, min) {|a| @aliases[a] = obj }
if aliases
[*aliases].each {|a| @aliases[a] = obj }
end
obj
end
private :_add
def sub name, desc, min: nil, aliases: nil, &exe
r = _add name, min, DenCli::Sub.new( self, name, desc), aliases
block_given? ? yield( r) : r
end
def cmd name, desc, min: nil, aliases: nil, &exe
_add name, min, DenCli::CMD.new( self, name, desc, exe), aliases
end
def complete *pre, str
if pre.empty?
@subs.keys.grep /\A#{Regexp.escape str}/
elsif sub = @subs[pre[0]]
sub.complete *pre[1..-1], str
else
STDOUT.print "\a"
end
end
def inspect
"#<%s:0x%x %s @name=%p @desc=%p @subs={%s} @aliases={%s} @parent=<%s:0x%x %s>>" % [
self.class.name, self.object_id, self.full_cmd,
@name, @desc, @subs.keys.join(', '), @aliases.keys.join(', '), @parent.class.name, @parent.class.object_id, @parent.full_cmd
]
end
end