#!/usr/bin/python

# tzcl.py
#       --copyright--                   Copyright 2010 (C) Tranzoa, Co. All rights reserved.    Warranty: You're free and on your own here. This code is not necessarily up-to-date or of public quality.
#       --url--                         http://www.tranzoa.net/tzpython/
#       --email--                       pycode is the name to send to. tranzoa.com is the place to send to.
#       --bodstamps--
#       October 30, 2010        bar
#       October 31, 2010        bar     comment
#       November 19, 2010       bar     include glob
#       April 20, 2011          bar     run from cmd line directly
#       April 24, 2011          bar     import time
#       May 19, 2011            bar     --help, etc.
#                                       fix refs to __name__ so that direct execution prints help nicely
#                                       add random to the imported modules
#       October 6, 2011         bar     version number
#       May 27, 2012            bar     doxygen namespace
#       February 13, 2013       bar     comment change
#       --eodstamps--
##      \file
#       \namespace              tzpython.tzcl
#
#       TODO:
#           use import tokenize to split up semi-colon'd lines and to handle the dots at the left end of the lines
#           or anyway, find some way to not get fooled by ;.... inside quoted strings
#
#

__doc__     = """
This module makes command line Python easier.

Eample command line operations:
    %s.py                       "print 'Hello world'"
    python  %s.py               "print 'Hello world'"
    python  -c  "import %s"     "print 'Hello world'"
    %s.py                    -l "print line_index, line"    <some_file
    %s.py                    -p "sub(r'\s+', '', line)"     <some_file
    %s.py                    -I "directory with local python code"  "print >>stderr, 'I am [%%s] at [%%s]' %% ( path.basename(__file__), path.dirname(__file__) );   print 'more'"

Command line code context:
    The Python code you put in the command line arguments
        is run with platform, shutil, sys, os, re, random, and glob "from [os|re|...] import *".

    open(), and exit(), are kept as their respective builtins.
    The built-in compile() is remembered as bicompile() while
        compile() is re.compile().
    os.open() and sys.exit() can be called directly.

Options:

    -I
    --inc
    --include           Put the next argument (a directory, presumably) on the end of the sys.path list.

    -l
    --loop
    -i
    --il
    --input_loop
    --input-loop
    --inputloop         The following argument is exec()'d for each input line from sys.stdin.readline().

    -p
    --print             Do --loop with the code wrapped in a print().

The following local variables are passed to your code:
    line_index      0...
    li              0...
    line_number     1...
    line            The input line rstrip()'d - without trailing whitespace (e.g. LF).
    l               Same as line.
    i               Don't use. Same as line (though, really, it should be line_index?).
    rline           The input line straight from sys.stdin.readline().
    rl              Same as rline.

These local variables are passed to your code even outside a --loop option,
    but line_index is always 0, line is always "", and rline is always "\\n".

The __code__ variable is set to the code being exec()'d.
    Note: Each command line argument is exec()'d separately.

__doc__ is set to the %s.py __doc__ help string.

Local variables persist from command line argument to argument.

"""


TZCL_VERSION    = 1

import      os

TZCL_NAME   = ((__name__ == '__main__') and os.path.splitext(os.path.basename(__file__))[0]) or __name__
__doc__     = __doc__ % ( TZCL_NAME, TZCL_NAME, TZCL_NAME, TZCL_NAME, TZCL_NAME, TZCL_NAME, TZCL_NAME, )


if  True :
    try             :
        biopen      =   __builtins__['open']
        biexit      =   __builtins__['exit']
        bicompile   =   __builtins__['compile']
    except TypeError :
        if  __name__ != '__main__' :
            import  sys
            print >>sys.stderr, __doc__
            sys.exit(255)
        biopen      =   open
        biexit      =   exit
        bicompile   =   compile

    from        platform    import  *
    from        shutil      import  *
    from        sys         import  *
    from        os          import  *
    from        re          import  *
    from        random      import  *
    from        glob        import  *
    open        =   biopen
    exit        =   biexit
    # compile   =   bicompile
    import      os.path
    import      platform, shutil, sys, re, random, glob
    import      time


