Added logic for dumping test output.
Added InfoMsg().
Began implementing logic for forced renaming of existing targets.
Added -S option to override forced renaming suffix.
1 parent f753db0 commit c7eb70fe5194498e0fbdb17b3d37afde07f0df70
@tundra tundra authored on 5 Feb 2010
Showing 1 changed file
View
136
tren.py
 
PROGNAME = "tren.py"
BASENAME = PROGNAME.split(".py")[0]
PROGENV = BASENAME.upper()
RCSID = "$Id: tren.py,v 1.146 2010/02/05 19:20:25 tundra Exp $"
RCSID = "$Id: tren.py,v 1.147 2010/02/05 21:13:07 tundra Exp $"
VERSION = RCSID.split()[2]
 
# Copyright Information
 
# Literals
#####
 
ALL = "All" # Rename target is whole filename
ARROW = "--->" # Used for formatting renaming messages
COMMENT = "#" # Comment character in include files
DEFEXT = "." # Default name/extension separator
DEFLEN = 80 # Default output line length
DEFSEP = "=" # Default rename command separator: old=new
DEFSUFFIX = ".backup" # String used to rename existing targets
ESC = "\\" # Escape character
EXT = "Ext" # Rename target is extension
INCL = "I" # Include file command line option
NAM = "Nam" # Rename target is name
 
DEBUG = "DEBUG"
CASESENSITIVE = "CASESENSITIVE"
ERRORCONTINUE = "ERRORCONTINUE"
EXISTSUFFIX = "EXISTSUFFIX"
EXTDELIM = "EXTDELIM"
FORCERENAM = "FORCERENAM"
GLOBAL = "GLOBAL"
MAXLINELEN = "MAXLINELEN"
eTOOMANYINC = "Too many includes! (Max is %d) Possible circular reference?" % MAXINCLUDES
 
 
#####
# Warning Messages
#####
# Informational Messages
#####
 
iSKIPPING = "Skipping renaming of '%s' - Newname '%s' Exists!"
 
 
#####
# Usage Prompts
#####
 
uTable = [PROGVER,
HOMEPAGE,
"usage: " + PROGNAME + " [-abCcdEefGghqtvwXx] [-I file] [-l string] [-r old=new]... file|dir file|dir ...",
"usage: " + PROGNAME + " [-abCcdEefGghqtvwXx] [-I file] [-l string] [-r old=new]... [-S suffix] file|dir file|dir ...",
" where,",
" -a Rename within the entire file or directory name (Default)",
" -C Do case-sensitive renaming (Default)",
" -c Collapse case when doing string substitution.",
" -c Collapse case when doing string substitution",
" -d Dump debugging information",
" -e Only perform renaming within extension portion of or directory name.",
" -e Only perform renaming within extension portion of or directory name",
" -E Continue renaming even after an error is encountered",
" -f Force renaming even if target file or directory name already exists.",
" -f Force renaming even if target file or directory name already exists",
" -G Rename only the first instance of the specified string (Default)",
" -g Replace all instances (global rename) of the old string with the new.",
" -h Print help information.",
" -g Replace all instances (global rename) of the old string with the new",
" -h Print help information",
" -I file Include command line arguments from file",
" -l string File extension delimiter string. (Default: .)",
" -q Quiet mode, do not show progress.",
" -R rensep Separator string for -r rename arguments. (Default: =)",
" -r old=new Replace old with new in file or directory names.",
" -l string File extension delimiter string (Default: %s)" % DEFEXT,
" -q Quiet mode, do not show progress",
" -R rensep Separator string for -r rename arguments (Default: %s)" % DEFSEP,
" -r old=new Replace old with new in file or directory names",
" -S suffix Suffix to use when renaming existing filenames (Default: %s)" % DEFSUFFIX,
" -t Test mode, don't rename, just show what the program *would* do",
" -v Print detailed program version information and exit.",
" -w Line length of diagnostic and error output (Default: 75)",
" -v Print detailed program version information and exit",
" -w Line length of diagnostic and error output (Default: %s)" % DEFLEN,
" -X Treat the renaming strings literally (Default)",
" -x Treat the old replacement string as a Python regular expression",
]
 
 
DEBUG : False, # Debugging off
CASESENSITIVE : True, # Search is case-sensitive
ERRORCONTINUE : False, # Do not continue after error
EXISTSUFFIX : DEFSUFFIX, # What to tack on when renaming existing targets
EXTDELIM : DEFEXT, # Name/Extension delimiter
FORCERENAM : False, # Do not rename if target already exists
GLOBAL : False, # Only rename first instance of old string
MAXLINELEN : DEFLEN, # Width of output messages
# Now that we have a new name, attempt the actual renaming
# operation
 
