diff --git a/twander.py b/twander.py index 9002441..e15ed58 100755 --- a/twander.py +++ b/twander.py @@ -6,7 +6,7 @@ # Program Information PROGNAME = "twander" -RCSID = "$Id: twander.py,v 3.189 2005/02/01 23:09:01 tundra Exp $" +RCSID = "$Id: twander.py,v 3.190 2005/02/02 09:13:09 tundra Exp $" VERSION = RCSID.split()[2] # Copyright Information @@ -193,11 +193,11 @@ # Wildcard Features -MOUSEFILTER = '' # Pop-up Filter Wildcard Menu -MOUSEWILD = '' # Pop-up Selection Wildcard Menu -FILTERWILD = '' # Filter file list with wildcard -SELWILD = '' # Select using wildcards -TOGFILT = '' # Invert the filter wildcard logic +MOUSEFILTER = '' # Pop-up Filter Wildcard Menu +MOUSEWILDSEL = '' # Pop-up Selection Wildcard Menu +FILTERWILD = '' # Filter file list with wildcard +SELWILD = '' # Select using wildcards +TOGFILT = '' # Invert the filter wildcard logic ##### @@ -486,7 +486,7 @@ # Name The Key/Mouse Assignments Which We Do Not Allow To Be Rebound In The Config File -NOREBIND = ["MOUSECTX", "MOUSEDIR", "MOUSEHIST", "MOUSESC", "MOUSESORT", "MOUSEFILTER", "MOUSEWILD", "MOUSEBACK","MOUSEUP", "MOUSESEL"] +NOREBIND = ["MOUSECTX", "MOUSEDIR", "MOUSEHIST", "MOUSESC", "MOUSESORT", "MOUSEFILTER", "MOUSEWILDSEL", "MOUSEBACK","MOUSEUP", "MOUSESEL"] ##### @@ -700,7 +700,8 @@ HISTMENU = 'History' # Title for History Menu button SCMENU = 'Shortcuts' # Title for Shortcut Menu button SORTMENU = 'Sorting' # Title for Sort Menu button -WILDMENU = 'Wildcards' # Title for Wildcard Menu button +FILTERMENU = 'Filter' # Title for Wildcard Filter Menu button +SELECTMENU = 'Select' # Title for Wildcard Selection Menu button HELPMENU = 'Help' # Title for Help Menu button # Sort Menu-Related @@ -824,7 +825,9 @@ dOPTVAR = hOPTVBLS dSYMTBL = hUSERVBLS dTRUE = "True" -dWILDSTK = "WILDCARD STACK" +dFILTER = "FILTER" +dSELECT = "SELECT" +dWILDLST = "%s WILDCARDS" # Debug Formatting @@ -860,7 +863,7 @@ " 5 - Dump Directory Stack As It Changes (0x020)", " 6 - Dump Command History Stack After Command Executes (0x040)", " 7 - Dump Contents Of Program Memories As They Change (0x080)", - " 8 - Dump Contents Of Wildcard Stack As It Changes (0x100)", + " 8 - Dump Contents Of Filter/Selection Wildcard Lists As They Change (0x100)", " 9 - Reserved", " 10 - Reserved", " 11 - Dump Requested Debug Information And Exit Immediately (0x800)", @@ -1192,7 +1195,7 @@ "SORTREV":SORTREV, "SORTSEP":SORTSEP, "MOUSEFILTER":MOUSEFILTER, - "MOUSEWILD":MOUSEWILD, + "MOUSEWILDSEL":MOUSEWILDSEL, "FILTERWILD":FILTERWILD, "SELWILD":SELWILD, "TOGFILT":TOGFILT, @@ -1604,8 +1607,8 @@ # Process any wildcard definitions elif name == WILDCARD: - if val and (val not in UI.WildHist): - UpdateMenu(UI.WildBtn, UI.WildHist, MAXMENU, MAXMENUBUF, KeySelWild, newentry=val, fakeevent=True) + if val and (val not in UI.SelectHist): + UpdateMenu(UI.SelectBtn, UI.SelectHist, MAXMENU, MAXMENUBUF, KeySelWild, newentry=val, fakeevent=True) # Process any option variables - blank RHS is OK and means to leave # option set to its default value. @@ -1724,7 +1727,7 @@ # Any user-set options have now been read, set the GUI - for i in (UI.CmdBtn, UI.DirBtn, UI.HistBtn, UI.ShortBtn, UI.SortBtn, UI.WildBtn, UI.HelpBtn): + for i in (UI.CmdBtn, UI.DirBtn, UI.HistBtn, UI.ShortBtn, UI.SortBtn, UI.FilterBtn, UI.SelectBtn, UI.HelpBtn): i.config(foreground=MFCOLOR, background=MBCOLOR, font=(MFNAME, MFSZ, MFWT)) i.menu.config(foreground=MFCOLOR, background=MBCOLOR, font=(MFNAME, MFSZ, MFWT)) @@ -1739,7 +1742,8 @@ UpdateMenu(UI.DirBtn, UI.AllDirs, MAXMENU, MAXMENUBUF, LoadDirList, sort=True) UpdateMenu(UI.HistBtn, UI.CmdHist, MAXMENU, MAXMENUBUF, KeyRunCommand, fakeevent=True) - UpdateMenu(UI.WildBtn, UI.WildHist, MAXMENU, MAXMENUBUF, KeySelWild, fakeevent=True) + UpdateMenu(UI.FilterBtn, UI.FilterHist, MAXMENU, MAXMENUBUF, KeyFiltWild, fakeevent=True) + UpdateMenu(UI.SelectBtn, UI.SelectHist, MAXMENU, MAXMENUBUF, KeySelWild, fakeevent=True) # Initialize the Sorting Menu @@ -2010,11 +2014,17 @@ self.SortBtn.menu = Menu(self.SortBtn) self.SortBtn.pack(side=LEFT, padx=MENUPADX) - # Setup the Wildcard Menu + # Setup the Filter Wildcard Menu - self.WildBtn = Menubutton(self.mBar, text=WILDMENU, underline=0, state=DISABLED) - self.WildBtn.menu = Menu(self.WildBtn) - self.WildBtn.pack(side=LEFT, padx=MENUPADX) + self.FilterBtn = Menubutton(self.mBar, text=FILTERMENU, underline=0, state=DISABLED) + self.FilterBtn.menu = Menu(self.FilterBtn) + self.FilterBtn.pack(side=LEFT, padx=MENUPADX) + + # Setup the Selection Wildcard Menu + + self.SelectBtn = Menubutton(self.mBar, text=SELECTMENU, underline=5, state=DISABLED) + self.SelectBtn.menu = Menu(self.SelectBtn) + self.SelectBtn.pack(side=LEFT, padx=MENUPADX) # Setup the Help Menu @@ -2267,10 +2277,10 @@ self.DirList.bind(self.KeyBindings["MOUSEFILTER"], MouseClick) # Bind handler to invoke Selection Wildcard Menu - self.DirList.bind(self.KeyBindings["MOUSEWILD"], MouseClick) + self.DirList.bind(self.KeyBindings["MOUSEWILDSEL"], MouseClick) # Bind handler for "Filter With Wildcard" - self.DirList.bind(self.KeyBindings["FILTERWILD"], lambda event : KeySelWild(event, FilterWildcard=True)) + self.DirList.bind(self.KeyBindings["FILTERWILD"], KeyFiltWild) # Bind handler for "Select With Wildcard" self.DirList.bind(self.KeyBindings["SELWILD"], KeySelWild) @@ -2498,15 +2508,15 @@ elif event.state == (Button3Mask | AltMask | ShiftMask): # Alt-Shift-Button-3 x, y = UI.DirList.winfo_pointerxy() # Position near mouse - PopupMenu(UI.SortBtn.menu, x, y) # Display Sort Menu - - elif event.state == (Button3Mask | AltMask | ControlMask): # Alt-Control-Button-3 - x, y = UI.DirList.winfo_pointerxy() # Position near mouse - PopupMenu(UI.WildBtn.menu, x, y) # Display Selection Wildcard Menu + PopupMenu(UI.SortBtn.menu, x, y) # Display Sort Menu elif event.state == (Button2Mask | AltMask | ControlMask): # Alt-Control-Button-2 x, y = UI.DirList.winfo_pointerxy() # Position near mouse - PopupMenu(UI.WildBtn.menu, x, y) # Display Filter Wildcard Menu + PopupMenu(UI.FilterBtn.menu, x, y) # Display Filter Wildcard Menu + + elif event.state == (Button3Mask | AltMask | ControlMask): # Alt-Control-Button-3 + x, y = UI.DirList.winfo_pointerxy() # Position near mouse + PopupMenu(UI.SelectBtn.menu, x, y) # Display Selection Wildcard Menu # End Of 'MouseClick()' @@ -2542,15 +2552,17 @@ def ClearHistory(event): global UI - UI.AllDirs = [] - UI.CmdHist = [] - UI.WildHist = [] - UI.LastCmd = "" - UI.LastDir = [] - UI.LastPathEntered = "" - UI.LastSelWildcard = "" + UI.AllDirs = [] + UI.CmdHist = [] + UI.FilterHist = [] + UI.SelectHist = [] + UI.LastCmd = "" + UI.LastDir = [] + UI.LastPathEntered = "" + UI.LastFiltWildcard = "" + UI.LastSelWildcard = "" - for x in [UI.DirBtn, UI.HistBtn, UI.WildBtn]: + for x in [UI.DirBtn, UI.HistBtn, UI.FilterBtn, UI.SelectBtn]: x.menu.delete(0,END) x['menu'] = x.menu x.config(state=DISABLED) @@ -2630,9 +2642,13 @@ elif event.char == 's': button = UI.SortBtn - # Wildcard Menu - elif event.char == 'w': - button = UI.WildBtn + # Filter Menu + elif event.char == 'f': + button = UI.FilterBtn + + # Select Menu + elif event.char == 't': + button = UI.SelectBtn # Help Menu elif event.char == 'l': @@ -2740,10 +2756,12 @@ global INVERTFILTER # Only toggle state if there is an active filtering wildcard + # If we do, reset the cursor to the top, but select nothing if UI.FilterWildcard[1]: INVERTFILTER = not INVERTFILTER RefreshDirList(event) + KeySelTop(event, clearsel=True) return 'break' @@ -3024,25 +3042,106 @@ # Event Handler: Select First Item ##### -def KeySelTop(event): +def KeySelTop(event, clearsel=False): + UI.SetSelection(('0',),0) + # In some cases, we call this routine just to position the cursor + # at the top of the file list but we don't actually want anything + # selected + + if clearsel: + KeySelNone(event) + return 'break' # End of 'KeySelTop()' ##### +# Event Handler: Filter Using Wildcard +##### + +def KeyFiltWild(event, initial=""): + global UI + + prompt = pWILDFILT + + # Ask the user for the wildcard pattern, using initial string, if any + if initial: + uwc = askstring(prompt, pENWILD, initialvalue=initial) + else: + uwc = askstring(prompt, pENWILD, initialvalue=UI.LastFiltWildcard) + + # Return focus to the main interface + UI.DirList.focus() + + # Blank value means to abort + if not uwc: + return 'break' + + # Reposition cursor to top of display and deselect everything + KeySelTop(event, clearsel=True) + + # Unless the user indicates otherwise, cook the regex so + # a match can occur anywhere on the line. If the user wants + # strict matching, save this fact so it can escape WILDNOCASE. + + strict = False + if uwc[0] == STRICTMATCH: + wc = uwc[1:] + strict = True + else: + wc = r".*" + uwc + + # Compile it - abort if compilation fails + # Build both a normal and lower-case version + # of the search engine so we can support case-insensitive + # matching elswehere. + + try: + wild = re.compile(wc) + wildl = re.compile(wc.lower()) + + except: + WrnMsg(wWILDCOMP % wc) + return 'break' + + # Refresh the display only showing entries that match + + UI.FilterWildcard = (wc, wild, wildl, strict) + RefreshDirList(None) + + # Save the wildcard only if dynamic menus are enabled (MAXMENU > 0) + # AND one of two conditions exist: + # + # 1) No initial string was provided (The user entered a command manually). + # 2) An initial string was provided, but the user edited it. + + if (MAXMENU > 0) and ((not initial) or (uwc != initial)): + UI.LastFiltWildcard = uwc + + # Add this wildcard to the menu if its not there already + if uwc not in UI.FilterHist: + UpdateMenu(UI.FilterBtn, UI.FilterHist, MAXMENU, MAXMENUBUF, KeyFiltWild, newentry=uwc, fakeevent=True) + + # Dump wildcard stack if debug requested it + if DEBUGLEVEL & DEBUGWILD: + PrintDebug(dWILDLST % dFILTER, UI.FilterHist) + + return 'break' + +# End of 'KeyFiltWild()' + + +##### # Event Handler: Filter Or Select Using Wildcard ##### -def KeySelWild(event, initial="", FilterWildcard=False): +def KeySelWild(event, initial=""): global UI - if FilterWildcard: - prompt = pWILDFILT - else: - prompt = pWILDSEL + prompt = pWILDSEL # Ask the user for the wildcard pattern, using initial string, if any if initial: @@ -3055,7 +3154,7 @@ # Blank value means to abort if not uwc: - return + return 'break' # Clear current selections KeySelNone(event) @@ -3084,38 +3183,30 @@ WrnMsg(wWILDCOMP % wc) return 'break' - # This function can be called to use wildcards to: 1) Filter file list or 2) Select files + # Iterate over the current directory listing saving the + # indexes of items which match. We start at 1 not 0 because + # the first entry ("..") is never considered when doing + # wildcard matching. This routine also observes the + # WILDNOCASE option - if set to True, case is collpased for + # matching purposes. - if FilterWildcard: - UI.FilterWildcard = (wc, wild, wildl, strict) - RefreshDirList(None) + matches = [] + wc = wild + if WILDNOCASE and not strict: + wc = wildl - else: + for x in range(1,UI.DirList.size()): - # Iterate over the current directory listing saving the - # indexes of items which match. We start at 1 not 0 because - # the first entry ("..") is never considered when doing - # wildcard matching. This routine also observes the - # WILDNOCASE option - if set to True, case is collpased for - # matching purposes. - - matches = [] - wc = wild + matchthis = UI.DirList.get(x) if WILDNOCASE and not strict: - wc = wildl + matchthis = matchthis.lower() - for x in range(1,UI.DirList.size()): + if wc.match(matchthis): + matches.append(x) - matchthis = UI.DirList.get(x) - if WILDNOCASE and not strict: - matchthis = matchthis.lower() - - if wc.match(matchthis): - matches.append(x) - - # If anything matched, select it - if matches: - UI.SetSelection(matches, matches[0]) + # If anything matched, select it + if matches: + UI.SetSelection(matches, matches[0]) # Save the wildcard only if dynamic menus are enabled (MAXMENU > 0) # AND one of two conditions exist: @@ -3127,13 +3218,12 @@ UI.LastSelWildcard = uwc # Add this wildcard to the menu if its not there already - if uwc not in UI.WildHist: - UpdateMenu(UI.WildBtn, UI.WildHist, MAXMENU, MAXMENUBUF, KeySelWild, newentry=uwc, fakeevent=True) + if uwc not in UI.SelectHist: + UpdateMenu(UI.SelectBtn, UI.SelectHist, MAXMENU, MAXMENUBUF, KeySelWild, newentry=uwc, fakeevent=True) # Dump wildcard stack if debug requested it if DEBUGLEVEL & DEBUGWILD: - PrintDebug(dWILDSTK, UI.WildHist) - + PrintDebug(dWILDLST %dSELECT, UI.SelectHist) return 'break' @@ -4648,10 +4738,7 @@ UI.CurrentDir=STARTDIR os.chdir(STARTDIR) UI.DirList.insert(0, *BuildDirList(UI.CurrentDir)) - KeySelTop(None) - KeySelNone(None) - - + KeySelTop(None, clearsel=True) # Update titlebar to reflect any changes UI.UpdateTitle(UIroot) @@ -5043,7 +5130,8 @@ # Initialize storage for last manually entered directory path UI.LastPathEntered = "" -# Initialize storage for last manually entered selection wildcard +# Initialize storage for last manually entered Filter and Selection wildcards +UI.LastFiltWildcard = "" UI.LastSelWildcard = "" # Initialize storage for current location