diff --git a/twander.py b/twander.py index 01d2bf8..0dba1e4 100755 --- a/twander.py +++ b/twander.py @@ -6,7 +6,7 @@ # Program Information PROGNAME = "twander" -RCSID = "$Id: twander.py,v 3.128 2003/03/05 23:38:14 tundra Exp $" +RCSID = "$Id: twander.py,v 3.129 2003/03/10 19:36:02 tundra Exp $" VERSION = RCSID.split()[2] # Copyright Information @@ -678,23 +678,21 @@ # Warnings wBADCFGLINE = "Ignoring Line %s.\nBogus Configuration Entry:\n\n%s" -wBADIF = "Ignoring Line %s.\nImproperly Formed Condition: \n\n%s" wBADDEBUG = "Ignoring Bogus Debug Level! - %s Is Not In Integer Or Hex Format." wBADENDIF = "Ignoring Line %s!\nBogus End-Of-Block Statement:\n\n%s" wBADENVVBL = "Ignoring Line %s.\nEnvironment Variable %s Not Set:\n\n%s" wBADEXE = "Could Not Execute Command:\n\n%s" +wBADIF = "Ignoring Line %s.\nImproperly Formed Condition: \n\n%s" wBADRHS = "Ignoring Line %s.\nOption Assignment Has Bad Righthand Side:\n\n%s" wBADSCNUM = "Ignoring Line %s.\nShortcut Number Must Be From 1-12:\n\n%s" wBADSORTFLD = "Don't Know How To Sort By: %s\n\nWill Sort By %s Instead." wCONFOPEN = "Cannot Open Configuration File:\n%s" -wDIRSCREDEF = "Ignoring Line %s.\nDirectory Shortcut Defined More Than Once:\n\n%s" -wDUPKEY = "Ignoring Line %s.\nFound Duplicate Command Key '%s':\n\n%s" wEXTRAENDIF = "Ignoring Line %s!\nNo Conditional Block To End:\n\n%s" wLINKBACK = "%s Points Back To Own Directory" wMISSENDIF = "Configuration File Is Missing %s " + CONDENDIF +" Statement(s)" wNOCMDS = "Running With No Commands Defined!" wNOREBIND = "Ignoring Line %s.\nCannot Rebind This Keyboard Or Mouse Button Combination:\n\n%s" -wREDEFVAR = "Ignoring Line %s.\nCannot Redefine Variable %s:\n\n%s" +wREDEFVAR = "Ignoring Line %s.\nCannot Redefine Built-In Variable %s:\n\n%s" wUNDEFVBL = "Ignoring Line %s.\nUndefined Variable %s Referenced:\n\n%s" wVBLTOODEEP = "Ignoring Line %s.\nVariable Definition Nested Too Deeply:\n\n%s" wWARN = "WARNING" @@ -869,13 +867,13 @@ ##### -# Parse & Process The Configuraton File +# Process The Configuraton File # This is called once at program start time # and again any time someone hits the READCONF key # while the program is running. ##### -def ParseConfFile(event, DoOptionsProcessing=TRUE): +def ProcessConfiguration(event, DoOptionsProcessing=TRUE): global CONF, UI, ConditionalStack # Cleanout any old configuration data @@ -887,7 +885,6 @@ # Initialize internal parsing data structures - linenum = 0 ConditionalStack = [TRUE,] # This is a sentinel and guarantees there will # will always be something in this stack @@ -1009,23 +1006,9 @@ if not CONF: CONF = os.path.join(HOME, "." + PROGNAME) - try: - cf = open(CONF) - # Successful open of config file - Begin processing it - # Process and massage the configuration file - for line in cf.read().splitlines(): - linenum += 1 - - # Parse this line - if line: - ParseLine(line, linenum) - - # Close the config file - cf.close() - - except: - WrnMsg(wCONFOPEN % CONF) + # Actually read and parse the configuration file. + ReadConfFile(CONF) MissingEndIfs = len(ConditionalStack) - 1 @@ -1038,7 +1021,39 @@ return 'break' -# End of 'ParseConfFile()' +# End of 'ProcessConfiguration()' + + +##### +# Read & Parse A Configuration File +# Called By ProcessConfiguration() And Each Time +# A '.include' Is Encountered Within A Configuration File +##### + +def ReadConfFile(file): + + # Keep track of the line number on a per-file basis + + linenum = 0 + try: + cf = open(file) + # Successful open of config file - Begin processing it + + # Process and massage the configuration file + for line in cf.read().splitlines(): + linenum += 1 + + # Parse this line + if line: + ParseLine(line, file, linenum) + + # Close the config file + cf.close() + + except: + WrnMsg(wCONFOPEN % CONF) + +# End of 'ReadConfFile()' ##### @@ -1046,7 +1061,7 @@ ##### -def ParseLine(line, num): +def ParseLine(line, file, num): global UI, ConditionalStack ### @@ -1148,7 +1163,7 @@ # the rightmost argument cannot be an empty string if (len(args) != numargs) or (not CONDVAR.match(args[0].strip())) or (not args[-1]): - WrnMsg(wBADIF % (num, line)) + WrnMsg(wBADIF % (num, line), fn=file) return # Syntax OK, process the conditional test @@ -1213,14 +1228,14 @@ # The end-of-block statement must be on a line by itself if len(fields) != 1: - WrnMsg(wBADENDIF % (num,line)) + WrnMsg(wBADENDIF % (num, line), fn=file) # The conditional stack must always have 1 value left in # it *after* all conditional processing. If it does not, # it means there are more .endifs than .ifs. elif len(ConditionalStack) == 1: - WrnMsg(wEXTRAENDIF % (num,line)) + WrnMsg(wEXTRAENDIF % (num, line), fn=file) else: ConditionalStack.pop() @@ -1269,11 +1284,10 @@ name = cleanline[:assign].strip() val=cleanline[assign+1:].strip() - # Error out on variable redefinitions of either - # existing user-defined variables or built-ins + # Error out on any attempt to "define" a Built-In Variable if UI.BuiltIns.has_key('[' + name + ']') or UI.BuiltIns.has_key('[' + name): - WrnMsg(wREDEFVAR % (num, name, line)) + WrnMsg(wREDEFVAR % (num, name, line), fn=file) return # Handle Directory Shortcut entries. @@ -1284,31 +1298,22 @@ sc = int(name.split(DIRSC)[1]) # Process if in range - if 0 < sc < NUMFUNCKEY + 1: - # Ignore attempts to redefine a shortcut within the config file + # Associate the directory with the correct shortcut key + UI.DirSCKeys[sc-1] = val - if UI.DirSCKeys[sc-1]: - WrnMsg(wDIRSCREDEF % (num, line)) - return + # Add to Directory Menu making sure it is PSEP-terminated - # Everything OK - process the entry - else: - # Associate the directory with the correct shortcut key - UI.DirSCKeys[sc-1] = val + if val and (val[-1] != PSEP): + val += PSEP - # Add to Directory Menu making sure it is PSEP-terminated - - if val and (val[-1] != PSEP): - val += PSEP - - if val: - UpdateDirMenu(val) + if val: + UpdateDirMenu(val) # User specified an invalid shortcut number else: - WrnMsg(wBADSCNUM % (num, line)) + WrnMsg(wBADSCNUM % (num, line), fn=file) return # Process any wildcard definitions @@ -1326,7 +1331,7 @@ if val == 'TRUE' or val == 'FALSE': globals()[name] = eval(val) # !!! Cheater's way to get to global variables. else: - WrnMsg(wBADRHS % (num, line)) + WrnMsg(wBADRHS % (num, line), fn=file) return elif name in UI.OptionsNumeric.keys(): @@ -1336,9 +1341,10 @@ if val >= 0: globals()[name] = val else: - WrnMsg(wBADRHS % (num, line)) + WrnMsg(wBADRHS % (num, line), fn=file) + return except: - WrnMsg(wBADRHS % (num, line)) + WrnMsg(wBADRHS % (num, line), fn=file) return elif name in UI.OptionsString.keys(): @@ -1353,7 +1359,7 @@ elif name in UI.KeyBindings.keys(): if name in NOREBIND: - WrnMsg(wNOREBIND % (num, line)) + WrnMsg(wNOREBIND % (num, line), fn=file) return else: UI.KeyBindings[name] = val @@ -1368,7 +1374,7 @@ # Must have at least 3 fields for a valid command definition if len(fields) < 3: - WrnMsg(wBADCFGLINE % (num, line)) + WrnMsg(wBADCFGLINE % (num, line), fn=file) return else: cmdkey = fields[0] @@ -1383,18 +1389,15 @@ return # Add the command entry to the command table. - # Prevent duplicate keys from being entered. - - if UI.CmdTable.has_key(cmdkey): - WrnMsg(wDUPKEY % (num, cmdkey, line)) - return - else: - UI.CmdTable[cmdkey] = [cmdname, cmd] - UI.CmdBtn.menu.add_command(label=PadString(cmdname, CMDMENU_WIDTH) + "(" + cmdkey + ")", + # If the key is a duplicate, the older definition is + # overwritten. + + UI.CmdTable[cmdkey] = [cmdname, cmd] + UI.CmdBtn.menu.add_command(label=PadString(cmdname, CMDMENU_WIDTH) + "(" + cmdkey + ")", command=lambda cmd=cmdkey: CommandMenuSelection(cmd)) else: - WrnMsg(wBADCFGLINE % (num, line)) + WrnMsg(wBADCFGLINE % (num, line), fn=file) # End of 'ParseLine()' @@ -1625,9 +1628,9 @@ # Print A Warning Message ##### -def WrnMsg(wmsg): +def WrnMsg(wmsg, fn=""): if WARN: - showwarning(PROGNAME + " " + VERSION + " " + wWARN, wmsg) + showwarning("%s %s %s %s" % (PROGNAME, VERSION, wWARN, fn), wmsg) # End of 'WrnMsg()' @@ -1747,7 +1750,7 @@ self.DirList.bind(self.KeyBindings["QUITPROG"], KeyQuitProg) # Bind handler for "Read Config File" - self.DirList.bind(self.KeyBindings["READCONF"], ParseConfFile) + self.DirList.bind(self.KeyBindings["READCONF"], ProcessConfiguration) # Bind handler for "Refresh Screen" self.DirList.bind(self.KeyBindings["REFRESH"], RefreshDirList) @@ -4372,7 +4375,7 @@ # pickup any options changes from the environment # variable or command line. -ParseConfFile(None, DoOptionsProcessing=FALSE) +ProcessConfiguration(None, DoOptionsProcessing=FALSE) # Process the rest of the options, if any