RenamingError = False
newname = pathname + basename
 
# First make sure the new name meets length constraints
 
if len(basename) < MINNAMELEN:
if len(basename) > MAXNAMELEN:
ErrorMsg(eNAMELONG % (target, basename, MAXNAMELEN), EXIT=not ProgramOptions[ERRORCONTINUE])
RenamingError = True
if not RenamingError:
print ColumnPad([target, pathname + basename], padwidth = 50)
if (target != newname) and not RenamingError:
 
# Figure out if the newname already exists
 
newexists = False
if os.path.exists(newname):
newexists = True
# Just show what we would do
 
if ProgramOptions[TESTMODE]:
 
if newexists:
if ProgramOptions[FORCERENAM]:
 
renameexisting = newname + ProgramOptions[EXISTSUFFIX]
InfoMsg(ColumnPad([newname + " %s " % ARROW, renameexisting]), TESTMODE)
 
else:
 
InfoMsg(iSKIPPING % (target, newname), TESTMODE)
 
InfoMsg(ColumnPad([target + " %s " % ARROW, newname]), TESTMODE)
 
# Actually do the renaming
else:
 
print target + "---->"+ newname
 
# End of 'Rename()'
 
 
#####
# Turn A List Into Columns With Space Padding
#####
 
def ColumnPad(list, padchar=PADCHAR, padwidth=PADWIDTH):
def ColumnPad(list, PAD=PADCHAR, WIDTH=PADWIDTH):
 
retval = ""
for l in list:
l = str(l)
retval += l + ((padwidth - len(l)) * padchar)
retval += l + ((WIDTH - len(l)) * PAD)
 
return retval
 
# End of 'ColumnPad()'
# Condition Line Length With Fancy Wrap And Formatting
#####
 
def ConditionLine(msg,
padchar=PADCHAR, \
padwidth=PADWIDTH, \
PAD=PADCHAR, \
WIDTH=PADWIDTH, \
wrapindent=WRAPINDENT ):
 
retval = []
retval.append(msg[:ProgramOptions[MAXLINELEN]])
msg = msg[ProgramOptions[MAXLINELEN]:]
 
while msg:
msg = padchar * (padwidth + wrapindent) + msg
msg = PAD * (WIDTH + wrapindent) + msg
retval.append(msg[:ProgramOptions[MAXLINELEN]])
msg = msg[ProgramOptions[MAXLINELEN]:]
 
return retval
 
def DumpList(handler, msg, listname, content):
 
handler(msg)
itemarrow = ColumnPad([listname, " "], padwidth=LSTPAD)
itemarrow = ColumnPad([listname, " "], WIDTH=LSTPAD)
handler(ColumnPad([" ", " %s %s" % (itemarrow, content)]))
 
# End of 'DumpList()'
 
# End of 'GetOldNew()'
 
 
#####
# Print An Informational Message
#####
 
def InfoMsg(dmsg, msgtype):
 
l = ConditionLine(dmsg)
 
for dmsg in l:
PrintStdout(PROGNAME + " " + msgtype + ": " + dmsg)
 
# End of 'InfoMsg()'
 
 
#####
# Print To stderr
#####
 
def PrintStderr(msg, trailing="\n"):
sys.stderr.write(msg + trailing)
def PrintStderr(msg, TRAILING="\n"):
sys.stderr.write(msg + TRAILING)
 
# End of 'PrintStderr()'
 
 
#####
# Print To stdout
#####
 
def PrintStdout(msg, trailing="\n"):
sys.stdout.write(msg + trailing)
def PrintStdout(msg, TRAILING="\n"):
sys.stdout.write(msg + TRAILING)
 
# End of 'PrintStdout'
 
 
 
# And parse the command line
 
try:
opts, args = getopt.getopt(OPTIONS, 'abbCcdEefGghl:qR:r:tvw:Xx]')
opts, args = getopt.getopt(OPTIONS, 'abbCcdEefGghl:qR:r:S:tvw:Xx]')
except getopt.GetoptError as e:
ErrorMsg(eBADARG % e.args[0], EXIT=True)
 
# Create and populate an object with rename targets. This must be
req[OLD], req[NEW] = GetOldNew(val)
for opt in ProgramOptions:
req[opt] = ProgramOptions[opt]
targs.RenRequests.append(req)
 
if opt == "-S":
ProgramOptions[EXISTSUFFIX] = val
 
if opt == "-t":
ProgramOptions[TESTMODE] = True