161 lines
3.8 KiB
Python
161 lines
3.8 KiB
Python
|
#!/usr/bin/python
|
||
|
|
||
|
import tokenize
|
||
|
import string
|
||
|
|
||
|
TABSONLY = 'TABSONLY'
|
||
|
SPACESONLY = 'SPACESONLY'
|
||
|
MIXED = 'MIXED'
|
||
|
|
||
|
class PyText:
|
||
|
def __init__(self, fnm, optdict):
|
||
|
self.optdict = optdict
|
||
|
self.fnm = fnm
|
||
|
self.txt = open(self.fnm, 'r').readlines()
|
||
|
self.indents = [(0, 0, )]
|
||
|
self.lnndx = 0
|
||
|
self.indentndx = 0
|
||
|
def getline(self):
|
||
|
if self.lnndx < len(self.txt):
|
||
|
txt = self.txt[self.lnndx]
|
||
|
self.lnndx = self.lnndx + 1
|
||
|
else:
|
||
|
txt = ''
|
||
|
return txt
|
||
|
def tokeneater(self, type, token, start, end, line):
|
||
|
if type == tokenize.INDENT:
|
||
|
(lvl, s) = self.indents[-1]
|
||
|
self.indents[-1] = (lvl, s, start[0]-1)
|
||
|
self.indents.append((lvl+1, start[0]-1,))
|
||
|
elif type == tokenize.DEDENT:
|
||
|
(lvl, s) = self.indents[-1]
|
||
|
self.indents[-1] = (lvl, s, start[0]-1)
|
||
|
self.indents.append((lvl-1, start[0]-1,))
|
||
|
elif type == tokenize.ENDMARKER:
|
||
|
(lvl, s) = self.indents[-1]
|
||
|
self.indents[-1] = (lvl, s, len(self.txt))
|
||
|
def split(self, ln):
|
||
|
content = string.lstrip(ln)
|
||
|
if not content:
|
||
|
return ('', '\n')
|
||
|
lead = ln[:len(ln) - len(content)]
|
||
|
lead = string.expandtabs(lead)
|
||
|
return (lead, content)
|
||
|
|
||
|
def process(self):
|
||
|
style = self.optdict.get('style', TABSONLY)
|
||
|
indent = string.atoi(self.optdict.get('indent', '4'))
|
||
|
tabsz = string.atoi(self.optdict.get('tabs', '8'))
|
||
|
print 'file %s -> style %s, tabsize %d, indent %d' % (self.fnm, style, tabsz, indent)
|
||
|
tokenize.tokenize(self.getline, self.tokeneater)
|
||
|
#import pprint
|
||
|
#pprint.pprint(self.indents)
|
||
|
new = []
|
||
|
for (lvl, s, e) in self.indents:
|
||
|
if s >= len(self.txt):
|
||
|
break
|
||
|
if s == e:
|
||
|
continue
|
||
|
oldlead, content = self.split(self.txt[s])
|
||
|
#print "oldlead", len(oldlead), `oldlead`
|
||
|
if style == TABSONLY:
|
||
|
newlead = '\t'*lvl
|
||
|
elif style == SPACESONLY:
|
||
|
newlead = ' '*(indent*lvl)
|
||
|
else:
|
||
|
sz = indent*lvl
|
||
|
t,spcs = divmod(sz, tabsz)
|
||
|
newlead = '\t'*t + ' '*spcs
|
||
|
new.append(newlead + content)
|
||
|
for ln in self.txt[s+1:e]:
|
||
|
lead, content = self.split(ln)
|
||
|
#print "lead:", len(lead)
|
||
|
new.append(newlead + lead[len(oldlead):] + content)
|
||
|
self.save(new)
|
||
|
#print "---", self.fnm
|
||
|
#for ln in new:
|
||
|
# print ln,
|
||
|
#print
|
||
|
|
||
|
def save(self, txt):
|
||
|
bakname = os.path.splitext(self.fnm)[0]+'.bak'
|
||
|
print "backing up", self.fnm, "to", bakname
|
||
|
#print os.getcwd()
|
||
|
try:
|
||
|
os.rename(self.fnm, bakname)
|
||
|
except os.error:
|
||
|
os.remove(bakname)
|
||
|
os.rename(self.fnm, bakname)
|
||
|
open(self.fnm, 'w').writelines(txt)
|
||
|
|
||
|
def test():
|
||
|
tc = PyText('test1.py')
|
||
|
tc.process()
|
||
|
tc = PyText('test1.py')
|
||
|
tc.process(style=TABSONLY)
|
||
|
tc = PyText('test1.py')
|
||
|
tc.process(style=MIXED, indent=4, tabs=8)
|
||
|
tc = PyText('test1.py')
|
||
|
tc.process(style=MIXED, indent=2, tabs=8)
|
||
|
|
||
|
def cleanfile(fnm, d):
|
||
|
if os.path.isdir(fnm) and not os.path.islink(fnm):
|
||
|
names = os.listdir(fnm)
|
||
|
for name in names:
|
||
|
fullnm = os.path.join(fnm, name)
|
||
|
if (os.path.isdir(fullnm) and not os.path.islink(fullnm)) or \
|
||
|
os.path.normcase(fullnm[-3:]) == ".py":
|
||
|
cleanfile(fullnm, d)
|
||
|
return
|
||
|
tc = PyText(fnm, d)
|
||
|
tc.process()
|
||
|
|
||
|
usage="""\
|
||
|
%s [options] [path...]
|
||
|
options
|
||
|
-T : reformat to TABS ONLY
|
||
|
-S : reformat to SPACES ONLY ( -i option is important)
|
||
|
-M : reformat to MIXED SPACES / TABS ( -t and -i options important)
|
||
|
-t<n> : tab is worth <n> characters
|
||
|
-i<n> : indents should be <n> characters
|
||
|
-h : print this text
|
||
|
path is file or directory
|
||
|
"""
|
||
|
if __name__ == '__main__':
|
||
|
import sys, getopt, os
|
||
|
opts, args = getopt.getopt(sys.argv[1:], "TSMht:i:")
|
||
|
d = {}
|
||
|
print `opts`
|
||
|
for opt in opts:
|
||
|
if opt[0] == '-T':
|
||
|
d['style'] = TABSONLY
|
||
|
elif opt[0] == '-S':
|
||
|
d['style'] = SPACESONLY
|
||
|
elif opt[0] == '-M':
|
||
|
d['style'] = MIXED
|
||
|
elif opt[0] == '-t':
|
||
|
d['tabs'] = opt[1]
|
||
|
elif opt[0] == '-i':
|
||
|
d['indent'] = opt[1]
|
||
|
elif opt[0] == '-h':
|
||
|
print usage % sys.argv[0]
|
||
|
sys.exit(0)
|
||
|
if not args:
|
||
|
print usage % sys.argv[0]
|
||
|
for arg in args:
|
||
|
cleanfile(arg, d)
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|