1#! /usr/bin/env python
2
3# Emulate some Perl command line options.
4# Usage: pp [-a] [-c] [-d] [-e scriptline] [-F fieldsep] [-n] [-p] [file] ...
5# Where the options mean the following:
6#   -a            : together with -n or -p, splits each line into list F
7#   -c            : check syntax only, do not execute any code
8#   -d            : run the script under the debugger, pdb
9#   -e scriptline : gives one line of the Python script; may be repeated
10#   -F fieldsep   : sets the field separator for the -a option [not in Perl]
11#   -n            : runs the script for each line of input
12#   -p            : prints the line after the script has run
13# When no script lines have been passed, the first file argument
14# contains the script.  With -n or -p, the remaining arguments are
15# read as input to the script, line by line.  If a file is '-'
16# or missing, standard input is read.
17
18# XXX To do:
19# - add -i extension option (change files in place)
20# - make a single loop over the files and lines (changes effect of 'break')?
21# - add an option to specify the record separator
22# - except for -n/-p, run directly from the file if at all possible
23
24import sys
25import getopt
26
27FS = ''
28SCRIPT = []
29AFLAG = 0
30CFLAG = 0
31DFLAG = 0
32NFLAG = 0
33PFLAG = 0
34
35try:
36    optlist, ARGS = getopt.getopt(sys.argv[1:], 'acde:F:np')
37except getopt.error, msg:
38    sys.stderr.write('%s: %s\n' % (sys.argv[0], msg))
39    sys.exit(2)
40
41for option, optarg in optlist:
42    if option == '-a':
43        AFLAG = 1
44    elif option == '-c':
45        CFLAG = 1
46    elif option == '-d':
47        DFLAG = 1
48    elif option == '-e':
49        for line in optarg.split('\n'):
50            SCRIPT.append(line)
51    elif option == '-F':
52        FS = optarg
53    elif option == '-n':
54        NFLAG = 1
55        PFLAG = 0
56    elif option == '-p':
57        NFLAG = 1
58        PFLAG = 1
59    else:
60        print option, 'not recognized???'
61
62if not ARGS: ARGS.append('-')
63
64if not SCRIPT:
65    if ARGS[0] == '-':
66        fp = sys.stdin
67    else:
68        fp = open(ARGS[0], 'r')
69    while 1:
70        line = fp.readline()
71        if not line: break
72        SCRIPT.append(line[:-1])
73    del fp
74    del ARGS[0]
75    if not ARGS: ARGS.append('-')
76
77if CFLAG:
78    prologue = ['if 0:']
79    epilogue = []
80elif NFLAG:
81    # Note that it is on purpose that AFLAG and PFLAG are
82    # tested dynamically each time through the loop
83    prologue = [
84            'LINECOUNT = 0',
85            'for FILE in ARGS:',
86            '   \tif FILE == \'-\':',
87            '   \t   \tFP = sys.stdin',
88            '   \telse:',
89            '   \t   \tFP = open(FILE, \'r\')',
90            '   \tLINENO = 0',
91            '   \twhile 1:',
92            '   \t   \tLINE = FP.readline()',
93            '   \t   \tif not LINE: break',
94            '   \t   \tLINENO = LINENO + 1',
95            '   \t   \tLINECOUNT = LINECOUNT + 1',
96            '   \t   \tL = LINE[:-1]',
97            '   \t   \taflag = AFLAG',
98            '   \t   \tif aflag:',
99            '   \t   \t   \tif FS: F = L.split(FS)',
100            '   \t   \t   \telse: F = L.split()'
101            ]
102    epilogue = [
103            '   \t   \tif not PFLAG: continue',
104            '   \t   \tif aflag:',
105            '   \t   \t   \tif FS: print FS.join(F)',
106            '   \t   \t   \telse: print \' \'.join(F)',
107            '   \t   \telse: print L',
108            ]
109else:
110    prologue = ['if 1:']
111    epilogue = []
112
113# Note that we indent using tabs only, so that any indentation style
114# used in 'command' will come out right after re-indentation.
115
116program = '\n'.join(prologue) + '\n'
117for line in SCRIPT:
118    program += '   \t   \t' + line + '\n'
119program += '\n'.join(epilogue) + '\n'
120
121import tempfile
122fp = tempfile.NamedTemporaryFile()
123fp.write(program)
124fp.flush()
125if DFLAG:
126    import pdb
127    pdb.run('execfile(%r)' % (fp.name,))
128else:
129    execfile(fp.name)
130