diff --git a/twander.py b/twander.py index 22fd5be..dc23d61 100755 --- a/twander.py +++ b/twander.py @@ -4,7 +4,7 @@ # For Updates See: http://www.tundraware.com/Software/twander PROGNAME = "twander" -RCSID = "$Id: twander.py,v 2.61 2003/01/16 17:26:03 tundra Exp $" +RCSID = "$Id: twander.py,v 2.62 2003/01/16 18:32:33 tundra Exp $" VERSION = RCSID.split()[2] @@ -724,82 +724,13 @@ cmdname = fields[1] cmd = " ".join(fields[2:]) - # Evaluate the command line, replacing - # variables as needed + # Process any User-Defined variables + cmd = ProcessVariables(cmd, num, line) - doeval = TRUE - depth = 0 + # A null return means there was a problem - abort + if not cmd: + return - while doeval: - - # Bound the number of times we can nest a definition - # to prevent self-references which give infinite nesting depth - - depth += 1 - if (depth > MAXNESTING): - doeval = FALSE - - # See if there are still unresolved variable references. - # If so, let the user know - - if REVAR.findall(cmd): - WrnMsg(wVBLTOODEEP % (num, cmd)) - return - - # Get a list of variable references - vbls = REVAR.findall(cmd) - - # Throw away references to Built-In Variables - these are - # processed at runtime and should be left alone here. - - # Note that we iterate over a *copy* of the variables - # list, because we may be changing that list contents - # as we go. i.e., It is bogus to iterate over a list - # which we are changing during the iteration. - - for x in vbls[:]: - - # Ignore references to Built-In Variables here - They are - # processed at runtime. - - if UI.BuiltIns.has_key(x): - vbls.remove(x) - - elif x.startswith(PROMPT): - vbls.remove(x) - - elif x.startswith(YESNO): - vbls.remove(x) - - if vbls: - for x in vbls: - vbl = x[1:-1] - - # Process ordinary variables - if UI.SymTable.has_key(vbl): - cmd = cmd.replace(x, UI.SymTable[vbl]) - - # Process environment variables. - # If an environment variable is referenced, - # but not defined, this is a fatal error - - elif vbl[0] == ENVVBL: - envvbl = os.getenv(vbl[1:]) - if envvbl: - cmd = cmd.replace(x, envvbl) - else: - WrnMsg(wBADENVVBL % (num, x, line)) - return - - # Process references to undefined variables - else: - WrnMsg(wUNDEFVBL % (num, x, line)) - return - - # No substitutions left to do - else: - doeval = FALSE - # Add the command entry to the command table. # Prevent duplicate keys from being entered. @@ -1659,7 +1590,7 @@ ##### -# Event Handler: Run Command +# Event Handler: Run Manually Entered Command #### def KeyRunCommand(event, initial=""): @@ -1679,7 +1610,7 @@ # Execute command (if any) - Blank entry means do nothing/return if cmd: - ExecuteCommand(cmd, pMANUALCMD) + ExecuteCommand(cmd, pMANUALCMD, ResolveVars=TRUE) # Save the command only if Command History is enabled (MAXHIST > 0) # AND one of two conditions exist: @@ -1825,19 +1756,33 @@ # Execute A Command ##### -def ExecuteCommand(cmd, name, UseStartDir=FALSE): +def ExecuteCommand(cmd, name, UseStartDir=FALSE, ResolveVars=FALSE): global UI - # Process any unresolved variables - newcmd = ProcessCommand(cmd, name) + # Process references to any Built-In variables + newcmd = ProcessBuiltIns(cmd, name) + + # Replace references to any Environment or User-Defined variables + # but only when asked to. - i.e., The command was manually + # entered by the user and may contain unresolved variables. + # (Commands the user defined in the configuration file + # already have their variables dereferenced when that file is + # read and parsed.) + + if ResolveVars: + newcmd = ProcessVariables(newcmd, 0 , name) + + # A null return value means there was a problem - abort + if not newcmd: + return # Just dump command if we're debugging if int(DEBUGLEVEL) & DEBUGCMDS: PrintDebug(dCMD, [newcmd,]) - # Otherwise,actually execute the command + # Otherwise,actually execute the command. elif newcmd: # Run the command on Win32 using filename associations @@ -2200,10 +2145,10 @@ ##### -# Process A Command Line Containing Unresolved Vatriables +# Process A Command Line Containing Unresolved Variables ##### -def ProcessCommand(cmd, name): +def ProcessBuiltIns(cmd, name): # First do any prompting required @@ -2250,11 +2195,95 @@ return cmd -# End of 'ProcessCommand()' +# End of 'ProcessBuiltIns()' ##### -# Refresh contents of directory listing to stay in sync with reality +# Process/Replace References To User-Defined & Environment Variables +##### + +def ProcessVariables(cmd, num, line): + + doeval = TRUE + depth = 0 + + while doeval: + + # Bound the number of times we can nest a definition + # to prevent self-references which give infinite nesting depth + + depth += 1 + if (depth > MAXNESTING): + doeval = FALSE + + # See if there are still unresolved variable references. + # If so, let the user know + + if REVAR.findall(cmd): + WrnMsg(wVBLTOODEEP % (num, cmd)) + return "" + + # Get a list of variable references + vbls = REVAR.findall(cmd) + + # Throw away references to Built-In Variables - these are + # processed at runtime and should be left alone here. + + # Note that we iterate over a *copy* of the variables + # list, because we may be changing that list contents + # as we go. i.e., It is bogus to iterate over a list + # which we are changing during the iteration. + + for x in vbls[:]: + + # Ignore references to Built-In Variables here - They are + # processed at runtime. + + if UI.BuiltIns.has_key(x): + vbls.remove(x) + + elif x.startswith(PROMPT): + vbls.remove(x) + + elif x.startswith(YESNO): + vbls.remove(x) + + if vbls: + for x in vbls: + vbl = x[1:-1] + + # Process ordinary variables + if UI.SymTable.has_key(vbl): + cmd = cmd.replace(x, UI.SymTable[vbl]) + + # Process environment variables. + # If an environment variable is referenced, + # but not defined, this is a fatal error + + elif vbl[0] == ENVVBL: + envvbl = os.getenv(vbl[1:]) + if envvbl: + cmd = cmd.replace(x, envvbl) + else: + WrnMsg(wBADENVVBL % (num, x, line)) + return "" + + # Process references to undefined variables + else: + WrnMsg(wUNDEFVBL % (num, x, line)) + return "" + + # No substitutions left to do + else: + doeval = FALSE + + return cmd + +# End of 'ProcessVariables()' + + +##### +# Refresh Contents Of Directory Listing To Stay In Sync With Reality ##### def RefreshDirList(*args):