class BitGirder::Core::BitGirderCliApplication

Public Class Methods

get_subcommand( commands ) click to toggle source
# File lib/bitgirder/core.rb, line 1135
def self.get_subcommand( commands )
    
    idx = ARGV.find_index { |arg| ! arg.start_with?( "-" ) }
    
    return nil unless idx

    cmd_str = ARGV.delete_at( idx )
    cmd_sym = cmd_str.gsub( "-", "_" ).to_sym
 
    unless res = commands[ cmd_sym ]
        raise UnrecognizedSubcommandError, cmd_str
    end

    res
end
new( opts = {} ) click to toggle source
# File lib/bitgirder/core.rb, line 940
def initialize( opts = {} )

    super( opts )
    raise "No such method: #@main_method" unless respond_to?( @main_method )

    @verbose = BitGirderLogger.is_debug_env_set?
end
run( cls ) click to toggle source
# File lib/bitgirder/core.rb, line 1127
def self.run( cls )

    BitGirderMethods::not_nil( cls, :cls )
    self.new( :app_class => cls ).run( ARGV )
end
run_subcommand_app( opts ) click to toggle source
# File lib/bitgirder/core.rb, line 1161
def self.run_subcommand_app( opts )

    cmds = has_key( opts, :commands )
    
    cmd_cls = begin
        self.get_subcommand( cmds )
    rescue UnrecognizedSubcommandError => e
        STDERR.puts( "Unrecognized command: #{e}" )
    end

    if cmd_cls
        self.run( cmd_cls )
    else
        self.show_subcommand_help( cmds )
    end
end
show_subcommand_help( cmds ) click to toggle source
# File lib/bitgirder/core.rb, line 1151
def self.show_subcommand_help( cmds )
    
    print "\ncommands:\n\n"

    cmds.keys.sort.map { |s| s.to_s.gsub( "_", "-" ) }.
         each { |s| puts "#{ " " * 4 }#{s}" }

    puts
end

Public Instance Methods

run( argv = ARGV ) click to toggle source
# File lib/bitgirder/core.rb, line 1103
def run( argv = ARGV )
 
    p, argh = configure_parser

    begin
        p.parse!( argv = argv.dup )
        app_obj = create_app_obj( argh )
    rescue SystemExit => e
        skip_main = true
    rescue Exception => e

        puts e
        puts p.to_s

        if @verbose || BitGirderLogger.is_debug_env_set?
            puts e.backtrace.join( "\n" ) 
        end

        exit EXIT_FAILURE
    end
 
    run_main( app_obj, argv ) unless skip_main
end

Private Instance Methods

configure_parser() click to toggle source
# File lib/bitgirder/core.rb, line 1030
def configure_parser
    
    p = create_base_parser
    argh = {}

    cd = BitGirderClassDefinition.for_class( @app_class )
    ( cd.attrs.keys - [ :main_method, :app_class ] ).each do |ident|
        
        attr = cd.attrs[ ident ]
        argv = get_opt_parser_argv( attr )

        p.on( *argv ) { |arg| 
            parse_arg( :arg => arg, :argh => argh, :attr => attr ) 
        }
    end

    [ p, argh ]
end
create_app_obj( argh ) click to toggle source
# File lib/bitgirder/core.rb, line 1050
def create_app_obj( argh )
    
    BitGirderClassDefinition.validation_listener =
        lambda { |attr, e| 

            warn( e, "Validation of attr #{attr} failed" ) if @verbose
            cli_opt = sym_to_cli_switch( attr.identifier )
            raise "#{cli_opt}: #{e.message}"
        }

    @app_class.new( argh )
end
create_base_parser() click to toggle source
# File lib/bitgirder/core.rb, line 949
def create_base_parser
    
    p = OptionParser.new

    p.on( "-v", "--[no-]verbose", "Run verbosely" ) { |flag|

        @verbose = flag

        BitGirderLogger.get_logger.level = to_bool( flag ) ? 
            BitGirderLogger::CODE : BitGirderLogger::DEFAULT
    }

    p.on( "-h", "--help", "Print this help" ) { 
        puts p
        exit 0
    }
end
default_to_s( defl ) click to toggle source
# File lib/bitgirder/core.rb, line 968
def default_to_s( defl )
    
    case defl
        when STDOUT then "stdout"
        when STDIN then "stdin"
        when STDERR then "stderr"
        else defl.to_s
    end
end
fail_run_main( e ) click to toggle source
# File lib/bitgirder/core.rb, line 1070
def fail_run_main( e )
    
    log = BitGirderLogger.get_logger
    
    if @verbose
        log.warn( e, "App failed" )
    else
        STDERR.puts( e.message )
    end

    exit EXIT_FAILURE
end
get_opt_parser_argv( attr ) click to toggle source
# File lib/bitgirder/core.rb, line 979
def get_opt_parser_argv( attr )

    argv = []
    
    switch_str = attr.identifier.to_s.gsub( /_/, "-" )

    if attr.processor == BitGirderAttribute::PROCESSOR_BOOLEAN
        argv << "--[no-]#{switch_str}"
    else
        argv << "--#{switch_str} VAL"
    end

    if desc = attr.description

        # attr default could be the boolean false, which we still want to
        # display
        unless ( defl = attr.get_default_value ) == nil
            defl = defl.call if defl.is_a?( Proc )
            desc += " (Default: #{default_to_s( defl )})"
        end

        argv << desc
    end

    argv
end
make_run_ctx( argv_remain ) click to toggle source
# File lib/bitgirder/core.rb, line 1064
def make_run_ctx( argv_remain )
    
    { :argv_remain => argv_remain, :verbose => @verbose }
end
parse_arg( argh ) click to toggle source
# File lib/bitgirder/core.rb, line 1007
    def parse_arg( argh )
 
        attr = argh[ :attr ]
        ident = attr.identifier

        # could be nil either way
        prev = argh[ :argh ][ ident ] || attr.get_default_value
        
        val = argh[ :arg ]
#        val = attr.processor.call( val ) if attr.processor

        if attr.is_list
            if prev == nil
                val = [ val ]
            else
                val = ( prev << val )
            end
        end

        argh[ :argh ][ ident ] = val
    end
run_main( app_obj, argv_remain ) click to toggle source
# File lib/bitgirder/core.rb, line 1084
def run_main( app_obj, argv_remain )
    
    meth = app_obj.class.instance_method( @main_method )

    args = 
        case arity = meth.arity
            when 0 then []
            when 1 then [ make_run_ctx( argv_remain ) ]
            else raise "Invalid arity for #{meth}: #{arity}"
        end

    begin
        meth.bind( app_obj ).call( *args )
    rescue Exception => e
        fail_run_main( e )
    end
end