Changed -i parsing logic to look for python-style indexes or slice ranges.
1 parent d9f04c4 commit 071a93b3c20d80e6accdc19db8e0f41a46247580
@tundra tundra authored on 25 Feb 2010
Showing 1 changed file
View
180
tren.py
 
PROGNAME = "tren.py"
BASENAME = PROGNAME.split(".py")[0]
PROGENV = BASENAME.upper()
RCSID = "$Id: tren.py,v 1.157 2010/02/25 20:04:39 tundra Exp $"
RCSID = "$Id: tren.py,v 1.158 2010/02/26 00:08:44 tundra Exp $"
VERSION = RCSID.split()[2]
 
# Copyright Information
 
#####
# Literals
#####
 
ARROW = "--->" # Used for formatting renaming messages
COMMENT = "#" # Comment character in include files
DEFLEN = 80 # Default output line length
DEFSEP = "=" # Default rename command separator: old=new
DEFSUFFIX = ".backup" # String used to rename existing targets
DEFESC = "\\" # Escape character
GLOBAL = 0 # Indicates we want global replacement
INCL = "I" # Include file command line option
INDENT = " " # Indent string for nested messages
ARROW = "--->" # Used for formatting renaming messages
COMMENT = "#" # Comment character in include files
DEFINST = 0 # Default replacement instance
DEFLEN = 80 # Default output line length
DEFSEP = "=" # Default rename command separator: old=new
DEFSUFFIX = ".backup" # String used to rename existing targets
DEFESC = "\\" # Escape character
INCL = "I" # Include file command line option
INDENT = " " # Indent string for nested messages
NULLESC = "Escape string" # Cannot be null
NULLRENSEP = "Old/New separator string" # Cannot be null
NULLSUFFIX = "Forced renaming suffix string" # Cannot be null
OPTINTRO = "-" # Option introducer
UPTO = "+" # "Replace up to ..." introducer
OPTINTRO = "-" # Option introducer
RANGESEP = ":" # Separator for instance ranges
SINGLEINST = "SINGLEINST" # Indicates a single, not range, replacement instance
 
# Internal program state literals
 
DEBUG = "DEBUG"
ESCAPE = "ESCAPE"
ERRORCONTINUE = "ERRORCONTINUE"
EXISTSUFFIX = "EXISTSUFFIX"
FORCERENAME = "FORCERENAME"
INSTANCESTART = "INSTANCESTART"
INSTANCEEND = "INSTANCEEND"
MAXLINELEN = "MAXLINELEN"
INSTANCE = "INSTANCE"
QUIET = "QUIET"
REGEX = "REGEX"
RENSEP = "RENSEP"
TESTMODE = "TESTMODE"
 
eARGLENGTH = "%s must contain exactly %s character(s)!"
eBADARG = "Invalid command line: %s!"
eBADINCL = "option -%s requires argument" % INCL
eBADINSTANCE = "%s is an invalid replacement instance!"
eBADINSTANCE = "%s is an invalid replacement instance! Must be integer values in the form: n, n:n, :n, n:, or :"
eBADLEN = "Bad line length '%s'!"
eBADNEWOLD = "Bad -r argument '%s'! Requires exactly one new, old string separator (Default: " + DEFSEP + ")"
eERROR = "ERROR"
eFILEOPEN = "Cannot open file '%s': %s!"
" -E Continue after an error is encountered (Default: False)",
" -f Force renaming even if target file or directory name already exists (Default: False)",
" -h Print help information (Default: False)",
" -I file Include command line arguments from file",
" -i num Specify which instance to replace (Default: %s, Global Replace)" % GLOBAL,
" -i num Specify which instance to replace (Default: %s)" % DEFINST,
" -P char Use 'char' as the escape sequence (Default: %s)" % DEFESC,
" -q Quiet mode, do not show progress (Default: False)",
" -R char Separator character for -r rename arguments (Default: %s)" % DEFSEP,
" -r old=new Replace old with new in file or directory names",
IncludedFiles = []
 
