DIRECTORY ProcessProps, Atom, BasicTime, Commander, CommanderOps, IO, IOTioga, List, NodeProps, PFS, PFSNames, PriorityQueue, Process, Rope; ButtonLSImpl: CEDAR PROGRAM IMPORTS ProcessProps, BasicTime, Commander, CommanderOps, IO, IOTioga, List, NodeProps, PFS, PFSNames, PriorityQueue, Process, Rope SHARES IO ~ BEGIN ROPE: TYPE ~ Rope.ROPE; PATH: TYPE ~ PFSNames.PATH; STREAM: TYPE ~ IO.STREAM; GMT: TYPE ~ BasicTime.GMT; LORA: TYPE ~ LIST OF REF ANY; FileItem: TYPE = REF FileItemRep; FileItemRep: TYPE = RECORD [fullUName, attachedTo: PATH, created: GMT, bytes: INT, fileType: PFS.FileType]; SortPred: PriorityQueue.SortPred = { xx: FileItem = NARROW[x]; yy: FileItem = NARROW[y]; options: LORA = NARROW[data]; FOR each: LORA ¬ options, each.rest WHILE each # NIL DO SELECT each.first FROM $MoreRecent => IF xx.created#yy.created THEN RETURN [BasicTime.Period[xx.created, yy.created] < 0]; $LessRecent => IF xx.created#yy.created THEN RETURN [BasicTime.Period[xx.created, yy.created] > 0]; $Larger => IF xx.bytes#yy.bytes THEN RETURN [xx.bytes > yy.bytes]; $Smaller => IF xx.bytes#yy.bytes THEN RETURN [xx.bytes < yy.bytes]; ENDCASE; ENDLOOP; RETURN [PFSNames.Compare[xx.fullUName, yy.fullUName, FALSE] = less]; }; QuotedStringError: ERROR = CODE; CmdTokenBreak: PROC [char: CHAR] RETURNS [IO.CharClass] = { IF char = '" THEN RETURN [break]; IF char = ' OR char = '\t OR char = ', OR char = '\l OR char = '\r THEN RETURN [sepr]; RETURN [other]; }; Token: TYPE = RECORD [value, literal: ROPE]; GetCmdToken: PROC [stream: IO.STREAM] RETURNS [token: Token ¬ [NIL, NIL]] = { token.value ¬ token.literal ¬ IO.GetTokenRope[stream, CmdTokenBreak ! IO.EndOfStream => CONTINUE].token; IF Rope.Equal[token.literal, "\""] THEN { ref: REF; IO.Backup[self: stream, char: '"]; ref ¬ IO.GetRefAny[stream ! IO.Error, IO.EndOfStream => ERROR QuotedStringError]; WITH ref SELECT FROM rope: ROPE => token.value ¬ rope; ENDCASE => ERROR QuotedStringError; }; }; -- Stolen from DFUtilitiesImpl DateFormat: TYPE = {explicit, omitted, greaterThan, notEqual}; Date: TYPE = RECORD [ format: DateFormat ¬ $omitted, gmt: GMT ¬ BasicTime.nullGMT ]; DateToStream: PROC [s: STREAM, date: Date] = { SELECT date.format FROM $explicit => { months: ROPE = "JanFebMarAprMayJunJulAugSepOctNovDec"; up: BasicTime.Unpacked = BasicTime.Unpack[date.gmt ! BasicTime.OutOfRange, BasicTime.TimeParametersNotKnown => GO TO noDate]; ConvertZone: PROC = { dst: BOOL = up.dst = yes; SELECT up.zone FROM 0 => IF ~dst THEN s.PutRope["GMT"]; NAT[5*BasicTime.minutesPerHour] => s.PutRope[IF dst THEN "EDT" ELSE "EST"]; NAT[6*BasicTime.minutesPerHour] => s.PutRope[IF dst THEN "CDT" ELSE "CST"]; NAT[7*BasicTime.minutesPerHour] => s.PutRope[IF dst THEN "MDT" ELSE "MST"]; NAT[8*BasicTime.minutesPerHour] => s.PutRope[IF dst THEN "PDT" ELSE "PST"]; ENDCASE => s.PutF["%g%02d%02d", [character[IF up.zone < 0 THEN '- ELSE '+]], [cardinal[up.zone.ABS/BasicTime.minutesPerHour]], [cardinal[up.zone.ABS MOD BasicTime.minutesPerHour]] ] }; s.PutF["%02d-%g-%02d ", [cardinal[up.day]], [rope[months.Substr[start: up.month.ORD*3, len: 3]]], [cardinal[up.year MOD 100]] ]; s.PutF["%02d:%02d:%02d ", [cardinal[up.hour]], [cardinal[up.minute]], [cardinal[up.second]]]; ConvertZone[]; }; $notEqual => s.PutRope["~="]; $greaterThan => s.PutChar['>]; ENDCASE; EXITS noDate => NULL; }; theButtonDataKey: ATOM ~ $ButtonData; theButtonDataRope: ROPE ~ "Poppy1 Class: PopUpButton MessageHandler: CommandTool Menu: ( (( \"\\\"\">) \"Open\" \"Opens a viewer on the file\") () ( \"\\\"\">> \"Stuff filename\" \"Stuff filename at the current insertion point\") ) Feedback: ( (MouseMoved ) )"; theButtonDataValue: REF ~ NodeProps.DoSpecs[theButtonDataKey, theButtonDataRope]; theDFButtonDataRope: ROPE ~ "Poppy1 Class: PopUpButton MessageHandler: CommandTool Menu: ( (( \"\\\"\">) \"Open\" \"Opens a viewer on the df file\") ((> \"\\\"; ButtonOpen \\\"\" \"\\\"\">) \"ButtonOpen\" \"Opens a browser for the files in the DF file\") ( \"\\\"\">> \"Stuff filename\" \"Stuff filename at the current insertion point\") ) Feedback: ( (MouseMoved ) )"; theDFButtonDataValue: REF ~ NodeProps.DoSpecs[theButtonDataKey, theDFButtonDataRope]; theDirectoryButtonDataRope: ROPE ~ "Poppy1 Class: PopUpButton MessageHandler: ThisCommandTool Menu: ( (( \"/*!H\\\"\">) \"ButtonLS\" \"Recursively invoke ButtonLS on this directory\") (( \"/*!H\\\"\">>) \"Fork ButtonLS\" \"Recursively invoke ButtonLS on this directory\") ( \"/\\\"\">> \"Stuff directory name\" \"Stuff directory name at the current insertion point\") ) Feedback: ( (MouseMoved ) )"; theDirectoryButtonDataValue: REF ~ NodeProps.DoSpecs[theButtonDataKey, theDirectoryButtonDataRope]; thePostfixKey: ATOM ~ $Postfix; thePostfixRope: ROPE ~ "-2.0 outlineBoxBearoff 1.0 outlineBoxThickness"; thePostfixValue: REF ~ NodeProps.DoSpecs[thePostfixKey, thePostfixRope]; theFileNameKey: ATOM ~ $ButtonLSFileName; lookF: IOTioga.Looks ~ IOTioga.LooksFromRope["f"]; SetCharProp: PROC [stream: STREAM, key: ATOM, val: REF] ~ { old: IOTioga.PropList ~ IOTioga.GetCharProps[stream]; new: IOTioga.PropList ~ IOTioga.PropPut[old, key, val]; IOTioga.SetCharProps[stream, new]; }; SetLagPrefix: PROC [fileName: PATH, lagPrefix: PATH, lagPrefixLen: INT] RETURNS [newLagPrefix: PATH, newLagPrefixLen: INT] = { newPrefix: PATH ¬ IF fileName# NIL THEN PFSNames.Parent[fileName] ELSE NIL; newLagPrefix ¬ lagPrefix; newLagPrefixLen ¬ lagPrefixLen; IF lagPrefix # NIL THEN { IF PFSNames.Equal[lagPrefix, newPrefix] THEN RETURN; -- new prefix same as old }; newLagPrefix ¬ newPrefix; newLagPrefixLen ¬ PFSNames.ComponentCount[newPrefix]; }; ListCommandAux: PROC [cmd: Commander.Handle, printOneFile: PrintOneFileProc] RETURNS [result: REF ¬ NIL, msg: ROPE ¬ NIL] = { PrintOneFile: PROC [item: FileItem] = { [lagPrefix, lagPrefixLen] ¬ printOneFile[out, item, lagPrefix, lagPrefixLen, briefPrint, narrowPrint, fullPrint, attachPrint, oneLine, prefixOnly, typePrint]; }; EachFileName: PFS.NameProc = { attachedTo: PATH ¬ NIL; created: BasicTime.GMT ¬ BasicTime.nullGMT; bytes: INT ¬ -1; fileType: PFS.FileType ¬ PFS.tUnspecified; uniqueID: PFS.UniqueID; item: FileItem ¬ NIL; continue ¬ TRUE; Process.CheckForAbort[]; IF xactLevelMatch AND componentsRequired # PFSNames.ComponentCount[name] THEN RETURN; IF NOT prefixOnly THEN { [attachedTo: attachedTo, bytes: bytes, uniqueID: uniqueID, fileType: fileType] ¬ PFS.FileInfo[name: name]; }; IF bytes >=0 AND lostFilesOnly THEN RETURN; IF attachedTo#NIL AND unattachedOnly THEN RETURN; item ¬ NEW[FileItemRep ¬ [name, attachedTo, uniqueID.egmt.gmt, bytes, PFS.tUnspecified]]; filesSeen ¬ filesSeen + 1; IF bytes > 0 THEN bytesTotal ¬ bytesTotal + bytes; SELECT TRUE FROM prefixOnly => { oldLag: PATH ¬ lagPrefix; [lagPrefix, lagPrefixLen] ¬ SetLagPrefix[name, lagPrefix, lagPrefixLen]; IF oldLag # lagPrefix THEN { item.fullUName ¬ lagPrefix; PriorityQueue.Insert[pq, item]; }; }; complexSorting => PriorityQueue.Insert[pq, item]; ENDCASE => PrintOneFile[item]; }; EachFileInfo: PFS.InfoProc = { item: FileItem ¬ NIL; continue ¬ TRUE; Process.CheckForAbort[]; IF xactLevelMatch AND componentsRequired # PFSNames.ComponentCount[fullFName] THEN RETURN; IF bytes >=0 AND lostFilesOnly THEN RETURN; IF attachedTo#NIL AND unattachedOnly THEN RETURN; item ¬ NEW[FileItemRep ¬ [fullFName, attachedTo, uniqueID.egmt.gmt, bytes, fileType]]; filesSeen ¬ filesSeen + 1; IF bytes > 0 THEN bytesTotal ¬ bytesTotal + bytes; SELECT TRUE FROM prefixOnly => { oldLag: PATH ¬ lagPrefix; [lagPrefix, lagPrefixLen] ¬ SetLagPrefix[fullFName, lagPrefix, lagPrefixLen]; IF oldLag # lagPrefix THEN { item.fullUName ¬ lagPrefix; PriorityQueue.Insert[pq, item]; }; }; complexSorting => PriorityQueue.Insert[pq, item]; ENDCASE => PrintOneFile[item]; }; TryPattern: PROC [pattern: PATH, allVersions: BOOL¬FALSE] = { Do: PROC [] ~ { ENABLE PFS.Error => IF error.group # $bug THEN { IO.PutRope[cmd.err, " -- "]; IO.PutRope[cmd.err, error.explanation]; IO.PutRope[cmd.err, "\n"]; GO TO err}; patternsTried ¬ patternsTried + 1; IF allVersions THEN { pattern ¬ PFSNames.SetVersionNumber[pattern, [all]]; highestPrint ¬ FALSE; }; IF highestPrint THEN pattern ¬ PFSNames.SetVersionNumber[pattern, [highest]]; IF xactLevelMatch THEN { pattern ¬ PFS.AbsoluteName[pattern]; componentsRequired ¬ PFSNames.ComponentCount[pattern]; }; complexSorting ¬ sortData # NIL; SELECT TRUE FROM prefixOnly => pq ¬ PriorityQueue.Create[SortPred, NIL]; complexSorting => pq ¬ PriorityQueue.Create[SortPred, sortData]; ENDCASE => pq ¬ NIL; [lagPrefix, lagPrefixLen] ¬ SetLagPrefix[NIL, lagPrefix, lagPrefixLen]; IF prefixOnly OR xactLevelMatch THEN PFS.EnumerateForNames[pattern, EachFileName] ELSE PFS.EnumerateForInfo[pattern, EachFileInfo]; [lagPrefix, lagPrefixLen] ¬ SetLagPrefix[NIL, lagPrefix, lagPrefixLen]; IF pq # NIL THEN { lagName: PATH ¬ NIL; THROUGH [0..PriorityQueue.Size[pq]) DO item: FileItem = NARROW[PriorityQueue.Remove[pq]]; IF prefixOnly THEN { IF PFSNames.Equal[item.fullUName, lagName] THEN LOOP; lagName ¬ item.fullUName; }; PrintOneFile[item]; ENDLOOP; }; EXITS err => {IO.PutRope[cmd.err, "\n"]; RETURN}; }; wDir: ROPE ~ NARROW[ProcessProps.GetProp[$WorkingDirectory]]; newProp: List.AList ~ List.PutAssoc[$WDir, PFS.PathFromRope[wDir], NIL]; ProcessProps.AddPropList[newProp, Do]; }; AddSortOption: PROC [option: ATOM] = { new: LORA ¬ LIST[option]; IF sortDataTail = NIL THEN sortData ¬ new ELSE sortDataTail.rest ¬ new; sortDataTail ¬ new; }; RemSortOption: PROC [option: ATOM] = { lag: LORA ¬ sortData; IF lag = NIL THEN RETURN; IF lag.first = option THEN { sortData ¬ sortData.rest; RETURN}; FOR each: LORA ¬ lag.rest, each.rest WHILE each # NIL DO IF each.first = option THEN {lag.rest ¬ each.rest; EXIT}; lag ¬ each; ENDLOOP; }; ProcessSwitches: PROC [arg: ROPE] = { sense: BOOL ¬ TRUE; direction: {up, down} ¬ down; FOR index: INT IN [1..Rope.Length[arg]) DO SELECT Rope.Fetch[arg, index] FROM '~ => {sense ¬ NOT sense; LOOP}; '> => direction ¬ down; '< => direction ¬ up; 'a, 'A => attachPrint ¬ sense; 'b, 'B => briefPrint ¬ sense; 'd, 'D => { RemSortOption[$MoreRecent]; RemSortOption[$LessRecent]; IF sense THEN AddSortOption[IF direction = up THEN $LessRecent ELSE $MoreRecent]; }; 'f, 'F => fullPrint ¬ sense; 'h, 'H => highestPrint ¬ sense; 'k, 'K => keepPrint ¬ sense; 'n, 'N => narrowPrint ¬ sense; 'o, 'O => oneLine ¬ sense; 'p, 'P => prefixOnly ¬ sense; 'r, 'R => { }; 's, 'S => { RemSortOption[$Larger]; RemSortOption[$Smaller]; IF sense THEN AddSortOption[IF direction = up THEN $Smaller ELSE $Larger]; }; 't, 'T => typePrint ¬ sense; 'u, 'U => unattachedOnly ¬ sense; 'x, 'X => xactLevelMatch ¬ sense; 'z, 'Z => lostFilesOnly ¬ sense; ENDCASE => { result ¬ $Failure; msg ¬ Rope.Cat["Unknown switch: ", arg.Substr[0, index], " ", arg.Substr[index]]; RETURN; }; sense ¬ TRUE; ENDLOOP; }; gHost, gDir: ROPE ¬ NIL; out: STREAM = cmd.out; lagPrefix: PATH ¬ NIL; lagPrefixLen: INT ¬ 0; patternsTried, filesSeen, bytesTotal: INT ¬ 0; briefPrint, complexSorting, fullPrint, attachPrint, keepPrint, lostFilesOnly, narrowPrint, oneLine, prefixOnly, typePrint, unattachedOnly, xactLevelMatch: BOOL ¬ FALSE; highestPrint: BOOL ¬ cmd.procData.clientData = $Highest; componentsRequired: INT ¬ 0; sortData: LORA ¬ NIL; sortDataTail: LORA ¬ NIL; pq: PriorityQueue.Ref ¬ NIL; argStream: IO.STREAM ~ IO.RIS[cmd.commandLine]; DO arg: Token = GetCmdToken[argStream ! QuotedStringError => {msg ¬ "Mismatched quotes"; GO TO failed}]; IF arg.value = NIL THEN EXIT; IF Rope.Length[arg.value] = 0 THEN LOOP; IF Rope.Fetch[arg.literal, 0] = '- THEN { ProcessSwitches[arg.literal]; IF result = $Failure THEN RETURN; LOOP; }; TryPattern[PFS.PathFromRope[arg.value ! PFS.Error => IF error.group # $bug THEN { IO.PutRope[cmd.err, " -- "]; IO.PutRope[cmd.err, error.explanation]; IO.PutRope[cmd.err, "\n"]; GO TO failed}]]; ENDLOOP; IF patternsTried = 0 THEN TryPattern[PFS.PathFromRope["*" ! PFS.Error => IF error.group # $bug THEN { IO.PutRope[cmd.err, " -- "]; IO.PutRope[cmd.err, error.explanation]; IO.PutRope[cmd.err, "\n"]; GO TO failed}]]; IF oneLine THEN IO.PutChar[out, '\n]; IF filesSeen > 0 THEN { out: IO.STREAM ~ IO.ROS[]; IO.PutF1[out, "-- %g files", [integer[filesSeen]] ]; IF bytesTotal > 0 THEN IO.PutF1[out, ", %g total bytes", [integer[bytesTotal]] ]; IO.PutChar[out, '\n]; msg ¬ IO.RopeFromROS[out]; }; EXITS failed => {result ¬ $Failure}; }; -- end of ListCommandProc PrintOneFileProc: TYPE = PROC [out: IO.STREAM, item: FileItem, lagPrefix: PATH, lagPrefixLen: INT, briefPrint, narrowPrint, fullPrint, attachPrint, oneLine, prefixOnly, typePrint: BOOL] RETURNS [newLagPrefix: PATH, newLagPrefixLen: INT]; ButtonPrintOneFile: PrintOneFileProc = { IsDF: PROC [p: PATH] RETURNS [BOOL] ~ { name: ROPE ¬ PFSNames.ComponentRope[PFSNames.ShortName[p]]; RETURN [ Rope.Match[pattern: "*.df", object: name, case: FALSE] ]; }; oldLag: PATH ¬ lagPrefix; printName: ROPE ¬ PFS.RopeFromPath[item.fullUName]; fullName: ROPE ¬ printName; oldCharProps, newCharProps: IOTioga.PropList ¬ NIL; newLagPrefix ¬ lagPrefix; newLagPrefixLen ¬ lagPrefixLen; Process.CheckForAbort[]; IF NOT fullPrint AND NOT prefixOnly THEN { [lagPrefix, lagPrefixLen] ¬ SetLagPrefix[item.fullUName, lagPrefix, lagPrefixLen]; IF oldLag # lagPrefix THEN { IO.PutRope[out, PFS.RopeFromPath[lagPrefix]]; IO.PutChar[out, IF oneLine THEN ' ELSE '\n]; }; printName ¬ PFS.RopeFromPath[PFSNames.SubName[item.fullUName, lagPrefixLen]]; IF NOT oneLine THEN IO.PutRope[out, " "]; }; SetCharProp[out, theFileNameKey, fullName]; SetCharProp[out, theButtonDataKey, IF item.fileType=PFS.tDirectory THEN theDirectoryButtonDataValue ELSE IF IsDF[item.fullUName] THEN theDFButtonDataValue ELSE theButtonDataValue]; SetCharProp[out, thePostfixKey, thePostfixValue]; IO.PutRope[out, " "]; SetCharProp[out, thePostfixKey, NIL]; SetCharProp[out, theButtonDataKey, NIL]; IO.PutRope[out, " "]; SELECT TRUE FROM prefixOnly => IO.PutRope[out, printName]; briefPrint => { IO.PutRope[out, printName]; }; ENDCASE => { form: ROPE = IF narrowPrint THEN "%g\n%12g " ELSE "%-24g %6g "; IO.PutF[out, form, [rope[printName]], [integer[item.bytes]] ]; IF item.created = BasicTime.nullGMT THEN IO.PutRope[out, "??"] ELSE DateToStream[out, [explicit, item.created] ]; IF typePrint THEN { r: ROPE ~ SELECT item.fileType FROM PFS.tUnspecified => " tUnspec", PFS.tDirectory => " tDir", PFS.tText => " tText", ENDCASE => IO.PutFR1[" t%g", [integer[item.fileType]]]; IO.PutRope[out, r]; }; IF attachPrint AND item.attachedTo#NIL THEN IO.PutF[out, "%g=> %g", [rope[IF oneLine THEN " " ELSE "\n "]], [rope[PFS.RopeFromPath[item.attachedTo]]]]; }; SetCharProp[out, theFileNameKey, NIL]; IO.PutChar[out, IF oneLine THEN ' ELSE '\n]; RETURN[lagPrefix, lagPrefixLen]; }; PlainPrintOneFile: PrintOneFileProc = { oldLag: PATH ¬ lagPrefix; printName: ROPE ¬ PFS.RopeFromPath[item.fullUName]; newLagPrefix ¬ lagPrefix; newLagPrefixLen ¬ lagPrefixLen; Process.CheckForAbort[]; IF NOT fullPrint AND NOT prefixOnly THEN { [lagPrefix, lagPrefixLen] ¬ SetLagPrefix[item.fullUName, lagPrefix, lagPrefixLen]; IF oldLag # lagPrefix THEN { IO.PutRope[out, PFS.RopeFromPath[lagPrefix]]; IO.PutChar[out, IF oneLine THEN ' ELSE '\n]; }; printName ¬ PFS.RopeFromPath[PFSNames.SubName[item.fullUName, lagPrefixLen]]; IF NOT oneLine THEN IO.PutRope[out, " "]; }; SELECT TRUE FROM prefixOnly => IO.PutRope[out, printName]; briefPrint => { IO.PutRope[out, printName]; }; ENDCASE => { form: ROPE = IF narrowPrint THEN "%g\n%12g " ELSE "%-24g %6g "; IO.PutF[out, form, [rope[printName]], [integer[item.bytes]] ]; IF item.created = BasicTime.nullGMT THEN IO.PutRope[out, "??"] ELSE DateToStream[out, [explicit, item.created] ]; IF typePrint THEN { r: ROPE ~ SELECT item.fileType FROM PFS.tUnspecified => " tUnspec", PFS.tDirectory => " tDir", PFS.tText => " tText", ENDCASE => IO.PutFR1[" t%g", [integer[item.fileType]]]; IO.PutRope[out, r]; }; IF attachPrint AND item.attachedTo#NIL THEN IO.PutF[out, "%g=> %g", [rope[IF oneLine THEN " " ELSE "\n "]], [rope[PFS.RopeFromPath[item.attachedTo]]]]; }; IO.PutChar[out, IF oneLine THEN ' ELSE '\n]; RETURN[lagPrefix, lagPrefixLen]; }; listDoc: ROPE = "{switch | pattern}* Lists files matching pattern. -a print attachments -b brief format -d date sort -f full name print -h highest version -k keep print -n narrow print -o one line -p prefixes only -s size sort -t file type print -x exact level match -u unattached files only -z 0-length files only -> sort decreasing -< sort increasing"; ListCommand: Commander.CommandProc = { RETURN ListCommandAux[cmd, PlainPrintOneFile]; }; ButtonListCommand: Commander.CommandProc = { [] ¬ CommanderOps.DoCommand["Buttons on -quiet", cmd]; RETURN ListCommandAux[cmd, ButtonPrintOneFile]; }; ButtonGenTest: Commander.CommandProc ~ { italic: IOTioga.Looks ~ IOTioga.LooksFromRope["i"]; bold: IOTioga.Looks ~ IOTioga.LooksFromRope["b"]; keyPostfix: ATOM ~ $Postfix; purplePostfix: REF ~ NodeProps.DoSpecs[keyPostfix, "0.75 1 0.9 textColor"]; purpleProps: IOTioga.PropList ~ IOTioga.PropPut[NIL, $Postfix, purplePostfix]; IO.PutRope[cmd.out, "Here is some "]; IOTioga.AddLooks[cmd.out, italic]; IO.PutRope[cmd.out, "italic"]; IOTioga.RemoveLooks[cmd.out, italic]; IO.PutRope[cmd.out, " and "]; IOTioga.AddLooks[cmd.out, bold]; IO.PutRope[cmd.out, "bold"]; IOTioga.RemoveLooks[cmd.out, bold]; IO.PutRope[cmd.out, " text, and a "]; IOTioga.SetCharProps[cmd.out, purpleProps]; IO.PutRope[cmd.out, "purple"]; IOTioga.SetCharProps[cmd.out, NIL]; IO.PutRope[cmd.out, " word.\n"]; }; Commander.Register["ButtonLS", ButtonListCommand, listDoc]; Commander.Register["PlainLS", ListCommand, listDoc]; Commander.Register["ButtonGenTest", ButtonGenTest]; END. ButtonLSImpl.mesa Copyright Σ 1990, 1992 by Xerox Corporation. All rights reserved. Doug Wyatt, August 16, 1990 1:59 pm PDT Bier, February 12, 1992 3:40 pm PST Kenneth A. Pier, October 30, 1990 2:01 pm PST Chauser, May 27, 1992 11:35 am PDT [x: Item, y: Item, data: REF] RETURNS [BOOL] monthName: ARRAY BasicTime.MonthOfYear[January..December] OF ROPE ~ [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]; 'gmt' is valid only if dateFormat = $explicit. (We don't use a variant record because it complicates the client's life too much (i.e., the compiler is unnecessarily picky about assignments involving variant records that aren't REF-containing).) Note: Dates returned by ParseFromStream are guaranteed to have `gmt' = nullGMT if `format' ~= $explicit. The other procedures of this interface ignore the 'gmt' field if 'format' ~= $explicit. ... sets the lagging prefix from the given file name, which is presumed to be syntactically correct, although it need not be complete. A file name without a prefix will set the lagPrefix to NIL. We also enforce lagPrefixLen = Rope.Length[lagPrefix] at exit, assuming that no other routine sets lagPrefix. We have a new lagging prefix, so scan backwards for the LAST directory [name: PATH] RETURNS [continue: BOOL] We may need the info In these cases it is better to enumerate the names, then get the info In these cases it is better to enumerate for info, to reduce server traffic -- remoteCheck _ sense; This argument sets switches for the remaining patterns Now the argument is assumed to be a file pattern. PROC [out: IO.STREAM, item: FileItem, lagPrefix: PATH, lagPrefixLen: INT, briefPrint, narrowPrint, fullPrint, attachPrint, oneLine, prefixOnly, typePrint: BOOL] RETURNS [newLagPrefix: PATH, newLagPrefixLen]; item: REF [fullUName, attachedTo: PATH, created: GMT, bytes: INT, keep: CARDINAL, PFS.FileType] Factor out the directories Emit the button and a space. PROC [out: IO.STREAM, item: FileItem, lagPrefix: PATH, lagPrefixLen: INT, briefPrint, narrowPrint, fullPrint, attachPrint, oneLine, prefixOnly, typePrint: BOOL] RETURNS [newLagPrefix: PATH, newLagPrefixLen]; item: REF [fullUName, attachedTo: PATH, created: GMT, bytes: INT, keep: CARDINAL, PFS.FileType] Factor out the directories [cmd: Handle] RETURNS [result: REF _ NIL, msg: ROPE _ NIL] CommandObject = [in, out, err: STREAM, commandLine, command: ROPE, ...] [cmd: Handle] RETURNS [result: REF _ NIL, msg: ROPE _ NIL] CommandObject = [in, out, err: STREAM, commandLine, command: ROPE, ...] Κa–(cedarcode) style•NewlineDelimiter ™code™Kšœ Οeœ7™BK™'K™#K™-K™"K™—šΟk ˜ Kšœ8žœžœ)˜‚K˜—KšΟn œžœž˜Kšžœ3žœžœ(˜ƒKšžœž˜ Kšœž˜K˜Kšžœžœžœ˜Kšžœžœ žœ˜Kšžœžœžœžœ˜Kšžœžœ žœ˜Kš žœžœžœžœžœžœ˜K˜Kšœ žœžœ ˜!š œ žœžœžœ žœ žœ žœ ˜kK˜—šŸœ˜$Kšœžœžœžœ™,Kšœžœ˜Kšœžœ˜Kšœ žœžœ˜š žœžœžœžœž˜7šžœ ž˜šœžœž˜,Kšžœ0˜6—šœžœž˜,Kšžœ0˜6—šœ žœž˜$Kšžœ˜—šœ žœž˜%Kšžœ˜—Kšžœ˜—Kšžœ˜—Kšžœ/žœ ˜DK˜K˜—šŸœžœžœ˜ K˜—š Ÿ œžœžœžœžœ˜;Kšžœ žœžœ ˜!Kšžœ žœ žœ žœ žœ žœžœ˜WKšžœ ˜K˜K˜—šœžœžœžœ˜,K˜—šŸ œžœ žœžœžœžœžœ˜MKšœžœ&žœžœ˜h•StartOfExpansion6[pattern: ROPE, object: ROPE, case: BOOL _ TRUE]šžœ!žœ˜)Kšœžœ˜ K–[self: STREAM, char: CHAR]šžœ ˜"Kš œžœžœžœžœ˜Qšžœžœž˜Kšœžœ˜!Kšžœžœ˜#—Kšœ˜—K˜K˜—šœ žœ*žœžœ™EKšœR™RK™K™—K˜Kšœ žœ.˜>šœžœžœ˜K˜Kšœžœ˜Kšœυ™υKšœ˜K™ΒK™—šŸ œžœžœ˜.šžœ ž˜šœ˜Kšœžœ*˜6˜2Kšœ<žœžœ ˜J—šŸ œžœ˜Kšœžœ˜šžœ ž˜Kšœžœžœ˜#Kšžœ*žœžœžœ˜KKšžœ*žœžœžœ˜KKšžœ*žœžœžœ˜KKšžœ*žœžœžœ˜Kšžœ˜ šœ˜Kšœ žœ žœžœ˜,Kšœžœ˜1Kšœžœžœ˜4K˜———K˜—šœ˜Kšœ˜Kšœ$žœ˜5Kšœžœ˜K˜—šœ˜KšœC˜C—Kšœ˜K˜—Kšœ˜Kšœ˜Kšžœ˜—šž˜Kšœ žœ˜—K˜K˜—Kšœžœ˜%Kšœžœ€˜—Kšœžœ:˜QKšœžœΜ˜εKšœžœ<˜UKšœžœΥ˜υšœžœC˜cK˜—Kšœžœ ˜Kšœžœ4˜Hšœžœ4˜HK˜—šœžœ˜)K˜—˜2K˜—š Ÿ œžœ žœžœžœ˜;K˜5K˜7K˜"K˜K˜—šŸ œžœ žœ žœžœžœžœžœ˜~KšœΏžœp™²Kš œ žœžœ žœžœžœžœ˜KK˜K˜šžœ žœžœ˜Kšžœ&žœžœΟc˜NK˜—Kšœ8žœ ™FK˜K˜5Kšœ˜K˜—šŸœžœ9žœ žœžœžœžœ˜}šŸ œžœ˜'K˜žK˜K˜—–. -- [fullFName: ROPE] RETURNS [continue: BOOL]šŸ œžœ ˜Kšœžœžœ žœ™%Kšœ žœžœ˜Kšœžœ˜+Kšœžœ˜Kšœ žœ žœ˜*Kšœ žœ ˜Kšœžœ˜Kšœ žœ˜Kšœ˜Kšžœžœ4žœžœ˜Ušžœžœ žœ˜K™KšœQžœ˜jK˜—Kšžœ žœžœžœ˜+Kš žœ žœžœžœžœ˜1Kšœžœ<žœ˜YK˜Kšžœ žœ!˜2šžœžœž˜šœ˜Kšœžœ ˜K˜Hšžœžœ˜K˜Kšœ˜K˜—K˜—Kšœ1˜1KšžœΟb œ˜—K˜—šŸ œžœ ˜Kšœžœ˜Kšœ žœ˜Kšœ˜Kšžœžœ9žœžœ˜ZKšžœ žœžœžœ˜+Kš žœ žœžœžœžœ˜1KšœžœL˜VK˜Kšžœ žœ!˜2šžœžœž˜šœ˜Kšœžœ ˜K˜Mšžœžœ˜K˜Kšœ˜K˜—K˜—Kšœ1˜1Kšžœ‘ œ˜—K˜—š Ÿ œžœ žœžœžœ˜=šŸœžœ˜šžœžœ žœžœ˜0Kšžœ˜Kšžœ%˜'K˜Kšžœžœ˜ —K˜"šžœ žœ˜K˜4Kšœžœ˜Kšœ˜—šžœž˜K˜8—šžœžœ˜Kšœ žœ˜$K˜6Kšœ˜—Kšœžœ˜ šžœžœž˜Kšœ2žœ˜7K˜@Kšžœ žœ˜—Kšœ)žœ˜Gšžœ žœ˜šžœžœ)˜1K™E—šžœžœ)˜1K™K——Kšœ)žœ˜Gšžœžœžœ˜Kšœ žœžœ˜šžœž˜&Kšœžœ˜2šžœ žœ˜Kšžœ)žœžœ˜5K˜K˜—Kš‘ œ˜Kšžœ˜—K˜—šž˜Kšœžœžœ˜+—K˜—Kšœžœžœ*˜=Kšœ+žœžœ˜HKšœ&˜&K˜—šŸ œžœ žœ˜&Kšœžœžœ ˜Kšžœžœžœžœ˜GK˜K˜—šŸ œžœ žœ˜&Kšœžœ ˜Kšžœžœžœžœ˜šžœžœ˜K˜Kšžœ˜—š žœžœžœžœž˜8Kšžœžœžœ˜9K˜ Kšžœ˜—K˜—šŸœžœžœ˜%Kšœžœžœ˜K˜šžœžœžœž˜*šžœž˜"Kšœžœžœ˜ K˜K˜K˜K˜šœ ˜ Kšœ˜Kšœ˜šžœž˜ Kšœžœžœ žœ˜C—K˜—K˜K˜K˜K˜K˜K˜šœ ˜ Kšœ™Kšœ˜—šœ ˜ Kšœ˜Kšœ˜šžœž˜ Kšœžœžœ žœ ˜<—Kšœ˜—K˜K˜!K˜!K˜ šžœ˜ K˜K˜QKšžœ˜Kšœ˜——Kšœžœ˜ Kšžœ˜—K˜—Kšœ žœžœ˜Kšœžœ ˜Kšœ žœžœ˜Kšœžœ˜Kšœ&žœ˜.Kšœ›žœžœ˜¨Kšœžœ&˜8Kšœžœ˜Kšœ žœžœ˜Kšœžœžœ˜Kšœžœ˜Kš œ žœžœžœžœ˜/šž˜KšœVžœžœ ˜eKšžœ žœžœžœ˜Kšžœžœžœ˜(šžœ!žœ˜)Kšœ6™6Kšœ˜Kšžœžœžœ˜!Kšžœ˜Kšœ˜—Kšœ1™1šœ žœ'žœžœ˜QKšžœ˜Kšžœ%˜'K˜Kšžœžœ ˜—Kšžœ˜—š žœžœ žœ!žœžœ˜eKšžœ˜Kšžœ%˜'K˜Kšžœžœ ˜—Kšžœ žœžœ˜%šžœžœ˜Kš œžœžœžœžœ˜Kšžœ2˜4Kšžœžœžœ8˜QKšžœ˜Kšœžœ˜K˜—šž˜K˜—Kšœ˜K˜—KšœžœžœžœžœžœžœSžœžœžœžœ˜νK˜šŸœ˜(KšžœžœžœžœžœSžœžœ™ΟKš œžœžœ žœ žœžœžœ ™_š Ÿœžœžœžœžœ˜'Kšœžœ1˜;Kšžœ3žœ˜BK˜—Kšœžœ ˜Kšœ žœžœ˜3Kšœ žœ ˜Kšœ/žœ˜3K˜9Kšœ˜š žœžœ žœžœ žœ˜*Kšœ™K˜Ršžœžœ˜Kšžœžœ˜-Kšžœžœ žœžœ˜-K˜—Kšœ žœ>˜MKšžœžœ žœžœ˜*K˜—K˜K™Kš‘ œ ˜+Kš‘ œžœžœ žœžœžœžœžœ˜΄Kš‘ œ&˜1Kšžœ˜Kš‘ œžœ˜%Kš‘ œžœ˜(Kšžœ˜K˜šžœžœž˜Kšœžœ˜)šœ˜Kšžœ˜K˜—šžœ˜ Kš œžœžœ žœžœ˜@Kšžœ<˜>šžœ!˜#Kšžœžœ˜Kšžœ.˜2—šžœ žœ˜šœžœžœž˜#Kšžœ˜Kšžœ˜Kšžœ˜Kšžœžœ*˜7—Kšžœ˜Kšœ˜—Kšžœ žœžœžœžœžœ žœžœžœ"˜˜K˜——Kš‘ œžœ˜&Kšžœžœ žœžœ˜-Kšžœ˜ K˜K˜—šŸœ˜'KšžœžœžœžœžœSžœžœ™ΟKš œžœžœ žœ žœžœžœ ™_Kšœžœ ˜Kšœ žœžœ˜3K˜9Kšœ˜š žœžœ žœžœ žœ˜*Kšœ™K˜Ršžœžœ˜Kšžœžœ˜-Kšžœžœ žœžœ˜-K˜—Kšœ žœ>˜MKšžœžœ žœžœ˜*K˜—šžœžœž˜Kšœžœ˜)šœ˜Kšžœ˜K˜—šžœ˜ Kš œžœžœ žœžœ˜@Kšžœ<˜>šžœ!˜#Kšžœžœ˜Kšžœ.˜2—šžœ žœ˜šœžœžœž˜#Kšžœ˜Kšžœ˜Kšžœ˜Kšžœžœ*˜7—Kšžœ˜Kšœ˜—Kšžœ žœžœžœžœžœ žœžœžœ"˜˜K˜——Kšžœžœ žœžœ˜-Kšžœ˜ K˜K˜—šœ žœυ˜‚K˜—šŸ œ˜&Kš œžœ žœžœžœžœ™:Kšœžœžœ™GKšžœ(˜.K˜K˜—šŸœ˜,Kš œžœ žœžœžœžœ™:Kšœžœžœ™GKšœŸ œ˜6Kšžœ)˜/K˜K˜—šŸ œ˜(K˜3K˜1Kšœ žœ ˜Kšœžœ9˜KKšœ0žœ˜NKšžœ#˜%Kšœ"˜"Kšžœ˜Kšœ%˜%Kšžœ˜Kšœ ˜ Kšžœ˜Kšœ#˜#Kšžœ#˜%Kšœ+˜+K• CharProps#Postfix0.75 1 0.9 textColoršžœ˜Kšœžœ˜#Kšžœ˜ K˜K˜—Kšœ;˜;Kšœ4˜4Kšœ3˜3K˜Kšžœ˜—…—GrgΣ