diff --git a/tren.py b/tren.py index bf5f703..aa12afb 100755 --- a/tren.py +++ b/tren.py @@ -8,7 +8,7 @@ PROGNAME = "tren.py" BASENAME = PROGNAME.split(".py")[0] PROGENV = BASENAME.upper() -RCSID = "$Id: tren.py,v 1.156 2010/02/24 00:00:35 tundra Exp $" +RCSID = "$Id: tren.py,v 1.157 2010/02/25 20:04:39 tundra Exp $" VERSION = RCSID.split()[2] # Copyright Information @@ -88,12 +88,14 @@ 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 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 # Internal program state literals @@ -103,8 +105,8 @@ ERRORCONTINUE = "ERRORCONTINUE" EXISTSUFFIX = "EXISTSUFFIX" FORCERENAME = "FORCERENAME" -GLOBAL = "GLOBAL" MAXLINELEN = "MAXLINELEN" +INSTANCE = "INSTANCE" QUIET = "QUIET" REGEX = "REGEX" RENSEP = "RENSEP" @@ -165,8 +167,9 @@ eARGLENGTH = "%s must contain exactly %s character(s)!" eBADARG = "Invalid command line: %s!" eBADINCL = "option -%s requires argument" % INCL -eBADNEWOLD = "Bad -r argument '%s'! Requires exactly one new, old string separator (Default: " + DEFSEP + ")" +eBADINSTANCE = "%s is an invalid replacement instance!" 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!" eLINELEN = "Specified line length too short! Must be at least %s" % MINLEN @@ -191,17 +194,16 @@ uTable = [PROGVER, HOMEPAGE, - "usage: " + PROGNAME + " [-CcdEfGghqtvwXx] [-I file] [-r old=new]... [-S suffix] file|dir file|dir ...", + "usage: " + PROGNAME + " [[-CcdEfhqtvwXx] [-I file] [-i instance] [-P escape] [ -R separator] [-S suffix] [-r old=new]] ... file|dir file|dir ...", " where,", " -C Do case-sensitive renaming (Default)", " -c Collapse case when doing string substitution (Default: False)", " -d Dump debugging information (Default: False)", " -E Continue after an error is encountered (Default: False)", " -f Force renaming even if target file or directory name already exists (Default: False)", - " -G Rename only the first instance of the specified string (Default)", - " -g Replace all instances (global rename) of the old string with the new (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, " -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, @@ -230,12 +232,12 @@ 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 - GLOBAL : False, # Only rename first instance of old string 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 # Global data structures + TESTMODE : False # Test mode off } @@ -285,8 +287,8 @@ CASESENSITIVE : case sensitivity flag, ERRORCONTINUE : error continuation flag, FORCERENAME : force renaming flag, - GLOBAL : global replace flag, 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, @@ -481,7 +483,7 @@ # Only process leftmost occurence if global replace is off - if not renrequest[GLOBAL]: + if not renrequest[INSTANCE]: oldstrings = [oldstrings[0],] # Replace selected substring(s). @@ -938,7 +940,7 @@ # And parse the command line try: - opts, args = getopt.getopt(OPTIONS, 'CcdEfGghP:qR:r:S:tvw:Xx]') + opts, args = getopt.getopt(OPTIONS, 'CcdEfhi:P:qR:r:S:tvw:Xx]') except getopt.GetoptError as e: ErrorMsg(eBADARG % e.args[0], EXIT=True) @@ -970,16 +972,28 @@ if opt == "-f": ProgramOptions[FORCERENAME] = True - if opt == "-G": - ProgramOptions[GLOBAL] = False - - if opt == "-g": - ProgramOptions[GLOBAL] = True - if opt == "-h": Usage() sys.exit(0) + if opt == "-i": + + # Record the presence of an "Replace up to ..." introducer + + prefix = val[0] + if prefix == UPTO: + val = val[1:] + + else: + prefix = "" + + try: + instance = int(val) + except: + ErrorMsg(eBADINSTANCE % val, EXIT=True) + + ProgramOptions[INSTANCE] = (prefix, val) + if opt == "-P": if len(val) == 1: ProgramOptions[ESCAPE] = val