ProgramOptions = {
 
DEBUG : False, # Debugging off
CASESENSITIVE : True, # Search is case-sensitive
ESCAPE : DEFESC, # Escape string
ERRORCONTINUE : False, # Do not continue after error
EXISTSUFFIX : DEFSUFFIX, # What to tack on when renaming existing targets
FORCERENAME : False, # Do not rename if target already exists
MAXLINELEN : DEFLEN, # Width of output messages
QUIET : False, # Display progress
INSTANCE : GLOBAL, # Default to global replacement
REGEX : False, # Do not treat old string as a regex
RENSEP : DEFSEP, # Old, New string separator for -r
TESTMODE : False # Test mode off
DEBUG : False, # Debugging off
CASESENSITIVE : True, # Search is case-sensitive
ESCAPE : DEFESC, # Escape string
ERRORCONTINUE : False, # Do not continue after error
EXISTSUFFIX : DEFSUFFIX, # What to tack on when renaming existing targets
FORCERENAME : False, # Do not rename if target already exists
INSTANCESTART : DEFINST, # Replace first, leftmost instance by default
INSTANCEEND : SINGLEINST,
MAXLINELEN : DEFLEN, # Width of output messages
QUIET : False, # Display progress
REGEX : False, # Do not treat old string as a regex
RENSEP : DEFSEP, # Old, New string separator for -r
TESTMODE : False # Test mode off
}
 
 
#--------------------------- Code Begins Here ---------------------------------#
DEBUG : debug flag,
CASESENSITIVE : case sensitivity flag,
ERRORCONTINUE : error continuation flag,
FORCERENAME : force renaming flag,
INSTANCESTART : DReplace first, leftmost instance by default
INSTANCEEND :
MAXLINELEN : max output line length,
INSTANCE : what instance(s) should be replaced,
QUIET : quiet output flag,
REGEX : regular expression enable flag,
RENSEP : old/new rename separator string,
TESTMODE : testmode flag
if oldstrings:
# Only process leftmost occurence if global replace is off
 
if not renrequest[INSTANCE]:
if not renrequest[DEFINST]:
oldstrings = [oldstrings[0],]
 
# Replace selected substring(s).
# Substitute from R->L in original string
# Now process the options
 
for opt, val in opts:
 
# Select case-sensitivity for replacements (or not)
if opt == "-C":
ProgramOptions[CASESENSITIVE] = True
 
if opt == "-c":
ProgramOptions[CASESENSITIVE] = False
 
# Turn on debugging
 
if opt == "-d":
ProgramOptions[DEBUG] = True
DumpState()
 
 
# Force continuation through errors, if possible
 
if opt == "-E":
ProgramOptions[ERRORCONTINUE] = True
 
# Force renaming of existing targets
 
if opt == "-f":
ProgramOptions[FORCERENAME] = True
 
 
# Output usage information
 
if opt == "-h":
Usage()
sys.exit(0)
 
 
# Specify which instances to replace
 
if opt == "-i":
 
# Record the presence of an "Replace up to ..." introducer
 
prefix = val[0]
if prefix == UPTO:
val = val[1:]
 
else:
prefix = ""
# Parse the argument
try:
instance = int(val)
 
# Process ranges
 
if val.count(RANGESEP):
 
lhs, rhs = val.split(RANGESEP)
 
if not lhs:
lhs = None
 
else:
lhs = int(lhs)
if not rhs:
rhs = None
 
else:
rhs = int(rhs)
# Process single indexes
 
else:
 
lhs = int(val)
rhs = SINGLEINST
 
# Something about the argument was bogus
 
except:
ErrorMsg(eBADINSTANCE % val, EXIT=True)
 
ProgramOptions[INSTANCE] = (prefix, val)
ProgramOptions[INSTANCESTART] = lhs
ProgramOptions[INSTANCEEND] = rhs
 
# Set the escape character
 
if opt == "-P":
if len(val) == 1:
ProgramOptions[ESCAPE] = val
else:
ErrorMsg(eARGLENGTH % (NULLESC, 1), EXIT=True)
 
# Set quiet mode
if opt == "-q":
ProgramOptions[QUIET] = True
 
# Set the separator character for replacement specifications
 
if opt == '-R':
if len(val) == 1:
ProgramOptions[RENSEP] = val
else:
ErrorMsg(eARGLENGTH % (NULLRENSEP, 1), EXIT=True)
 
# Specify a replacement command
 
if opt == "-r":
req = {}
req[OLD], req[NEW] = GetOldNew(val)
for opt in ProgramOptions:
req[opt] = ProgramOptions[opt]
targs.RenRequests.append(req)
 
# Specify a renaming suffix
 
if opt == "-S":
if val:
ProgramOptions[EXISTSUFFIX] = val
else:
ErrorMsg(eNULLARG % NULLSUFFIX, EXIT=True)
 
# Request test mode
 
if opt == "-t":
ProgramOptions[TESTMODE] = True
 
 
# Output program version info
 
if opt == "-v":
PrintStdout(RCSID)
 
# Set output width
 
if opt == "-w":
try:
l = int(val)
if l < MINLEN:
ErrorMsg(eLINELEN, EXIT=True)
ProgramOptions[MAXLINELEN] = l
 
# Select whether 'old' replacement string is a regex or not
 
if opt == "-X":
ProgramOptions[REGEX] = False
 
if opt == "-x":