diff --git a/twander.py b/twander.py index 68e51c3..2052341 100755 --- a/twander.py +++ b/twander.py @@ -4,7 +4,7 @@ PROGNAME = "twander" -RCSID = "$Id: twander.py,v 1.48 2002/11/13 23:17:16 tundra Exp $" +RCSID = "$Id: twander.py,v 1.49 2002/11/14 03:06:47 tundra Exp $" VERSION = RCSID.split()[2] @@ -25,6 +25,19 @@ # Defaults ##### +# Key Assignments + +GOHOME = '' +GOPREV = '' +GOSTART = '' +GOUP = '' +KEYPRESS = '' +QUITPROG = '' +SELECTKEY = '' +SELECTMOUSE = '' + + + # Configuration file CONF = os.path.join(os.getenv("HOME"), # Name of default config file @@ -60,12 +73,6 @@ #----------------------------------------------------------# -# Aliases & Redefinitions # -#----------------------------------------------------------# - - - -#----------------------------------------------------------# # Constants & Literals # #----------------------------------------------------------# @@ -125,12 +132,6 @@ ##### -# Informational Messages -##### - - - -##### # Usage Prompts ##### @@ -151,12 +152,6 @@ ] -##### -# Prompts -##### - - - #----------------------------------------------------------# # Global Variables & Data Structures # #----------------------------------------------------------# @@ -169,48 +164,10 @@ #----------------------------------------------------------# -# Object Base Class Definitions # +# General Support Functions # #----------------------------------------------------------# -#----------------------------------------------------------# -# Supporting Function Definitions # -#----------------------------------------------------------# - -##### -# Return Ordered List Of Directories & Files For Current Root -##### - -def BuildDirList(ROOTDIR): - - dList, fList = [], [] - - # Walk the directory separate subdirs and files - try: - for file in os.listdir(ROOTDIR): - if os.path.isdir(os.path.join(ROOTDIR,file)): - dList.append(DIR_LDELIM + file + DIR_RDELIM) - else: - fList.append(file) - except: - ErrMsg(eDIRRD % ROOTDIR) - - dList.sort() - - # Entry to move up one directory is always first, - # no matter what the sort. This is necessary because - # OSs like Win32 like to use '$' in file names which - # sorts before "." - - if ROOTDIR != os.path.abspath(PSEP): - dList.insert(0, DIR_LDELIM + ".." + DIR_RDELIM) - - fList.sort() - return dList + fList - -# End of 'BuildDirList()' - - ##### # Print An Error Message ##### @@ -222,56 +179,14 @@ ##### -# Get Directory Of Current ROOTDIR And Load Into UI +# Print A Warning Message ##### -def LoadDirList(newdir, save=TRUE): - global LASTDIR, ROOTDIR - - # Canonicalize the current directory name - newdir = os.path.abspath(newdir) +def WrnMsg(wmsg): + if WARN: + print PROGNAME + " " + VERSION + " " + wWARN + ": " + wmsg - # Push last directory visited onto the visited stack - # Do not do this if we've been told not to OR if - # what we're about to save is the same as the top - # of the stack - - # If there is anything on the stack, see if last element - # matches what we're about to put there. - - if LASTDIR: - if LASTDIR[-1] == ROOTDIR: - save = FALSE - if save: - LASTDIR.append(ROOTDIR) - - # And select new directory to visit - ROOTDIR = newdir - - # And make sure it ends with a path separator character - if ROOTDIR[-1] != PSEP: - ROOTDIR = ROOTDIR + PSEP - - # Update the widget - UpdateDirList() - -# End of 'LoadDirList(): - - -##### -# Update/Redraw Directory Listing -##### - -def UpdateDirList(): - - # Clear out the old contents - UI.DirList.delete(0,END) - - # Load new directory contents into UI - for x in BuildDirList(ROOTDIR): - UI.DirList.insert(END, x) - -# End of 'UpdateDirList()' +# End of 'WrnMsg()' ##### @@ -355,19 +270,132 @@ # End of 'Usage()' -##### -# Print A Warning Message -##### +#----------------------------------------------------------# +# GUI Classes, Handlers, & Support Functions # +#----------------------------------------------------------# -def WrnMsg(wmsg): - if WARN: - print PROGNAME + " " + VERSION + " " + wWARN + ": " + wmsg - -# End of 'WrnMsg()' ##### -# Process Current Selection +# Enacapsulate the UI in a class +##### + + +class twanderUI: + + def __init__(self, root): + + # Setup the visual elements + + self.hSB = Scrollbar(root, orient=HORIZONTAL) + self.vSB = Scrollbar(root, orient=VERTICAL) + self.DirList = Listbox(root, + foreground = FCOLOR, + background = BCOLOR, + font = (FNAME, FSZ, FWT), + selectmode=SINGLE, + exportselection=0, + xscrollcommand=self.hSB.set, + yscrollcommand=self.vSB.set, + height = HEIGHT, + width = WIDTH, + ) + + # Make them visible by packing + + self.hSB.config(command=self.DirList.xview) + self.hSB.pack(side=BOTTOM, fill=X) + self.vSB.config(command=self.DirList.yview) + self.vSB.pack(side=RIGHT, fill=Y) + self.DirList.pack(side=LEFT, fill=BOTH, expand=1) + + ##### + # Bind the relevant widget event handlers + ##### + + # We'll accept Single-Clicks as a selection + self.DirList.bind(SELECTMOUSE, DirListHandler) + + # Bind the relevant root window handlers + + # Bind handler for "Up Dir" + root.bind(GOUP, KeyUpDir) + + # Bind handler for "Quit Program" + root.bind(QUITPROG, KeyQuitProg) + + # Bind handler for "Goto Starting Dir" + root.bind(GOSTART, KeyStartDir) + + # Bind handler for "Previous Dir" + root.bind(GOPREV, KeyPrevDir) + + # Set up keystroke handler for application + # These will be checked against the command + # key definitions in the configuration file + root.bind(KEYPRESS, KeystrokeHandler) + + # Bind handler for "Item Select" + root.bind(SELECTKEY, DirListHandler) + + self.DirList.focus() + + # End if method 'twanderUI.__init__()' + + + ##### + # Support periodic polling to make sure widget stays + # in sync with reality of current directory. + ##### + + def poll(self): + + RefreshDirList() + self.DirList.after(1000, self.poll) + + # End of method 'twanderUI.poll()' + + + ##### + # Return name of currently selected item + ##### + + def CurrentSelection(self): + index = self.DirList.curselection() + if index: + return self.DirList.get(index) + else: + return "" + + # End of method 'twanderUI.CurrentSelection()' + + + ##### + # Update title bar with most current information + ##### + + def UpdateTitle(self, mainwin): + + # Get current selection + selected = self.CurrentSelection() + + # If there was a file selection append to title + if selected \ + and selected[0] == DIR_LDELIM \ + and selected[-1] == DIR_RDELIM: + + selected = "" + + # Update the titlebar + mainwin.title(PROGNAME + " " + VERSION + " " + ROOTDIR + selected) + + # End of method 'twanderUI.UpdateTitle()' + +# End of class definition, 'twanderUI' + + +##### +# Event Hander: Process Current Selection ##### def DirListHandler(event): @@ -419,134 +447,88 @@ else: pass - # Update the window title + # Have to update the window title because selection changed UI.UpdateTitle(UIroot) # End of 'DirListHandler()' -#----------------------------------------------------------# -# GUI Classes And Handlers # -#----------------------------------------------------------# +##### +# Get Directory Of Current ROOTDIR And Load Into UI +##### +def LoadDirList(newdir, save=TRUE): + global LASTDIR, ROOTDIR + + # Canonicalize the current directory name + newdir = os.path.abspath(newdir) + + # Push last directory visited onto the visited stack + # Do not do this if we've been told not to OR if + # what we're about to save is the same as the top + # of the stack + + # If there is anything on the stack, see if last element + # matches what we're about to put there. + + if LASTDIR: + if LASTDIR[-1] == ROOTDIR: + save = FALSE + if save: + LASTDIR.append(ROOTDIR) + + # And select new directory to visit + ROOTDIR = newdir + + # And make sure it ends with a path separator character + if ROOTDIR[-1] != PSEP: + ROOTDIR = ROOTDIR + PSEP + + # Clear out the old contents + UI.DirList.delete(0,END) + + # Load new directory contents into UI + for x in BuildDirList(ROOTDIR): + UI.DirList.insert(END, x) + + # And update the title to reflect changes + UI.UpdateTitle(UIroot) + +# End of 'LoadDirList(): ##### -# Enacapsulate the UI in a class +# Return Ordered List Of Directories & Files For Current Root ##### +def BuildDirList(ROOTDIR): -class twanderUI: + dList, fList = [], [] + + # Walk the directory separate subdirs and files + try: + for file in os.listdir(ROOTDIR): + if os.path.isdir(os.path.join(ROOTDIR,file)): + dList.append(DIR_LDELIM + file + DIR_RDELIM) + else: + fList.append(file) + except: + ErrMsg(eDIRRD % ROOTDIR) - def __init__(self, root): + dList.sort() - # Setup the visual elements + # Entry to move up one directory is always first, + # no matter what the sort. This is necessary because + # OSs like Win32 like to use '$' in file names which + # sorts before "." - self.hSB = Scrollbar(root, orient=HORIZONTAL) - self.vSB = Scrollbar(root, orient=VERTICAL) - self.DirList = Listbox(root, - foreground = FCOLOR, - background = BCOLOR, - font = (FNAME, FSZ, FWT), - selectmode=SINGLE, - exportselection=0, - xscrollcommand=self.hSB.set, - yscrollcommand=self.vSB.set, - height = HEIGHT, - width = WIDTH, - ) + if ROOTDIR != os.path.abspath(PSEP): + dList.insert(0, DIR_LDELIM + ".." + DIR_RDELIM) - # Make them visible by packing - - self.hSB.config(command=self.DirList.xview) - self.hSB.pack(side=BOTTOM, fill=X) - self.vSB.config(command=self.DirList.yview) - self.vSB.pack(side=RIGHT, fill=Y) - self.DirList.pack(side=LEFT, fill=BOTH, expand=1) + fList.sort() + return dList + fList - ##### - # Bind the relevant widget event handlers - ##### - - # We'll accept Single-Clicks as a selection - self.DirList.bind('', DirListHandler) - - # Bind the relevant root window handlers - - # Bind handler for "Up Dir" - root.bind('', KeyUpDir) - - # Bind handler for "Quit Program" - root.bind('', KeyQuitProg) - - # Bind handler for "Goto Starting Dir" - root.bind('', KeyStartDir) - - # Bind handler for "Previous Dir" - root.bind('', KeyPrevDir) - - # Set up keystroke handler for application - # These will be checked against the command - # key definitions in the configuration file - root.bind('', KeystrokeHandler) - - # Bind handler for "Item Select" - root.bind('', DirListHandler) - - # Bind handler for "Refresh Dir Listing" - root.bind('', RefreshDirList) - - self.DirList.focus() - - # End if method 'twanderUI.__init__()' - - - ##### - # Support periodic polling to make sure widget stays - # in sync with reality of current directory. - ##### - - def poll(self): - - RefreshDirList() - self.DirList.after(1000, self.poll) - - # End of method 'twanderUI.poll()' - - - ##### - # Return name of currently selected item - ##### - - def CurrentSelection(self): - index = self.DirList.curselection() - if index: - return self.DirList.get(index) - else: - return "" - - # End of method 'twanderUI.CurrentSelection()' - - - ##### - # Update title bar with most current information - ##### - - def UpdateTitle(self, mainwin): - - # Get current selection - selected = self.CurrentSelection() - - # Only append selection if it is a file - if selected[0] == DIR_LDELIM and selected[-1] == DIR_RDELIM: - selected = "" - - # Update the titlebar - mainwin.title(PROGNAME + " " + VERSION + " " + ROOTDIR + selected) - - # End of method 'twanderUI.UpdateTitle()' - -# End of class definition, 'twanderUI' +# End of 'BuildDirList()' ##### @@ -583,14 +565,16 @@ UI.DirList.see(number) UI.DirList.activate(active) - # Update the window title + # We have to update the title because the selection + # may have changed. + UI.UpdateTitle(UIroot) # End of 'RefreshDirList() ##### -# Event Handler For Backspace Key - Move up one directory +# Event Handler: Move up one directory ##### def KeyUpDir(event): @@ -600,12 +584,11 @@ if ROOTDIR != os.path.abspath(PSEP): LoadDirList(ROOTDIR + "..") - # End of 'KeyUpDir()' ##### -# Event Handler For Esc Key - Program Quit +# Event Handler: Program Quit ##### def KeyQuitProg(event): @@ -615,7 +598,7 @@ ##### -# Event Handler For Left Arrow Key - Move To Previous Directory +# Event Handler: Move To Previous Directory ##### def KeyPrevDir(event): @@ -634,7 +617,7 @@ ##### -# Event Handler For Home Key - Go Back to Initial Directory +# Event Handler: Go Back to Initial Directory ##### def KeyStartDir(event): @@ -646,7 +629,7 @@ ##### -# Event Handler For Individual Keystrokes +# Event Handler: Individual Keystrokes ##### def KeystrokeHandler(event):