diff --git a/twander.py b/twander.py index 60cbe18..cd5186e 100755 --- a/twander.py +++ b/twander.py @@ -6,7 +6,7 @@ # Program Information PROGNAME = "twander" -RCSID = "$Id: twander.py,v 3.108 2003/02/26 23:24:16 tundra Exp $" +RCSID = "$Id: twander.py,v 3.109 2003/02/27 00:49:39 tundra Exp $" VERSION = RCSID.split()[2] # Copyright Information @@ -296,9 +296,6 @@ KB = 1024 # 1 KB constant MB = KB * KB # 1 MB constant GB = MB * KB # 1 GB constant -MAXSORTFIELD = 7 # Highest legal field # for sorting -NAMEFIELD = 7 # Field containing name for normal displays -DLVNAMEFIELD = 5 # Field containting name in Drive List View NUMFUNCKEY = 12 # Number of function keys NUMPROGMEM = 12 # Number of program memories POLLINT = 20 # Interval (ms) the poll routine should run @@ -306,6 +303,21 @@ SHOWDRIVES = '\\\\' # Logical directory name for Win32 Drive Lists STRICTMATCH = '#' # Tells wildcard system to enforce strict matching +# Sorting-Related Constants + +fNONE = "None" +fPERMISSIONS = "Permissions" +fLINKS = "Link Count" +fOWNER = "Owner" +fGROUP = "Group" +fLENGTH = "Length" +fDATE = "Date/Time" +fNAME = "Name" + +FieldNames = [fNONE, fPERMISSIONS, fLINKS, fOWNER, fGROUP, fLENGTH, fDATE, fNAME] + +MAXSORTFIELD = len(FieldNames) + ##### # System-Related Defaults ##### @@ -538,7 +550,7 @@ TTLFILES = "Total Files:" TTLSIZE = "Total Size:" -TTLSORTFLD = "Sort => Fld:" +TTLSORTFLD = "Sort By" TTLSORTREV = "Rev:" TTLSORTSEP = "Sep:" @@ -1731,7 +1743,8 @@ mainwin.title("%s %s %s: %s %s %s %s %s %s %s %s %s %s %s" % (PROGNAME, VERSION, FULLNAME, UI.CurrentDir, TTLFILES, str(self.DirList.size()), TTLSIZE, FileLength(self.TotalSize), - TTLSORTFLD, SORTBYFIELD, TTLSORTREV, YesOrNo[SORTREVERSE], TTLSORTSEP, YesOrNo[SORTSEPARATE])) + TTLSORTFLD, FieldNames[SORTBYFIELD], TTLSORTREV, YesOrNo[SORTREVERSE], + TTLSORTSEP, YesOrNo[SORTSEPARATE])) # End of method 'twanderUI.UpdateTitle()' @@ -2821,8 +2834,9 @@ global UI UI.TotalSize = 0 - dDetails, fDetails, detlist = [], [], [] - dFields, fFields = [], [] + + fileinfo = [] + dKeys, fKeys = {}, {} # Indicate where in each display string the actual file name # can be found. This is used both in the code in this routine @@ -2846,38 +2860,91 @@ # Normal directory reads if currentdir != SHOWDRIVES: - # Walk the directory separate subdirs and files - for file in os.listdir(currentdir): + # Get and sort directory contents - detail, fields = FileDetails(file, currentdir) + filelist = os.listdir(currentdir) + for x in range(len(filelist)): + + # Get File/Dir name - # Track directory and file entries separately + file = filelist[x] + + # Get detail display string as well as individual fields + + detail, fields = FileDetails(file, currentdir) + + # Get the key by which to sort - we decrement it by one because + # the user expresses it as a 1-relative value. + # Collapse case on Win32 when sorting by name + + sortkey = fields[SORTBYFIELD-1] + if OSNAME == 'nt' and (FieldNames[SORTBYFIELD] == fNAME): + sortkey = sortkey.lower + + + # Keep track of the file name and its details, separating directories from files + # Build corresponding key list for sorting if detail[0] == ST_SPECIALS["04"]: - dDetails.append(detail) - dFields.append(fields) - else: - fDetails.append(detail) - fFields.append(fields) - # Sort as requested - SORTBYFIELD == 0 means no sorting - return in order provided by OS - # SORTSEPARATE == True means to sort directories and files separately - # Sorting is case-insensitive on Win32 systems + fileinfo.append((file+PSEP, detail+PSEP)) + dKeys.setdefault(sortkey, []).append(x) + + else: + fileinfo.append((file, detail)) + fKeys.setdefault(sortkey, []).append(x) + + - dList, fList = [], [] - if 0 < SORTBYFIELD <= MAXSORTFIELD: + # Sort keys according to user's desire for Dir/File separation + + if SORTSEPARATE: + dk = dKeys.keys() + dk.sort() + fk = fKeys.keys() + fk.sort() - if OSNAME == 'nt': - CollapseCase = True - else: - CollapseCase = False + else: + # Combine the two key dicts into one composite + # dictionary (dKeys) - if SORTSEPARATE: - dList = SortDir(dDetails, dFields, NAMEFIELD, SORTBYFIELD, SORTREVERSE, UI.DetailsOn, CollapseCase) - fList = SortDir(fDetails, fFields, NAMEFIELD, SORTBYFIELD, SORTREVERSE, UI.DetailsOn, CollapseCase) - else: - dList = SortDir(dDetails+fDetails, dFields+fFields, NAMEFIELD, SORTBYFIELD, SORTREVERSE, UI.DetailsOn, CollapseCase) + for key in fKeys.keys(): + for val in fKeys[key]: + dKeys.setdefault(key, []).append(val) + + dk = dKeys.keys() + dk.sort() + fk = [] + # Reverse the sorts, if requested + + if SORTREVERSE: + dk.reverse() + fk.reverse() + + # Build corresponding dir/file lists, observing user's + # request for detail information + + dList, fList = [], [] + + for x in dk: + + for index in dKeys[x]: + + if UI.DetailsOn: + dList.append(fileinfo[index][1]) + else: + dList.append(fileinfo[index][0]) + + for x in fk: + + for index in fKeys[x]: + + if UI.DetailsOn: + fList.append(fileinfo[index][1]) + else: + fList.append(fileinfo[index][0]) + # Entry to move up one directory is always first, # no matter what the sort. This is necessary because @@ -3201,60 +3268,6 @@ # End of 'FileDetails()' -##### -# Sort A List Of Directories Or Files, Using A Specified Detail Field As The Key -# Case-Sensitivity Can Be Turned On- Or Off- -# Sort Can Be Normal (Ascending) Or Reversed -# Appends A Path Separator Character To Directory Names -# Returns Sorted List -##### - -def SortDir(details, fields, namefield, keyfield, Reverse, DetailsOn, CollapseCase): - - # Build a dictonary of entries ordered by key field - # We substract 1 from the passed keyfield because the code is 0-relative, - # But the user provides the field as 1-relative. - - # Because the keys are not guaranteed to be unique, each key has - # an associated *list* of entries. Each such entry associated with - # the key is a tuple in the form: (file/dir details string, file/dir name) - - dict = {} - for x in range(len(fields)): - key = fields[x][keyfield-1] - dict.setdefault(key, []).append((details[x], fields[x][namefield-1])) - - - # Sort the keys, reversing if required - - keylist = dict.keys() - keylist.sort() - if Reverse: - keylist.reverse() - - # Build Result Set, Appending Path Separators To Directory Entries - - results = [] - for key in keylist: - - # Process each entry associated with a given key - - for det, nam in dict[key]: - - # Append the path separator for directories - if det[0] == ST_SPECIALS["04"]: - det += PSEP - nam += PSEP - - if DetailsOn: - results.append(det) - else: - results.append(nam) - - return results - -# End of 'SortDir()' - ##### # Process A Command Line Containing Built-In Variables