DIRECTORY Atom USING [GetPName], Commander USING [CommandProc, Handle, Lookup, Register], CommandExtras USING [MakeUninterpreted], CommandTool USING [DoCommand], Convert USING [RopeFromInt], EditedStream USING [UnAppendBufferChars], FileNames USING [GetShortName], IO USING [BreakProc, Close, EndOf, EndOfStream, Error, GetRefAny, GetToken, IDProc, PeekChar, RIS, SkipWhitespace, STREAM, TokenProc], List USING [Assoc], MBQueue USING [CreateMenuEntry], Menus USING [AppendMenuEntry, ClickProc, FindEntry, Menu, MenuEntry, ReplaceMenuEntry], ReadEvalPrint USING [Handle], Rope USING [Cat, Concat, Equal, Find, FromChar, FromRefText, Length, Match, Replace, ROPE, SkipTo, Substr], RopeList USING [Reverse], TiogaOps USING [GetSelection, Location, LocOffset, Ref, Root], ViewerClasses USING [Viewer], ViewerIOExtras USING [GetBuffer, TypeChars], ViewerOps USING [PaintViewer], ViewerTools USING [GetSelectionContents, SetSelection]; CommandsCImpl: CEDAR PROGRAM IMPORTS Atom, Commander, CommandExtras, CommandTool, Convert, EditedStream, FileNames, List, MBQueue, Menus, IO, Rope, RopeList, TiogaOps, ViewerIOExtras, ViewerOps, ViewerTools = BEGIN AliasCellObject: TYPE = RECORD [ args: LIST OF Rope.ROPE _ NIL, def: Rope.ROPE ]; AliasCell: TYPE = REF AliasCellObject; Alias: Commander.CommandProc = TRUSTED { commandLineStream: IO.STREAM = IO.RIS[cmd.commandLine]; name, def: Rope.ROPE; token: REF TEXT _ NEW[TEXT[30]]; args: LIST OF Rope.ROPE _ NIL; aliasCell: AliasCell; { ENABLE { IO.EndOfStream => GOTO Die; IO.Error => GOTO Die; }; token.length _ 0; token _ commandLineStream.GetToken[IO.TokenProc, token].token; name _ Rope.FromRefText[token]; [] _ commandLineStream.SkipWhitespace[FALSE]; IF NOT commandLineStream.EndOf[] AND commandLineStream.PeekChar[] = '( THEN { FOR l: LIST OF REF ANY _ NARROW[commandLineStream.GetRefAny[]], l.rest UNTIL l = NIL DO WITH l.first SELECT FROM r: Rope.ROPE => args _ CONS[r, args]; a: ATOM => args _ CONS[Atom.GetPName[a], args]; ENDCASE => ERROR; ENDLOOP; TRUSTED {args _ RopeList.Reverse[args]; }; }; token.length _ 0; token _ commandLineStream.GetToken[CRBreak, token].token; def _ Rope.FromRefText[token]; aliasCell _ NEW[AliasCellObject _ [args, def]]; Commander.Register[ key: name, proc: AliasImplProc, doc: Rope.Concat["Alias ", cmd.commandLine], clientData: aliasCell]; commandLineStream.Close[]; EXITS Die => NULL; }; }; RopeSubst: PROC [old, new, base: Rope.ROPE, case: BOOL _ FALSE, allOccurrences: BOOL _ TRUE] RETURNS[Rope.ROPE] = { lenOld: INT = old.Length[]; lenNew: INT = new.Length[]; i: INT _ 0; WHILE (i _ Rope.Find[s1: base, s2: old, case: case, pos1: i]) # -1 DO base _ Rope.Replace[base: base, start: i, len: lenOld, with: new]; IF ~allOccurrences THEN EXIT; i _ i + lenNew; ENDLOOP; RETURN[base]; }; RopeMemb: PROC [rope: Rope.ROPE, lst: LIST OF Rope.ROPE] RETURNS[BOOL] = { FOR l: LIST OF Rope.ROPE _ lst, l.rest UNTIL l = NIL DO IF Rope.Equal[rope, l.first, FALSE] THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE] }; gennum: LONG CARDINAL _ 10000; UniqueRope: PROC [c: CHARACTER _ 'A] RETURNS[Rope.ROPE] = { gennum _ gennum + 1; RETURN[Rope.Concat[Rope.FromChar[c], Convert.RopeFromInt[gennum, 10, FALSE]]]; }; -- of Gensym AliasImplProc: Commander.CommandProc = TRUSTED { aliasCell: AliasCell _ NARROW[cmd.procData.clientData]; newCommandLine: Rope.ROPE _ aliasCell.def; token: REF TEXT _ NEW[TEXT[30]]; new: Rope.ROPE; restOfStream: Rope.ROPE; commandLineStream: IO.STREAM = IO.RIS[cmd.commandLine]; synonyms: LIST OF REF SynonymRecord; SynonymRecord: TYPE = RECORD[key, val: Rope.ROPE]; FOR l: LIST OF Rope.ROPE _ aliasCell.args, l.rest UNTIL l = NIL DO token.length _ 0; token _ commandLineStream.GetToken[IO.IDProc, token].token; new _ Rope.FromRefText[token]; IF RopeMemb[new, l.rest] THEN { -- e.g. args are (x y) and substituting y gorp. dummy: Rope.ROPE = UniqueRope[]; synonyms _ CONS[NEW[SynonymRecord _ [new, dummy]], synonyms]; new _ dummy; }; newCommandLine _ RopeSubst[old: l.first, new: new, base: newCommandLine, case: FALSE]; ENDLOOP; FOR l: LIST OF REF SynonymRecord _ synonyms, l.rest UNTIL l = NIL DO newCommandLine _ RopeSubst[old: l.first.val, new: l.first.key, base: newCommandLine, case: FALSE]; ENDLOOP; token.length _ 0; token _ commandLineStream.GetToken[CRBreak, token].token; restOfStream _ Rope.FromRefText[token]; newCommandLine _ Rope.Cat[newCommandLine, restOfStream, "\n"]; commandLineStream.Close[]; result _ CommandTool.DoCommand[commandLine: newCommandLine, parent: cmd]; }; CRBreak: IO.BreakProc = { IF char = '\n THEN RETURN[break]; RETURN[other]; }; CreateButton: Commander.CommandProc = TRUSTED { commandLineStream: IO.STREAM = IO.RIS[cmd.commandLine]; name: Rope.ROPE; def: Rope.ROPE; token: REF TEXT _ NEW[TEXT[30]]; br: ButtonImplRef _ NEW[ButtonImplObject]; cth: Commander.Handle _ cmd; { ENABLE { IO.EndOfStream => GOTO Die; IO.Error => GOTO Die; }; token.length _ 0; token _ commandLineStream.GetToken[IO.TokenProc, token].token; name _ Rope.FromRefText[token]; [] _ commandLineStream.SkipWhitespace[FALSE]; token.length _ 0; token _ commandLineStream.GetToken[CRBreak, token ! IO.EndOfStream => CONTINUE].token; def _ Rope.FromRefText[token]; SELECT TRUE FROM Rope.Length[def] = 0 => def _ NIL; Rope.Match["*\n", def] => {}; ENDCASE => def _ Rope.Concat[def, "\n"]; br.def _ def; DO br.rep _ NARROW[List.Assoc[key: $ReadEvalPrintHandle, aList: cth.propertyList]]; IF br.rep # NIL AND br.rep.viewer # NIL THEN EXIT; cth _ NARROW[List.Assoc[key: $ParentCommander, aList: cth.propertyList]]; IF cth = NIL THEN RETURN[$Failure, "Can't find $ReadEvalPrintHandle"]; ENDLOOP; IF br # NIL AND br.rep # NIL THEN { viewer: ViewerClasses.Viewer _ br.rep.viewer; IF viewer # NIL THEN { menu: Menus.Menu _ br.rep.viewer.menu; IF menu # NIL THEN { new: Menus.MenuEntry _ IF def = NIL THEN NIL ELSE MBQueue.CreateMenuEntry[q: br.rep.menuHitQueue, name: name, proc: ButtonImplButtonProc, clientData: br]; old: Menus.MenuEntry _ Menus.FindEntry[menu, name]; SELECT TRUE FROM old # NIL => Menus.ReplaceMenuEntry[menu, old, new]; new # NIL => Menus.AppendMenuEntry[menu, new, 0]; ENDCASE; ViewerOps.PaintViewer[viewer: viewer, hint: menu, clearClient: FALSE]; }; }; }; EXITS Die => NULL; }; commandLineStream.Close[]; }; ButtonImplButtonProc: Menus.ClickProc = { br: ButtonImplRef _ NARROW[clientData]; def: Rope.ROPE; curSel: Rope.ROPE; viewer: ViewerClasses.Viewer _ NIL; start: TiogaOps.Location; viewerName: Rope.ROPE _ NIL; fileName: Rope.ROPE _ NIL; shortFileName: Rope.ROPE _ NIL; index: INT _ -1; pos: INT; controlRope: Rope.ROPE _ IF control THEN "control" ELSE "noControl"; shiftRope: Rope.ROPE _ IF shift THEN "shift" ELSE "noShift"; buttonRope: Rope.ROPE; SELECT mouseButton FROM red => buttonRope _ "red"; yellow => buttonRope _ "middle"; blue => buttonRope _ "right"; ENDCASE => ERROR; IF br = NIL THEN RETURN; def _ br.def; [viewer: viewer, start: start] _ TiogaOps.GetSelection[primary]; curSel _ ViewerTools.GetSelectionContents[]; IF viewer # NIL AND NOT viewer.destroyed AND NOT viewer.newFile THEN { root: TiogaOps.Ref _ TiogaOps.Root[start.node]; offset: INT _ TiogaOps.LocOffset[loc1: [root, 0], loc2: start, skipCommentNodes: TRUE]; index _ offset; viewerName _ viewer.name; }; pos _ curSel.Find["\n"]; IF pos # -1 THEN curSel _ Rope.Substr[base: curSel, start: 0, len: pos]; fileName _ IF (Rope.SkipTo[s: curSel, pos: 0, skip: " "] = curSel.Length[]) AND (curSel.Length[] > 1) THEN curSel ELSE viewerName; shortFileName _ FileNames.GetShortName[path: fileName, stripOffVersionNumber: TRUE]; def _ RopeSubst[ old: "$CurrentSelection$", new: curSel, base: def, case: TRUE]; def _ RopeSubst[ old: "$FileNameSelection$", new: fileName, base: def, case: TRUE]; def _ RopeSubst[ old: "$ShortFileNameSelection$", new: shortFileName, base: def, case: TRUE]; def _ RopeSubst[ old: "$SelectedViewerName$", new: viewerName, base: def, case: TRUE]; def _ RopeSubst[ old: "$ViewerPosition$", new: Convert.RopeFromInt[index, 10, FALSE], base: def, case: TRUE]; def _ RopeSubst[ old: "$MouseButton$", new: buttonRope, base: def, case: TRUE]; def _ RopeSubst[ old: "$ControlKey$", new: controlRope, base: def, case: TRUE]; def _ RopeSubst[ old: "$ShiftKey$", new: shiftRope, base: def, case: TRUE]; { bufferContents: REF TEXT _ ViewerIOExtras.GetBuffer[br.rep.in]; IF bufferContents # NIL AND bufferContents.length > 0 AND bufferContents[bufferContents.length - 1] # '\n THEN { FOR n: NAT DECREASING IN [0..bufferContents.length) DO IF bufferContents[n] = '\n THEN { EditedStream.UnAppendBufferChars[ stream: br.rep.in, nChars: bufferContents.length - n - 1]; EXIT; } REPEAT FINISHED => EditedStream.UnAppendBufferChars[stream: br.rep.in, nChars: LAST[NAT]]; ENDLOOP; }; }; IF viewer = br.rep.viewer THEN ViewerTools.SetSelection[viewer: viewer, selection: NIL]; ViewerIOExtras.TypeChars[editedViewerStream: br.rep.in, chars: def]; }; ButtonImplRef: TYPE = REF ButtonImplObject; ButtonImplObject: TYPE = RECORD [ rep: ReadEvalPrint.Handle _ NIL, def: Rope.ROPE _ NIL ]; Init: PROC = { Commander.Register[key: "///Commands/Alias", proc: Alias, doc: "Create an alias for a command"]; Commander.Register[key: "///Commands/CreateButton", proc: CreateButton, doc: "Create a CommandTool herald button"]; CommandExtras.MakeUninterpreted[Commander.Lookup["///Commands/CreateButton"]]; Commander.Register[key: "///Commands/RemoveButton", proc: CreateButton, doc: "Remove a CommandTool herald button"]; }; Init[]; END. ψCommandsCImpl.mesa Copyright c 1984 by Xerox Corporation. All rights reserved. L. Stewart, January 17, 1984 11:08 am Russ Atkinson, January 28, 1985 7:31:23 pm PST if old is not found in base, then value = base. if allOccurrences THEN substitute for each occurrence of old, otherwise only for first. The first token willl be the name of the button. The rest of the commandLine will be the thing to stuff. A special character sequence, $$, will stand for the current selection. Get the rest of it! Search up chain of parents to find a ReadEvalPrint.Handle and the associated commander Various cases: (1) if there is no old entry, and there is a new definition, then create a new entry, (2) if there is an old entry and a new definition, replace the old entry, (3) if there is an old entry and no new definition, remove the old one, otherwise no action. There are specialized tokens: $CurrentSelection$ => replaced by the current selection up to but not including the first carriage return $FileNameSelection$ => replaced by the current selection if it appears to be a file name, otherwise replaced by the name of the selected viewer $ShortFileNameSelection$ => same as $FileNameSelection$ except that version number and directory are omitted $SelectedViewerName$ => replaced by the name of the selected viewer $ViewerPosition$ => replaced by the position of the current selection in a viewer $MouseButton$ => "left", "middle", or "right" $ShiftKey$ => "shift", "noShift" $ControlKey$ "control", "noControl" Get prefix of current selection before the first CR The curSel is the fileName if curSel is longer than one character and contains no whitespace. If the selected viewer is the commandtool, then set the caret to the end, or the ViewerIOExtras.TypeChars won't work. Κ ς˜šœ™Jšœ Οmœ1™Kšœžœ ˜Kšœžœ˜,Kšœ žœ˜Kšœ žœ&˜7—J˜šœžœž˜KšžœfžœB˜±Kšœž˜J˜šœžœžœ˜ Jš œžœžœžœžœ˜Jšœ ž˜J˜—J˜Jšœ žœžœ˜&J˜—šœžœ˜(Jš œžœžœžœžœ˜7Jšœžœ˜Jš œžœžœžœžœ˜ Jš œžœžœžœžœ˜J˜˜šžœ˜Jšžœžœ˜Jšžœ žœ˜J˜—J˜Jšœ#žœ˜>Jšœ˜Jšœ&žœ˜-šžœžœžœ#žœ˜Mšžœžœžœžœžœžœ(žœžœž˜Xšžœ žœž˜Kšœžœ žœ ˜%Kšœžœ žœ˜/Kšžœžœ˜—Kšžœ˜—Kšžœ#˜*K˜—J˜Jšœ9˜9Jšœ˜Jšœ žœ ˜/šœ˜Kšœ ˜ Kšœ˜Kšœ-˜-Kšœ˜—Jšœ˜šž˜Jšœžœ˜ —J˜—J˜—J˜šΟn œžœžœžœžœžœžœžœžœ˜sšœ/™/KšœW™W—Kšœžœ˜Kšœžœ˜Kšœžœ˜ šžœ>ž˜EKšœB˜BKšžœžœžœ˜K˜Kšžœ˜—Kšžœ˜ K˜—J˜šŸœžœ žœžœžœžœžœžœ˜Jš žœžœžœžœžœžœž˜7Jš žœžœžœžœžœ˜6Jšžœ˜—Jšžœžœ˜ J˜—J˜Jšœ žœžœ ˜J˜š Ÿ œžœž œžœžœ˜;J˜Jšžœ?žœ˜NJšžœΟc ˜—J™šœ'žœ˜0Jšœžœ˜7Jšœžœ˜*Jš œžœžœžœžœ˜ Jšœ žœ˜Jšœžœ˜Jš œžœžœžœžœ˜7Jšœ žœžœžœ˜$Jšœžœžœžœ˜2J˜š žœžœžœžœžœžœž˜BJ˜Jšœ#žœ˜;Jšœ˜šžœžœ /˜PJšœ žœ˜ Jšœ žœžœ*˜=J˜ J˜—JšœOžœ˜WJšžœ˜—š žœžœžœžœ"žœžœž˜DJšœ[žœ˜cJšžœ˜—J˜Jšœ9˜9Jšœ'˜'Jšœ>˜>Jšœ˜JšœI˜IJ˜—J˜šœ žœ˜Jšžœ žœžœ˜!Jšžœ˜J˜—J˜šœ&žœ˜/K™²Kš œžœžœžœžœ˜7Kšœ žœ˜Kšœ žœ˜Kš œžœžœžœžœ˜ Kšœžœ˜*K˜˜šžœ˜Kšžœžœ˜Kšžœ žœ˜K˜—K˜Kšœ#žœ˜>Kšœ˜Kšœ&žœ˜-K™K˜Kšœ4žœžœ˜VKšœ˜šžœžœž˜Kšœžœ˜"Kšœ˜Kšžœ!˜(—K˜ K˜KšœV™Všž˜Kšœ žœA˜PKš žœ žœžœžœžœžœ˜2Kšœžœ=˜IKšžœžœžœžœ.˜FKšžœ˜K˜—Kšœ‹™‹š žœžœžœ žœžœ˜#Kšœ-˜-šžœ žœžœ˜Kšœ&˜&šžœžœžœ˜Kš œžœžœžœžœžœi˜šKšœ3˜3šžœžœž˜Kšœžœ+˜4Kšœžœ(˜1Kšžœ˜—Kšœ?žœ˜FK˜—K˜—K˜—šž˜Kšœžœ˜ —K˜—Kšœ˜K˜—J™J˜™J™jJ™J™lJ™CJ™QJ™-J™ J™#—šœ)˜)Jšœžœ ˜'Jšœ žœ˜Jšœ žœ˜Jšœžœ˜#Jšœ˜Jšœžœžœ˜Jšœžœžœ˜Jšœžœžœ˜Jšœžœ˜Jšœžœ˜ Jš œžœžœ žœ žœ ˜DJš œžœžœžœ žœ ˜—šœ˜Kšœ8žœ˜>—šœ˜Kšœ4žœ˜:—˜Jšœžœžœ'˜?š žœžœžœžœ1žœ˜pš žœžœž œžœž˜6šžœžœ˜!šœ!˜!Kšœ:˜:—Jšžœ˜J˜—Jšž˜Jšžœ@žœžœ˜SJšžœ˜—J˜—J˜—Jšœu™uJšžœžœ5žœ˜XJšœD˜DJ˜—J˜Jšœžœžœ˜+J˜šœžœžœ˜!Jšœžœ˜ Jšœ žœž˜J˜—J˜šŸœžœ˜Kšœ`˜`Kšœs˜sKšœN˜NKšœs˜sJ˜—J˜J˜J˜Jšžœ˜J˜—…—$ΰ7Κ