DIRECTORY BasicTime, Booting, Commander, CommandTool, Convert, FS, IO, List, ProcessProps, Random, Rope, ThisMachine, UserCredentials, UserProfile; Promptery: CEDAR PROGRAM IMPORTS BasicTime, Booting, Commander, CommandTool, Convert, FS, IO, List, ProcessProps, Random, Rope, ThisMachine, UserCredentials, UserProfile = BEGIN ROPE: TYPE = Rope.ROPE; RopeList: TYPE = LIST OF ROPE; PromptVector: TYPE = REF PromptVectorRep; PromptVectorRep: TYPE = RECORD [ length: CARDINAL, totalWeight: REAL, ropes: SEQUENCE size: CARDINAL OF Prompt]; Prompt: TYPE = RECORD [incrWeight, sumWeight: REAL, rope: ROPE]; prompts: PromptVector _ NewPromptVector[255]; files: RopeList _ NIL; installationDirectory: ROPE _ CommandTool.CurrentWorkingDirectory[]; enabled: BOOLEAN _ FALSE; rs: Random.RandomStream; Subst: PROC [in, old, new: ROPE] RETURNS [out: ROPE] = BEGIN begin: INT; out _ in; WHILE (begin _ out.Find[old]) >= 0 DO out _ out.Replace[start: begin, len: old.Length[], with: new]; ENDLOOP; END; AddPrompt: PROC [old: PromptVector, weight: REAL, r: ROPE] RETURNS [new: PromptVector] = BEGIN IF old.size = old.length THEN BEGIN new _ NEW [PromptVectorRep[old.size*2]]; new.length _ old.length; new.totalWeight _ old.totalWeight; FOR i: CARDINAL IN [0 .. old.length) DO new[i] _ old[i] ENDLOOP; END ELSE new _ old; new[new.length] _ [ incrWeight: weight, sumWeight: weight + (IF new.length > 0 THEN new[new.length-1].sumWeight ELSE 0), rope: r]; new.length _ new.length+1; new.totalWeight _ new.totalWeight + weight; END; AddFile: PROC [to: PromptVector, fileName, wDir: ROPE] RETURNS [new: PromptVector] = BEGIN file: IO.STREAM _ NIL; ok: BOOLEAN _ TRUE; new _ to; file _ FS.StreamOpen[fileName: fileName, wDir: wDir !FS.Error => {ok _ FALSE; CONTINUE}]; IF NOT ok THEN RETURN; DO r: ROPE; w: REAL; [] _ file.SkipWhitespace[]; IF file.EndOf[] THEN EXIT; w _ file.GetReal[]; r _ IO.GetRopeLiteral[file]; new _ AddPrompt[new, w, r]; ENDLOOP; file.Close[]; END; NewPromptVector: PROC [size: CARDINAL] RETURNS [new: PromptVector] = {new _ NEW [PromptVectorRep[size]]; new.totalWeight _ new.length _ 0}; NoticeChanges: UserProfile.ProfileChangedProc --PROC [reason: ProfileChangeReason]-- = BEGIN newFiles: RopeList _ UserProfile.ListOfTokens[key: "Promptery.Sources", default: LIST ["Prompts.txt"]]; temp1, temp2: RopeList; enabled _ UserProfile.Boolean[key: "Promptery.Enabled", default: FALSE]; temp1 _ files; temp2 _ newFiles; WHILE (temp1 # NIL) AND (temp2 # NIL) DO IF NOT temp1.first.Equal[temp2.first] THEN EXIT; temp1 _ temp1.rest; temp2 _ temp2.rest; ENDLOOP; IF (temp1 # NIL) OR (temp2 # NIL) THEN BEGIN files _ newFiles; prompts.totalWeight _ prompts.length _ 0; FOR newFiles _ newFiles, newFiles.rest WHILE newFiles # NIL DO prompts _ AddFile[prompts, newFiles.first, installationDirectory]; ENDLOOP; END; END; changePromptHandle: Commander.CommandProcHandle _ NEW [Commander.CommandProcObject _ [proc: ChangePrompt]]; SetPromptery: PROC [cmd: Commander.Handle] RETURNS [result: REF _ NIL, msg: Rope.ROPE _ NIL] --Commander.CommandProc-- = BEGIN cls: IO.STREAM _ IO.RIS[cmd.commandLine]; toke: ROPE _ NIL; cmd.propertyList _ CommandTool.RemoveProcFromList[aList: cmd.propertyList, listKey: $After, proc: changePromptHandle]; cmd.propertyList _ CommandTool.AddProcToList[listKey: $After, proc: changePromptHandle, aList: cmd.propertyList]; toke _ cls.GetTokenRope[IO.IDProc !IO.Error, IO.EndOfStream => CONTINUE].token; IF toke = NIL THEN NULL ELSE IF toke.Equal["on", FALSE] THEN enabled _ TRUE ELSE IF toke.Equal["off", FALSE] THEN enabled _ FALSE ELSE RETURN [$Failure, "Usage: Promptery [on|off]"]; END; theGoddamCompilerDefaultsToRefTextInsteadOfROPE: ROPE _ "%l%% %l"; ChangePrompt: PROC [cmd: Commander.Handle] RETURNS [result: REF _ NIL, msg: Rope.ROPE _ NIL] --Commander.CommandProc-- = BEGIN min, max: CARDINAL; prompt, userName, time, wdir: ROPE; spot: REAL; IF NOT enabled THEN { cmd.propertyList _ List.PutAssoc[key: $Prompt, val: theGoddamCompilerDefaultsToRefTextInsteadOfROPE, aList: cmd.propertyList]; cmd.propertyList _ CommandTool.RemoveProcFromList[aList: cmd.propertyList, listKey: $After, proc: changePromptHandle]; RETURN; }; IF prompts.length = 0 THEN BEGIN cmd.out.PutF["%lNo prompts! (UserProfile entry Promptery.Sources lists only bad filenames)%l\n", IO.rope["bi"], IO.rope["BI"]]; RETURN; END; spot _ prompts.totalWeight*rs.ChooseInt[min: 0, max: 1000000000]/1000000000.0; min _ 0; max _ prompts.length - 1; WHILE max > min DO mid: CARDINAL _ (min+max)/2; IF prompts[mid].sumWeight >= spot THEN max _ mid ELSE min _ mid + 1; ENDLOOP; prompt _ prompts[min].rope; userName _ UserCredentials.Get[].name; time _ Convert.RopeFromTime[from: BasicTime.Now[], end: seconds]; wdir _ NARROW[List.Assoc[key: $WorkingDirectory, aList: ProcessProps.GetPropList[]]]; prompt _ Subst[prompt, "", machineName]; prompt _ Subst[prompt, "", userName]; prompt _ Subst[prompt, "