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 
24 import sys
25 import getopt
26 
27 FS = ''
28 SCRIPT = []
29 AFLAG = 0
30 CFLAG = 0
31 DFLAG = 0
32 NFLAG = 0
33 PFLAG = 0
34 
35 try:
36     optlist, ARGS = getopt.getopt(sys.argv[1:], 'acde:F:np')
37 except getopt.error, msg:
38     sys.stderr.write('%s: %s\n' % (sys.argv[0], msg))
39     sys.exit(2)
40 
41 for 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 
62 if not ARGS: ARGS.append('-')
63 
64 if 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 
77 if CFLAG:
78     prologue = ['if 0:']
79     epilogue = []
80 elif 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             ]
109 else:
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 
116 program = '\n'.join(prologue) + '\n'
117 for line in SCRIPT:
118     program += '   \t   \t' + line + '\n'
119 program += '\n'.join(epilogue) + '\n'
120 
121 import tempfile
122 fp = tempfile.NamedTemporaryFile()
123 fp.write(program)
124 fp.flush()
125 if DFLAG:
126     import pdb
127     pdb.run('execfile(%r)' % (fp.name,))
128 else:
129     execfile(fp.name)
130