diff --git a/bin/example.rb b/bin/example.rb index 006c188..2575dc7 100755 --- a/bin/example.rb +++ b/bin/example.rb @@ -1,10 +1,9 @@ #!/usr/bin/env ruby require 'pathname' -$:.unshift Pathname.new(__FILE__).dirname.dirname.join('lib').to_s -require 'dencli' require 'shellwords' require 'stringio' +require_relative '../lib/dencli' cli = DenCli.new :example, "This is an example for generate a DenCli-API" @@ -33,8 +32,8 @@ class Capture STDERR.printf "[% 4d] \e[1;35m? \e[0m %s tests %s\r", @counter, $0.shellescape, command.shelljoin end - def logok command - STDERR.printf "[% 4d] \e[1;32mok\e[0m %s tests %s\e[J\n", @counter, $0.shellescape, command.shelljoin + def logok info, command + STDERR.printf "[% 4d] \e[1;32mok\e[0m %s | %s tests %s\e[J\n", @counter, info, $0.shellescape, command.shelljoin end def logfail command @@ -54,7 +53,7 @@ class Capture logstart command $capture.capture { @cli.call 'tests', *command } if expect === @args - logok command + logok @args, command else logfail command loginfo "expected args: #{expect.inspect}" @@ -63,7 +62,7 @@ class Capture end rescue SystemExit if 0 == $!.status - logok command + logok @args, command else logfail command end @@ -79,7 +78,7 @@ class Capture logfail command rescue exception if message === $!.message - logok command + logok exception, command if @verbose logexception "raised:", $! STDERR.puts @@ -96,6 +95,14 @@ class Capture end cli.sub :tests, "Some tests", noshortaliases: true do |tcli| + OptionParser.accept IPAddr do |arg| + begin + IPAddr.new arg + rescue IPAddr::InvalidAddressError + raise OptionParser::InvalidArgument, "#{$!.message}: #{arg}" + end + end + tcli.cmd( :'-', "No arguments no options expected", &lambda {|| $capture.args = [] }) tcli.cmd( :'arg', "", &lambda {|one| $capture.args = [one] }) tcli.cmd( :'oar', "", &lambda {|one=nil| $capture.args = [one] }) @@ -109,6 +116,7 @@ cli.sub :tests, "Some tests", noshortaliases: true do |tcli| tcli.cmd( :'str', '', &lambda {|a:| $capture.args = [a] }).opt(:a, '-a=STR', '') tcli.cmd( :'lstr', '', &lambda {|a:| $capture.args = [a] }).opt(:a, '--astr=STR', '') tcli.cmd( :'bstr', '', &lambda {|a:| $capture.args = [a] }).opt(:a, '-a', '--astr=STR', '') + tcli.cmd( :'ipaddr', '', &lambda {|a:| $capture&.args = [a] }).opt(:a, '-a', '--addr=ADDR', IPAddr, '') tcli.cmd( :run, "Run all tests") do |verbose:| $capture = Capture.new cli, verbose: verbose @@ -187,6 +195,9 @@ cli.sub :tests, "Some tests", noshortaliases: true do |tcli| $capture.should_fail OptionParser::InvalidOption, //, 'bstr', '-b' $capture.should_fail OptionParser::InvalidOption, //, 'bstr', '--unexpected' $capture.should_fail DenCli::UsageError, //, 'bstr', 'unexpected' + + $capture.should_ok [IPAddr.new('1.2.3.4')], 'ipaddr', '-a', '1.2.3.4' + $capture.should_fail OptionParser::InvalidArgument, /invalid address/, 'ipaddr', '-a', '1.2.3.400' end.opt( :verbose, '-v', 'Prints additional information per test', default: false) end diff --git a/lib/dencli/cmd.rb b/lib/dencli/cmd.rb index f057b2d..e16385d 100644 --- a/lib/dencli/cmd.rb +++ b/lib/dencli/cmd.rb @@ -160,7 +160,7 @@ class DenCli::CMD end class Opt - attr_reader :name, :long, :short, :val, :desc, :os, :conv, :req + attr_reader :name, :long, :short, :type, :val, :desc, :conv, :req def required?() @req end def default?() NilClass != @default end def default() NilClass == @default ? nil : @default end @@ -183,11 +183,12 @@ class DenCli::CMD end private :parse_opt_string - def initialize cmd, name, opt, *alts, desc, default: NilClass, **os, &conv - @name, @desc, @default, @os, @conv, @val = - name.to_s.to_sym, desc, default, os, conv || lambda{|v|v}, nil + def initialize cmd, name, opt, *args, desc, default: NilClass, &conv + @name, @desc, @default, @conv, @val, @type = + name.to_s.to_sym, desc, default, conv || lambda{|v|v}, nil, nil parse_opt_string opt - alts.each &method( :parse_opt_string) + @type = args.pop if OptionParser.top.atype.has_key? args.last + args.each &method( :parse_opt_string) @req = if NilClass != default false @@ -200,30 +201,32 @@ class DenCli::CMD def on parser, store store[@name] = @default if default? - parser.on "#{@short}#{@val ? ?= : ''}#{@val}", "#{@long}#{@val ? ?= : ''}#{@val}", **@os do |val| + short = "#{@short}#{@val ? ?= : ''}#{@val}" + long = "#{@long}#{@val ? ?= : ''}#{@val}" + parser.on short, long, *[@type].compact do |val| store[@name] = @conv[val] end end def inspect - "#<%s:0x%016x %s %s %s %s (%p) %p os=%p conv=%s>" % [ + "#<%s:0x%x %s %s %s %s (%p) %p conv=%s>" % [ self.class.name, object_id, @req ? "<#{@name}>" : "[#{@name}]", - @short, @long, @val, @default, @desc, @os, + @short, @long, @val, @default, @desc, @type ? " type=#{type}" : '', @exe ? "<#{@exe.lambda? ? :lambda: :proc} ##{@exe.arity}>" : "nil" ] end end - def opt name, opt, *alts, desc, **os, &conv - r = Opt.new( self, name, opt, *alts, desc, **os, &conv) + def opt name, opt, *args, desc, &conv + r = Opt.new( self, name, opt, *args, desc, &conv) @options[r.name] = r self end def inspect - "#<%s:0x%x %s @name=%p @description=%p @parent=<%s:0x%x %s> @exe=>" % [ + "#<%s:0x%x %s @name=%p @description=%p @options=%p @parent=<%s:0x%x %s> @exe=>" % [ self.class.name, self.object_id, self.full_cmd, - @name, @description, @parent.class.name, @parent.class.object_id, @parent.full_cmd, + @name, @description, @options.values, @parent.class.name, @parent.class.object_id, @parent.full_cmd, @exe.arity ] end