if  False :
                #
                #                   Help find name collisions.
                #
                def built_in(m, d) :
                    for n in dir(m) :
                        if  n not in [ '__doc__', '__name__', '__package__', 'copyright', 'exit', 'compile', 'open', ] :
                            if  n in __builtins__ :
                                print ">>>>>builtin " + m.__name__ + "[" + n + "]"
                            if  n in d :
                                print ">>>>>module  " + m.__name__ + "[" + n + "]"
                            pass
                        pass
                    d  += dir(m)


                g   = dict(globals())
                for n in g.keys() :
                    if  n in __builtins__ :
                        if  n not in [ '__doc__', '__name__', '__package__', 'copyright', 'exit', 'compile', 'open', ] :
                            print ">>>>>[" + n + "]"
                        pass
                    pass

                modules = [
                            platform,
                            shutil,
                            sys,
                            os,
                            re,
                          ]
                d       = []
                for m in modules :
                    built_in(m, d)
                pass


def _exec(sc, ln, rline, locals) :
    """ Run the command line argument code. """

    line        = rline.rstrip()
    if  not rline :
        rline   = "\n"
    locals.update({
                    'line_index'    :   ln,
                    'li'            :   ln,
                    'line_number'   :   ln + 1,
                    'ln'            :   ln + 1,
                    'rline'         :   rline,
                    'rl'            :   rline,
                    'line'          :   line,
                    'l'             :   line,
                    'i'             :   line,
                    '__code__'      :   sc,
                  }
                 )
    exec sc in globals(), locals

    return(locals)


def main() :
    """ Go through the command line arguments and handle our options and run the code in the arguments. """

    if  sys.argv :                                      # in case we're imported by someone other than the command line, we'll just silently allow it and do nothing.
        if  (sys.argv[0] == "-c") or (sys.argv[0] == __file__) :
            if  len(sys.argv ) <= 1 :
                print >>sys.stderr, "Put the script in the argument just after the -c 'import %s'" % TZCL_NAME
                sys.exit(101)

            ignore      = False
            loop        = ""
            locals      = {}
            for ai, arg in enumerate(sys.argv[1:]) :
                if  ignore or (not arg) :
                    ignore  = False
                elif  arg in [ '-h', '--help', '-?', '--?', '/H', '/h', '/?', ] :
                    print __doc__
                    sys.exit(254)
                elif  arg in [ '-I', '--inc', '--include', ] :
                    sys.path.append(sys.argv[ai + 2])
                    ignore  = True
                elif  arg in [ '--loop', '--input_loop', '--inputloop', '--input-loop', '--il', '-l', '-i', ] :
                    loop    = 'l'
                elif  arg in [ '--print', '-p', ] :
                    loop    = 'p'
                else        :
                    lns     = re.split(r"\s*(?:\n|\\n)", arg)


                    if  True :
                        def _dotter(g)  :
                                return(' ' * len(g.group(1)))

                        def _sdotter(g) :
                                return(';' + (' ' * len(g.group(1))))

                        lns = [ re.sub(r";(\.+)", _sdotter, dln) for dln in [ re.sub(r"^(\.+)", _dotter, ln) for ln in lns ] ]


                    sc      = "\n".join(lns) + "\n"

                    if  not loop  :
                         locals = _exec(sc, 0, "", locals)
                    else :
                        lpo     = ""
                        lpc     = ""
                        if      loop == 'p':
                            lpo = "print ("
                            lpc = ")"

                        loop    = ""
                        ln      = 0
                        while True :
                            l   = sys.stdin.readline()
                            if  not l :
                                break
                            locals  = _exec(lpo + sc + lpc, ln, l, locals)
                            ln += 1
                        pass
                    pass
                pass
            pass
        pass
    pass

main()


#
#
#
# eof
