diff --git a/twander.py b/twander.py index d3a237f..ec1065f 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.48 2003/01/09 18:03:07 tundra Exp $" +RCSID = "$Id: twander.py,v 2.49 2003/01/10 19:26:08 tundra Exp $" VERSION = RCSID.split()[2] @@ -248,6 +248,15 @@ SHOWDRIVES = '\\\\' # Logical directory name for Win32 Drive Lists ##### +# GUI-Related Contsants +#### + +ROOTBORDER = 1 +MENUBORDER = 2 +MENUPADX = 2 +MENUOFFSET = ROOTBORDER + MENUBORDER + MENUPADX + +##### # Configuration File Related Literals ##### @@ -257,8 +266,17 @@ ENVVBL = r'$' # Symbol denoting an environment variable MAXNESTING = 32 # Maximum depth of nested variable definitions QUOTECHAR = '\"' # Character to use when quoting Built-In Variables -reVAR = r"\[.+?\]" # Regex describing variable notation +# Variable Name Pattern Matching Stuff + +DIRSC = "DIRSC" # Directory Shortcut naming +reDIRSC = r'^' + DIRSC + r'\d{1,2}$' # Regex describing Directory Shortcut names +reVAR = r"\[.+?\]" # Regex describing variable notation + +# Create actual regex matching engines + +REDIRSC = re.compile(reDIRSC) +REVAR = re.compile(reVAR) # Built-In Variables @@ -311,6 +329,7 @@ wCMDKEY = "Configuration File Entry For: \'%s\' Has No Command Key Defined." wCONFOPEN = "Cannot Open Configuration File:\n%s\n\n%s" +wDIRSCREDEF = "Directory Shortcut Defined More Than Once.\nIgnoring Line %s:\n\n%s" wLINKBACK = "%s Points Back To Own Directory" wNOCMDS = "Running With No Commands Defined!" wNOREBIND = "Cannot Rebind This Keyboard Or Mouse Button Combination.\nIgnoring Line %s:\n\n%s" @@ -336,6 +355,7 @@ dCMD = "" dCMDTBL = "" dDIRSTK = "" +dFUNCKEYS = "" dHEADER = "twander Debug Dump Run On: %s\n" dINTVAR = "" dKEYBINDS = "" @@ -441,6 +461,8 @@ # Cleanout any old configuration data UI.CmdTable = {} + UI.FuncKeys = ["", "", "", "", "", "", + "", "", "", "", "", ""] UI.SymTable = {} linenum = 0 @@ -526,16 +548,26 @@ else: WrnMsg(wNOCMDS) - # Dump tables if we're debugging + # Dump requested debug information if int(DEBUGLEVEL) & DEBUGKEYS: debuginfo = [] + + # Command keys for key in UI.KeyBindings.keys(): debuginfo.append(key + " " * (10-len(key)) + UI.KeyBindings[key]) - debuginfo.sort() PrintDebug(dKEYBINDS, debuginfo) + debuginfo = [] + + # Function Keys (Directory Shortcuts) + for x in range(len(UI.FuncKeys)): + key = "F" + str(x+1) + debuginfo.append(key + " " * (10-len(key)) + UI.FuncKeys[x]) + + PrintDebug(dFUNCKEYS, debuginfo) + if int(DEBUGLEVEL) & DEBUGSYMS: debuginfo = [] @@ -565,7 +597,6 @@ def ParseLine(line, num): global UI - revar = re.compile(reVAR) # Get rid of trailing newline, if any if line[-1] == '\n': @@ -619,6 +650,10 @@ # used in key binding, the statement is understood # to be a key rebinding, not a user variable definition. # + # If the LHS is one of the Directory Shortcut variables, + # the RHS is added to the Directory Menu and assigned + # to the associated Function Key (1-12). + # # Finally, the LHS cannot be one of the program # Built-In Variables - it is an error, for example, # to have something like: @@ -644,11 +679,42 @@ ErrMsg(eREDEFVAR % (name, num, line)) sys.exit(1) + # Handle Directory Shortcut entries. + + if REDIRSC.match(name): + + # Get shortcut number + sc = int(name.split(DIRSC)[1]) + + # Process if 1-12 + + if 0 < sc < 13: + + # Ignore attempts to redefine a shortcut within the config file + + if UI.FuncKeys[sc-1]: + WrnMsg(wDIRSCREDEF % (num, line)) + + # Everything OK - process the entry + else: + # Associate the directory with the correct function key + UI.FuncKeys[sc-1] = val + + # Add to Directory Menu making sure it is PSEP-terminated + + if val and (val[-1] != PSEP): + val += PSEP + + if val: + UpdateDirMenu(val) + + + # Process other variable types. # Distinguish between internal program variables and # user-defined variables and act accordingly. We inhibit # the rebinding of certain, special assignments, however. - if name in UI.KeyBindings.keys(): + elif name in UI.KeyBindings.keys(): if name in NOREBIND: WrnMsg(wNOREBIND % (num, line)) else: @@ -679,7 +745,7 @@ while doeval: # Get a list of variable references - vbls = revar.findall(cmd) + vbls = REVAR.findall(cmd) # Throw away references to Built-In Variables - these are # processed at runtime and should be left alone here. @@ -739,7 +805,7 @@ # See if there are still unresolved variable references. # If so, let the user know - if revar.findall(cmd): + if REVAR.findall(cmd): ErrMsg(eVBLTOODEEP % (num, cmd)) sys.exit(1) @@ -832,20 +898,20 @@ # Setup Menubar frame - self.mBar = Frame(root, relief=RAISED, borderwidth=2) + self.mBar = Frame(root, relief=RAISED, borderwidth=MENUBORDER) self.mBar.pack(fill=X) # Setup the Command Menu self.CmdBtn = Menubutton(self.mBar, text=COMMANDMENU, underline=0, state=DISABLED, font=(FNAME, FSZ, "bold")) self.CmdBtn.menu = Menu(self.CmdBtn, font=("courier", FSZ, "bold")) - self.CmdBtn.pack(side=LEFT, padx='2m') + self.CmdBtn.pack(side=LEFT, padx=MENUPADX) # Setup the Directory Menu self.DirBtn = Menubutton(self.mBar, text=DIRMENU, underline=0, font=(FNAME, FSZ, "bold")) self.DirBtn.menu = Menu(self.DirBtn, font=("courier", FSZ, "bold")) - self.DirBtn.pack(side=LEFT, padx='2m') + self.DirBtn.pack(side=LEFT, padx=MENUPADX) # Setup the Directory Listing and Scrollbars @@ -991,6 +1057,15 @@ self.DirList.bind(self.KeyBindings["MOUSESEL"], MouseDblClick) + ##### + # Function Keys + ##### + + # Bind function keys to a common handler + for x in range(len(self.FuncKeys)): + self.DirList.bind('' % (x+1), FuncKeypress) + + # Give the listbox focus so it gets keystrokes self.DirList.focus() @@ -1249,11 +1324,9 @@ y += UIroot.winfo_rooty() # So adjust accordingly # Display the Command Menu - - CommandMenu(event, x, y+h) + CommandMenu(event, x+MENUOFFSET, y+h) # Inhibit event from getting picked up by local accelerator key handlers - return "break" elif event.char == 'd': @@ -1268,10 +1341,9 @@ y += UIroot.winfo_rooty() # So adjust accordingly # Display the Command Menu - DirMenu(event, x, y+h) + DirMenu(event, x+MENUOFFSET, y+h) # Inhibit event from getting picked up by local accelerator key handlers - return "break" # We *only* want to handle simple single-character @@ -1646,7 +1718,7 @@ ##### -# Process Current Selection +# Event Handler: Process Current Selection ##### def DirListHandler(event): @@ -1728,6 +1800,26 @@ ##### +# Event Handler: Handler Function Keys +##### + +def FuncKeypress(event): + + index = int(event.keysym.split('F')[1]) - 1 + dir = UI.FuncKeys[index] + if dir: + LoadDirList(dir) + + # Inhibit other processing of this keystroke + return "break" + +# End of 'FuncKeypress()' + + +#-------------- Handler Utility Functions -----------------# + + +##### # Load UI With Selected Directory ##### @@ -1828,14 +1920,7 @@ os.chdir(newdir) # Keep list of all unique directories visited in the Directory Menu - - if newdir not in UI.AllDirs: - UI.AllDirs.append(newdir) - UI.AllDirs.sort() - UI.DirBtn.menu.delete(0,END) - for dir in UI.AllDirs: - UI.DirBtn.menu.add_command(label=dir, command=lambda dir=dir: LoadDirList(dir)) - UI.DirBtn['menu'] = UI.DirBtn.menu + UpdateDirMenu(newdir) # And always force selection of first item there. # This guarantees a selection in the new @@ -2055,9 +2140,6 @@ # End of 'BuildDirList()' -#-------------- Handler Utility Functions -----------------# - - ##### # Refresh contents of directory listing to stay in sync with reality ##### @@ -2102,7 +2184,7 @@ # End of 'RefreshDirList() -#---------------------- Menu Handlers ---------------------# +#---------------- Menu Support Functions ------------------# ##### # Handle Command Menu Selections @@ -2120,6 +2202,20 @@ # End Of 'CommandMenuSelection()' +def UpdateDirMenu(newdir): + global UI + + if newdir not in UI.AllDirs: + UI.AllDirs.append(newdir) + UI.AllDirs.sort() + UI.DirBtn.menu.delete(0,END) + for dir in UI.AllDirs: + UI.DirBtn.menu.add_command(label=dir, command=lambda dir=dir: LoadDirList(dir)) + UI.DirBtn['menu'] = UI.DirBtn.menu + +# End of 'UpdateDirMenu()' + + #----------------------------------------------------------# # Program Entry Point # #----------------------------------------------------------# @@ -2226,6 +2322,9 @@ # Prepare storage for key bindings UI.KeyBindings = {} +# Initialize list of all directories visited +UI.AllDirs = [] + # Parse the and store configuration file, if any ParseConfFile(None) @@ -2235,9 +2334,6 @@ # Initialize directory stack UI.LastDir = [] -# Initialize list of all directories visited -UI.AllDirs = [] - # And current location UI.CurrentDir = ""