<> <> <> <> <> <> <> <<>> DIRECTORY AMTypes USING [TV, TVToType, TVType, Type, UnderClass], Interpreter USING [Evaluate], IO USING [BreakProc, GetCedarTokenRope, RIS, RopeFromROS, ROS, STREAM, TokenProc], MessageWindow USING [Append, Blink, Clear], PrintTV USING [PrintType], Process USING [Detach], Rope USING [Cat, Concat, Fetch, Find, FromChar, Length, Replace, ROPE, Run, Substr], TiogaOps USING [BackSpace, Break, CallWithLocks, ClearLooks, FirstChild, GetCaret, GetRope, GetSelection, GoToPreviousCharacter, InsertRope, IsComment, Location, Nest, Next, NextPlaceholder, PutProp, PutTextKey, Ref, RegisterAbbrevFailedProc, SaveSelA, SetComment, SetLooks, SetNotComment, SetSelection, ViewerDoc], TiogaOpsDefs USING [Ref], ViewerClasses USING [Viewer], WindowManager USING [UnWaitCursor, WaitCursor]; EditorComfortsBImpl: CEDAR PROGRAM IMPORTS AMTypes, Interpreter, IO, MessageWindow, PrintTV, Process, Rope, TiogaOps, WindowManager = BEGIN <> <<>> Location: TYPE = TiogaOps.Location; ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; TiogaRef: TYPE = TiogaOpsDefs.Ref; TV: TYPE = AMTypes.TV; Viewer: TYPE = ViewerClasses.Viewer; <> <<>> Expand: PROC RETURNS [BOOL] = { caret: Location _ TiogaOps.GetCaret[]; r: ROPE _ TiogaOps.GetRope[caret.node]; i: INT _ caret.where; WHILE i >= 0 DO IF i=0 OR (IO.TokenProc[Rope.Fetch[r, i - 1]] # other) THEN TRUSTED { <> Process.Detach[FORK Expand0[Rope.Substr[base: r, start: i, len: caret.where - i], caret]]; RETURN [TRUE]; }; i _ i -1; ENDLOOP; RETURN [FALSE]; }; Expand0: PROC [name: ROPE, caret: Location] = { Expand1: PROC [root: REF] = { IF newName # NIL THEN { TiogaOps.BackSpace[Rope.Length[name]]; TiogaOps.InsertRope[newName]; caret _ TiogaOps.GetCaret[]; }; TiogaOps.SaveSelA[]; TiogaOps.PutProp[n: caret.node, name: $StartOfExpansion, value: expansion]; TiogaOps.PutTextKey[node: caret.node, where: caret.where - 1, key: expansion]; <> IF Rope.Run[s1: expansion, s2: " -- "] = 4 THEN { expansion _ Rope.Substr[expansion, 4]; TiogaOps.ClearLooks[which: caret]; TiogaOps.InsertRope[" = {"]; TiogaOps.Break[]; TiogaOps.Nest[]; TiogaOps.SetComment[]; TiogaOps.SetLooks[looks: "ck", which: caret]; TiogaOps.InsertRope[expansion]; TiogaOps.ClearLooks[which: caret]; TiogaOps.Break[]; TiogaOps.SetNotComment[]; TiogaOps.InsertRope["Body"]; TiogaOps.Break[]; TiogaOps.InsertRope["};"]; [] _ TiogaOps.NextPlaceholder[dir: backwards, gotoend: FALSE]; } ELSE { TiogaOps.InsertRope[expansion]; TiogaOps.GoToPreviousCharacter[Rope.Length[expansion]]; [] _ TiogaOps.NextPlaceholder[gotoend: FALSE]; }; }; viewer: Viewer _ TiogaOps.GetSelection[].viewer; expansion, newName: ROPE; IF viewer = NIL THEN RETURN; IF Rope.Find[name, "."] = -1 THEN { <> n: TiogaRef _ TiogaOps.FirstChild[TiogaOps.ViewerDoc[viewer]]; WHILE n # NIL DO r: ROPE = TiogaOps.GetRope[n]; IF NOT TiogaOps.IsComment[n] AND (Rope.Find[r, "PROGRAM"] # -1 OR Rope.Find[r, "MONITOR"] # -1) THEN { name _ Rope.Cat[IO.GetCedarTokenRope[IO.RIS[r]].token, ".", name]; EXIT }; n _ TiogaOps.Next[n]; ENDLOOP; }; MessageWindow.Append[message: Rope.Cat["Evaluating ", name, "..."], clearFirst: TRUE]; WindowManager.WaitCursor[]; [expansion, newName] _ ExpandRecord[name, viewer ! UNWIND => WindowManager.UnWaitCursor[]]; WindowManager.UnWaitCursor[]; IF viewer = TiogaOps.GetSelection[].viewer THEN { IF TiogaOps.GetCaret[] # caret THEN { MessageWindow.Append["Caret has moved, insertion NOT performed.", TRUE]; MessageWindow.Blink[]; RETURN; }; } ELSE TiogaOps.SetSelection[viewer: viewer, start: caret, end: caret]; <> MessageWindow.Clear[]; IF expansion # NIL THEN IF useLocks THEN TiogaOps.CallWithLocks[proc: Expand1] ELSE Expand1[NIL]; }; ExpandRecord: PROC [name: ROPE, viewer: Viewer] RETURNS [expansion: ROPE, newName: ROPE] = { h: STREAM = IO.ROS[]; i: INT; tv: TV; errorRope: ROPE; noResult: BOOL; type: AMTypes.Type; [tv, errorRope, noResult] _ Interpreter.Evaluate[rope: name]; -- Abort? IF noResult THEN { MessageWindow.Append[errorRope, TRUE]; MessageWindow.Blink[]; GOTO Fail}; type _ AMTypes.TVType[tv]; SELECT AMTypes.UnderClass[type] FROM type => { PrintTV.PrintType[type: AMTypes.TVToType[tv], put: h, width: printWidth, verbose: TRUE]; <> expansion _ h.RopeFromROS[]; i _ Rope.Find[expansion, "["]; IF i = -1 THEN expansion _ NIL ELSE expansion _ Rope.Concat[" -- ", Rope.Substr[base: expansion, start: i]]; RETURN; }; procedure, signal, error, record => { Expand1: PROC [args: ROPE] RETURNS [expansion: ROPE _ NIL] = { left: ROPE = Rope.FromChar['\001]; right: ROPE = Rope.FromChar['\002]; i, length: INT; i _ 1; expansion _ args; length _ Rope.Length[expansion]; DO <> n: INT _ -1; -- will be character position of : j: INT _ i; -- will be position of the first character beyond this argument, i.e. the , or ] WHILE j < length DO SELECT Rope.Fetch[expansion, j] FROM '', '\\ => j _ j + 2; '], ', => EXIT; ': => n _ j; '[ => -- default value for this argument is a record constructor. find matching right ] and replace interior by its expansion {count: INT _ 1; k: INT _ j + 1; r: ROPE; nChars: INT; WHILE k < length DO SELECT Rope.Fetch[expansion, k] FROM '', '\\ => {k _ k + 2; LOOP}; '[ => count _ count + 1; '] => IF (count _ count - 1) = 0 THEN EXIT; ENDCASE; k _ k + 1; REPEAT FINISHED => GOTO Fail; -- did not find matching ] ENDLOOP; nChars _ k - j + 1; r _ Expand1[Rope.Substr[base: expansion, start: j, len: nChars]]; expansion _ Rope.Replace[base: expansion, start: j, len: nChars, with: r]; length _ Rope.Length[expansion]; j _ k + (Rope.Length[r] - nChars); }; ENDCASE; j _ j + 1; ENDLOOP; IF n = -1 OR j >= length THEN GOTO Fail; expansion _ Rope.Replace[base: expansion, start: j, len: 0, with: right]; <> expansion _ Rope.Replace[base: expansion, start: n + 2, len: 0, with: left]; <<+ 2 to skip over the : and the space.>> length _ length + 2; i _ j + 3; IF i = length THEN EXIT; ENDLOOP; EXITS Fail => expansion _ args; }; PrintTV.PrintType[type: type, put: h, width: printWidth, verbose: TRUE]; expansion _ h.RopeFromROS[]; IF (i _ Rope.Find[expansion, "RETURNS"]) # -1 THEN expansion _ Rope.Substr[base: expansion, len: i - 1]; <> i _ Rope.Find[expansion, "["]; IF i = -1 THEN {expansion _ "[]"; RETURN}; expansion _ Rope.Substr[expansion, i]; <> expansion _ Expand1[expansion]; }; ENDCASE => GO TO Fail; EXITS Fail => expansion _ NIL; }; printWidth: INT _ 250; <> <<>> useLocks: BOOL _ TRUE; TiogaOps.RegisterAbbrevFailedProc[Expand]; END.