Eq[args[i], "-
undateDf"] => {
EachFile:
PROC [name:
ROPE] ~ {
in, out: IO.STREAM;
base: ROPE ¬ Base[name, TRUE];
Process.CheckForAbort[];
IO.PutF1[cmd.out, "processing %g...\n", IO.rope[base]];
in ¬ IO.RIS[PFS.RopeOpen[PFS.PathFromRope[name]].rope
! PFS.Error => GOTO Bad];
in ¬
PFS.StreamOpen[
fileName: PFS.PathFromRope[name],
streamOptions: [
TRUE,
TRUE]
! PFS.Error => GOTO Bad];
out ¬ FS.StreamOpen[name, $create];
DO
line: ROPE ¬ IO.GetLineRope[in ! IO.EndOfStream => EXIT];
IF all
THEN {
n: INT ¬ Rope.Find[line, "."];
IF n # -1 THEN line ¬ Rope.Substr[line, 0, Rope.SkipTo[line, n, "!"]];
}
ELSE {
n: INT ¬ Rope.Find[line, base, 0, FALSE];
IF n # -1 THEN line ¬ Rope.Substr[line, 0, n+Rope.Length[base]];
};
IO.PutF1[out, "%g\n", IO.rope[line]];
ENDLOOP;
IO.Close[out];
EXITS Bad => IO.PutF1[cmd.out, "can't open %g\n", IO.rope[name]];
};
WHILE NoSwitchArg[i+1] DO OutputError[Enumerate[NextArg[], EachFile]]; ENDLOOP;
};
Eq[args[i], "-
calc"] => {
result: REAL ¬ 1.0;
op: {divide, multiply, add, subtract} ¬ multiply;
WHILE NoSwitchArg[i+1]
DO
arg: ROPE ¬ NextArg[];
SELECT
TRUE
FROM
Eq[arg, "-"] => op ¬ subtract;
Eq[arg, "+"] => op ¬ add;
Eq[arg, "/"] => op ¬ divide;
Eq[arg, "*"] => op ¬ multiply;
ENDCASE => {
val:
REAL ¬ Convert.RealFromRope[arg ! Convert.Error => {
IO.PutF1[cmd.out, "bad argument: %g\n", IO.rope[arg]];
EXIT;
}];
result ¬
SELECT op
FROM
divide => result/val,
multiply => result*val,
subtract => result-val,
add => result+val,
ENDCASE => result;
};
ENDLOOP;
IO.PutF1[cmd.out, "= %g\n", IO.real[result]];
};
Eq[args[i], "-
top"] =>
IF cmd.in #
NIL
THEN {
viewer: ViewerClasses.Viewer ¬ ViewerIO.GetViewerFromStream[cmd.out];
IF viewer = NIL OR viewer.class = NIL OR viewer.class.scroll = NIL THEN RETURN;
Process.Pause[Process.MsecToTicks[100]];
[] ¬ viewer.class.scroll[viewer, thumb, 100];
ViewerTools.SetSelection[viewer];
};
Eq[args[i], "-
multiRename"] => {
EachFile:
PROC [name:
ROPE]
RETURNS [continue:
BOOL ¬
TRUE] ~ {
oldName: ROPE ~ FileNames.GetShortName[name];
n: INT ¬ Rope.Find[oldName, oldBase, 0, FALSE];
Process.CheckForAbort[];
IF n = -1
THEN IO.PutRope[cmd.err, Rope.Concat["Error renaming ", name]]
ELSE {
newName: ROPE ~ Rope.Concat[newBase, Rope.Substr[oldName, n+length]];
commandLine: ROPE ~ Rope.Cat["Rename ", newName, " ← ", oldName];
IF interactive
THEN {
IO.PutF[cmd.err, "Rename %g to %g? (RETURN: yes, DEL: no) ",
IO.rope[oldName], IO.rope[newName]];
IF
IO.GetChar[cmd.in
!
IO.Error,
IO.Rubout =>
GOTO
No] # '\n
THEN GOTO No;
};
[] ¬ CommanderOps.DoCommand[commandLine, cmd];
};
EXITS No => IO.PutRope[cmd.err, " . . . aborted\n"];
};
length: NAT;
oldBase, newBase: ROPE ¬ NIL;
WHILE NoSwitchArg[i+1]
DO
arg: ROPE ¬ NextArg[];
IF oldBase = NIL THEN oldBase ¬ arg ELSE newBase ¬ arg;
ENDLOOP;
length ¬ Rope.Length[oldBase];
IF Rope.IsEmpty[oldBase]
OR Rope.IsEmpty[newBase]
THEN IO.PutRope[cmd.out, multiRenameUsage]
ELSE
FS.EnumerateForNames[Rope.Concat[oldBase, "*!H"], EachFile !
FS.Error =>
{IO.PutRope[cmd.out, Rope.Concat[error.explanation, "\n"]]; CONTINUE}];
};
Eq[args[i], "-
updateDirectory"] => {
DoIt:
PROC [mode: {copy, update}, oldDir, newDir, name:
ROPE] ~ {
new: ROPE ¬ Rope.Concat[newDir, name];
old: ROPE ¬ Rope.Concat[oldDir, name];
IF
NOT namesOnly
THEN {
IO.PutF1[cmd.out, "%l", IO.rope["b"]];
IF mode = copy
THEN IO.PutF1[cmd.out, "\t%g doesn't exist\n", IO.rope[old]]
ELSE
IO.PutFL[cmd.out, "\t%g (%g) newer than\n\t%g (%g)\n",
LIST[
IO.rope[new], IO.rope[RopeDate[FS.FileInfo[new].created]],
IO.rope[old], IO.rope[RopeDate[FS.FileInfo[old].created]]]];
IO.PutF1[cmd.out, "%l", IO.rope["B"]];
};
IF interactive
THEN {
c: CHAR;
IO.PutF[cmd.err,
"\t\t?
copy
-c
%g
←\n\t\t\t\t\t%g ?\n\t\t(RET:
yes,
DEL:
no)",
IO.rope[old], IO.rope[new]];
c ¬ IO.GetChar[cmd.in ! IO.Error, IO.Rubout => CONTINUE];
IF c # '\n
THEN {
IO.PutF[cmd.out, "%l aborted%l\n", IO.rope["i"], IO.rope["I"]];
RETURN;
};
};
nChanges ¬ nChanges+1;
IF makeBelieve
THEN {
IF namesOnly
THEN {
ShortDir:
PROC [dir:
ROPE]
RETURNS [short:
ROPE] ~ {
len: INTEGER ¬ Rope.Length[dir];
n: INTEGER ¬ 1+Rope.FindBackward[dir, "/", MAX[0, len-2]];
short ¬ Rope.Substr[dir, n, len-n];
};
IF mode = copy
THEN
IO.PutF[cmd.out, "\t%g (missing in %g)\n",
IO.rope[name], IO.rope[ShortDir[oldDir]]]
ELSE
IO.PutF[cmd.out, "\t%g (%g newer)\n",
IO.rope[name], IO.rope[ShortDir[newDir]]];
}
ELSE
IO.PutF[cmd.out,
"\t\twould
copy
-c
%g
←\n\t\t\t\t\t\t
%g\n",
IO.rope[old], IO.rope[new]];
}
ELSE {
reply:
ROPE ¬ CommanderOps.DoCommandRope[
Rope.Cat["copy -c ", old, " ← ", new],, NIL].out;
reply ¬ Rope.Substr[reply, Rope.SkipOver[reply,, " "]];
reply ¬ Rope.Substr[reply, 0, Rope.Length[reply]-1];
IF Rope.Find[reply, "←"] # -1
THEN reply ¬
IO.PutFR["%g\n\t\t%g",
IO.rope[Rope.Substr[reply, 0, 1+Rope.Find[reply, "←"]]],
IO.rope[Rope.Substr[reply, 2+Rope.Find[reply, "←"]]]];
IO.PutF1[cmd.out, "\t\t%g\n", IO.rope[reply]];
};
};
nChanges: INTEGER ¬ 0;
remoteNames, localNames: REF RopeSequence;
dir: ROPE ¬ ProperDirectoryName[NextArg[ ! argError => GOTO Bad]];
wdir: ROPE ¬ PFS.RopeFromPath[PFS.GetWDir[]];
IF Rope.IsEmpty[dir] THEN RETURN[$Failure, updateDirectoryUsage];
IF (remoteNames ¬ GetFileNames[dir, files]) =
NIL
THEN IO.PutF1[cmd.out, "Error enumerating files in %g\n", IO.rope[dir]];
IF (localNames ¬ GetFileNames[
NIL, files]) =
NIL
THEN IO.PutRope[cmd.out, "Error enumerating files in local directory\n"];
IF
remoteNames =
NIL
OR
localNames =
NIL
THEN RETURN[$Failure, updateDirectoryUsage];
IF namesOnly THEN IO.PutRope[cmd.out, "Discrepancies exist for the following:\n"];
FOR n:
NAT
IN [0..remoteNames.length)
DO
remoteNames[n] ¬ FileNames.GetShortName[remoteNames[n]];
ENDLOOP;
FOR n:
NAT
IN [0..localNames.length)
DO
localNames[n] ¬ FileNames.GetShortName[localNames[n]];
ENDLOOP;
FOR n:
NAT
IN [0..remoteNames.length)
DO
IF InSequence[remoteNames[n], localNames]
THEN {
loc: ROPE ¬ Rope.Concat[wdir, remoteNames[n]];
rem: ROPE ¬ Rope.Concat[dir, remoteNames[n]];
SELECT
BasicTime.Period[
FS.FileInfo[loc].created,
FS.FileInfo[rem].created]
FROM
< 0 => DoIt[update, dir, wdir, remoteNames[n]];
> 0 => DoIt[update, wdir, dir, remoteNames[n]];
ENDCASE;
};
ENDLOOP;
FOR n:
NAT
IN [0..remoteNames.length)
DO
local: ROPE ¬ FileNames.GetShortName[remoteNames[n]];
IF NOT InSequence[local, localNames] THEN DoIt[copy, wdir, dir, local];
ENDLOOP;
FOR n:
NAT
IN [0..localNames.length)
DO
local: ROPE ¬ FileNames.GetShortName[localNames[n]];
IF NOT InSequence[local, remoteNames] THEN DoIt[copy, dir, wdir, local];
ENDLOOP;
IF
NOT namesOnly
THEN
IO.PutF[cmd.out, "\t%g change%g\n",
IO.int[nChanges], IO.rope[IF nChanges = 1 THEN NIL ELSE "s"]];
};
Eq[args[i], "-
noRedundantFiles"], Eq[args[i], "-
noExtraneousFiles"] => {
dir: ROPE ¬ ProperDirectoryName[NextArg[]];
mode:
ATOM ¬
IF Rope.Find[cmd.command, "Extraneous", 0,
FALSE] # -1
THEN $Extraneous ELSE $Redundant;
use: ROPE ¬ IF mode = $Extraneous THEN noExtraneousUsage ELSE redundantUsage;
IF
NOT Rope.IsEmpty[dir]
THEN {
fsNames, localNames: REF RopeSequence;
IF (fsNames ¬ GetFileNames[dir]) =
NIL
THEN IO.PutF1[cmd.out, "Error enumerating files in %g\n", IO.rope[dir]];
IF (localNames ¬ GetFileNames["*"]) =
NIL
THEN IO.PutRope[cmd.out, "Error enumerating files in local directory\n"];
IF fsNames #
NIL
AND localNames #
NIL
THEN {
FOR n:
NAT
IN [0..localNames.length)
DO
localNames[n] ¬ FileNames.GetShortName[localNames[n]];
ENDLOOP;
FOR n:
NAT
IN [0..fsNames.length)
DO
in: BOOL ¬ InSequence[FileNames.GetShortName[fsNames[n]], localNames];
IF (mode = $Extraneous
AND
NOT in)
OR (mode = $Redundant
AND in)
THEN {
IF interactive
THEN {
IO.PutF1[cmd.err,"\nDelete
%g?
(Return:
yes,
Delete:
no)
",
IO.rope[fsNames[n]]];
IF
IO.GetChar[cmd.in !
IO.Error,
IO.Rubout =>
LOOP] # '\n
THEN LOOP;
};
IF makeBelieve
THEN IO.PutF1[cmd.out, "Would delete %g\n", IO.rope[fsNames[n]]]
ELSE {
IO.PutF1[cmd.out, "Deleting %g\n", IO.rope[fsNames[n]]];
FS.Delete[fsNames[n] ! FS.Error => CONTINUE];
};
};
ENDLOOP;
};
}
ELSE RETURN[$Failure, use];
};