<> <> <> <<>> DIRECTORY BasicTime USING [GMT, Now, Period, Update, nullGMT], Commander USING [CommandProc, Handle, Register], CommandTool USING [DoCommand, ArgumentVector, Failed, Parse], Convert USING [Error, IntFromRope], List USING [Assoc], Process USING [Pause, SecondsToTicks], ProcessProps USING [GetPropList], Rope USING [Cat, ROPE], RepeatCommand, Tempus USING [Parse, Unintelligible]; RepeatCommandImpl: CEDAR PROGRAM IMPORTS BasicTime, Commander, CommandTool, Convert, List, Process, ProcessProps, Rope, Tempus EXPORTS RepeatCommand ~ BEGIN OPEN RepeatCommand; doc: Rope.ROPE = "\"Command line to be performed\" [period [\"Start time interpretable by Tempus\" [nTimes]]] period defaults to 24*60*60 (one day) startTime defaults to BasicTime.Now[] nTimes defaults to LAST[INT]"; Repeat: PUBLIC PROC [cmd: Rope.ROPE, period: INT _ Days, start: BasicTime.GMT _ Immediately, nTimes: INT _ Forever] ~ { nextTime: BasicTime.GMT _ IF start = BasicTime.nullGMT THEN BasicTime.Now[] ELSE start; FOR i: INT IN [0..nTimes) DO WaitForTime[nextTime]; [] _ CommandTool.DoCommand[commandLine: cmd, parent: NARROW[List.Assoc[$CommanderHandle, ProcessProps.GetPropList[]]]]; nextTime _ BasicTime.Update[nextTime, period]; ENDLOOP; }; WaitForTime: PROC [time: BasicTime.GMT] ~ { timeLeft: INT; WHILE (timeLeft _ BasicTime.Period[ from: BasicTime.Now[], to: time ]) > 0 DO Process.Pause[Process.SecondsToTicks[MIN[timeLeft, 1000]]]; ENDLOOP; }; RepeatCommandProc: Commander.CommandProc = { <<[cmd: Commander.Handle] RETURNS [result: REF ANY _ NIL, msg: ROPE _ NIL]>> argv: CommandTool.ArgumentVector _ CommandTool.Parse[cmd: cmd, starExpand: FALSE ! CommandTool.Failed => {msg _ Rope.Cat[ "usage: ", doc]; GO TO failed}]; <> argc: NAT _ argv.argc; commandLine: Rope.ROPE; startTime: BasicTime.GMT _ BasicTime.nullGMT; period: INT _ Days; nTimes: INT _ LAST[INT]; IF argc < 2 THEN {msg _ Rope.Cat[ "usage: ", doc]; GO TO failed}; commandLine _ argv[1]; IF argc >= 3 THEN period _ Convert.IntFromRope[argv[2] ! Convert.Error => { msg _ Rope.Cat[ "Can't Parse \"", argv[2], "\" as an INT"]; GO TO failed}]; IF argc >= 4 THEN startTime _ Tempus.Parse[argv[3] ! Tempus.Unintelligible => { msg _ Rope.Cat[ "Can't Parse \"", argv[3], "\" as a time"]; GO TO failed}].time; IF argc >= 5 THEN nTimes _ Convert.IntFromRope[argv[4] ! Convert.Error => { msg _ Rope.Cat[ "Can't Parse \"", argv[4], "\" as an INT"]; GO TO failed}]; Repeat[commandLine, period, startTime, nTimes]; EXITS failed => {result _ $Failure}; }; <> Commander.Register[ key: "///Commands/Repeat", proc: RepeatCommandProc, doc: doc, clientData: NIL, interpreted: TRUE ]; END.