#!/usr/bin/env python import sys import yaml import empty import base import dbg def new(): av = sys.argv[1:] # copy idx = lambda s: av.index(s) if s in av else -1 def idx_startswith(s): for i in range( len(av) ): if av[i].startswith(s): return i return -1 def pop_str(k, dv=''): i = idx(k) if i >= 0 and i+1 < len(av): av.pop(i) # skip k v = av.pop(i) return v i = idx_startswith(k) if i >= 0: v = av.pop(i) return v[ len(k): ] return dv def pop_v(k, dv=None): s = pop_str(k) if s == '': return dv return yaml.load(s) def pop(dv='', avoid_k='-'): for i in range( len(av) ): if avoid_k and av[i].startswith(avoid_k): continue return av.pop(i) return dv def is_pop(s): i = idx(s) if i < 0: return False av.pop(i) return True get_av = lambda : av return empty.new( locals() ) def cmd_new(name, args=[], opts={}, comment='', **kwds): return empty.new( name=name, args=args, opts=opts, comment=comment, **kwds ) def get_name_args(cmds, a=None): # cmds = [ # cmd_new( 'create' ), # cmd_new( 'commit' ), # cmd_new( 'log' ), # cmd_new( 'curr', comment='show current id' ), # cmd_new( 'ids', comment='show all id' ), # cmd_new( 'tails', comment='show tail ids' ), # cmd_new( 'checkout', [ 'id' ] ), # cmd_new( 'check', comment='show dirty' ), # cmd_new( 'fixlink', comment='fix link info' ), # cmd_new( 'push', [ 'to_path' ] ), # cmd_new( 'pull', [ 'from_path' ] ), # ] # # cmd = get_name_args( cmds ) # # obj has obj.create(), obj.commit() ... # # func = getattr( obj, cmd.name ) # func( *cmd.args ) dic = dict( map( lambda cmd: ( cmd.name, cmd ), cmds ) ) def get_help_str(cmd, max_n=0): def cnv(v): if v == '': return '""' if v is False: return '' return v def f(kv): (k, v) = kv lst = [ '[', '-' + k, str( cnv( v ) ), ']' ] return base.to_str( filter( lambda e: e, lst ), delim=' ' ) opts = list( map( f, cmd.opts.items() ) ) lst = [ cmd.name ] + opts + cmd.args s = base.to_str( lst, delim=' ' ) if max_n < 0: # auto max_n = len( s ) if max_n > 0 and cmd.comment: s += ' ' * ( max_n - len( s ) ) s += ' # ' + cmd.comment return s def help(): msg = 'cmd arg ...\n' max_n = max( map( lambda cmd: len( get_help_str( cmd ) ), cmds ) ) msg += base.to_str( map( lambda cmd: get_help_str( cmd, max_n ), cmds ), ' ' ) dbg.help_exit( msg ) if not a: a = new() name = a.pop() if name not in dic: help() cmd = dic.get( name ) def pop_key_v(key, dv): if dv is False: return a.is_pop( key ) return a.pop_v( key, dv ) opts = cmd.opts.copy() for (k, dv) in opts.items(): key = '-' + k # signel '-' v = pop_key_v( key, dv ) if v != dv: opts[ k ] = v n = len( cmd.args ) av = a.get_av() if len( av ) < n: help() args = list( map( lambda i: av.pop( 0 ), range( n ) ) ) s = get_help_str( cmd, -1 ) return cmd_new( cmd.name, args, opts, help=s, a=a ) # EOF