DIRECTORY Convert USING [AppendInt], EditSpan USING [AddLooks, ChangeLooks, noLooks, RemoveLooks], EditSpanSupport USING [Apply], IO USING [GetCedarToken, GetIndex, RIS, SetIndex, STREAM, TokenKind], MessageWindow USING [Append], NodeAddrs USING [GetTextAddr, PutTextAddr, RemTextAddr], NodeProps USING [true], RefText USING [AppendRope, Equal, New], Rope USING [Equal, FromRefText, ROPE, Size, Substr], RopeEdit USING [AlphaNumericChar, BlankChar], RopeReader USING [Create, Get, GetIndex, Peek, PeekBackwards, ReadOffEnd, Ref, SetPosition], TEditDocument USING [Selection], TEditInput USING [CommandProc, currentEvent, Register], TEditInputOps USING [CallWithLocks], TEditLocks USING [Lock, Unlock], TEditMesaOps USING [], TEditSelection USING [MakeSelection, pSel, SetSelLooks], TextEdit USING [DeleteText, PutProp], TextLooks USING [Looks, noLooks], TextNode USING [EndPos, Location, MaxLen, NodeItself, Offset, Ref, RefTextNode, Root, Span], UndoEvent USING [Ref]; TEditMesaOpsImpl: CEDAR PROGRAM IMPORTS Convert, EditSpan, EditSpanSupport, IO, MessageWindow, NodeAddrs, NodeProps, RefText, Rope, RopeEdit, RopeReader, TEditInput, TEditInputOps, TEditLocks, TEditSelection, TextEdit, TextNode EXPORTS TEditMesaOps = BEGIN ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; SetSpanMesaLooks: PUBLIC PROC [span: TextNode.Span, event: UndoEvent.Ref] RETURNS [procs, comments, keywords: INT] = { root: TextNode.Ref = TextNode.Root[span.start.node]; rdr: RopeReader.Ref _ RopeReader.Create[]; skipComments: BOOL = span.start.node # span.end.node; SetMesaLooks: PROC [node: TextNode.RefTextNode, start, len: TextNode.Offset] RETURNS [stop: BOOL] = { p, c, k: INT; IF node.comment AND skipComments THEN { p _ c _ k _ 0; stop _ FALSE } ELSE [stop,p,c,k] _ DoIt[node, start, len, rdr, event]; procs _ procs+p; comments _ comments+c; keywords _ keywords+k }; procs _ comments _ keywords _ 0; [] _ TEditLocks.Lock[root, "SetSpanMesaLooks"]; EditSpanSupport.Apply[span,SetMesaLooks]; TEditLocks.Unlock[root]; }; namifyTypes: BOOL _ FALSE; DoIt: PROC [node: TextNode.RefTextNode, start, len: TextNode.Offset, rdr: RopeReader.Ref, event: UndoEvent.Ref] RETURNS [stop: BOOL _ FALSE, procs, comments, keywords: INT _ 0] = { root: TextNode.Ref = TextNode.Root[node]; pStart, pLen: TextNode.Offset _ 0; lastChar: CHAR _ '\000; token: REF TEXT _ RefText.New[40]; Match: PROC [a: REF READONLY TEXT] RETURNS [BOOL] ~ INLINE { RETURN [a.length=token.length AND RefText.Equal[a, token]] }; tokenKind: IO.TokenKind _ tokenERROR; CheckID: PROC RETURNS [alpha, allcaps: BOOL _ TRUE] = { IF token = NIL THEN RETURN [FALSE, FALSE]; IF token.length = 1 THEN allcaps _ FALSE; FOR index: NAT IN [0..token.length) DO lastChar _ token[index]; IF lastChar > 'Z OR lastChar < 'A THEN allcaps _ FALSE; IF NOT RopeEdit.AlphaNumericChar[lastChar] THEN alpha _ FALSE; ENDLOOP; }; allComments: BOOL _ TRUE; nameLooks: TextLooks.Looks _ TextLooks.noLooks; mesaLooks: TextLooks.Looks _ TextLooks.noLooks; stream: STREAM _ NIL; size: INT ~ Rope.Size[node.rope]; first: INT ~ MIN[start, size]; length: INT ~ MIN[len, size-start]; end: INT ~ start+length; state: {null, procName, procNameColon, procNameDef} _ null; stream _ IO.RIS[node.rope.Substr[0, end]]; IO.SetIndex[stream, first]; mesaLooks['k] _ mesaLooks['c] _ mesaLooks['n] _ TRUE; nameLooks['n] _ TRUE; IF end > first THEN EditSpan.RemoveLooks[root, [[node, first], [node, end-1]], mesaLooks, event]; UNTIL tokenKind = tokenEOF DO add, alpha, allcaps: BOOL _ FALSE; addLooks, remLooks: TextLooks.Looks _ TextLooks.noLooks; tokStart, tokLen: INT _ 0; [tokenKind, token] _ IO.GetCedarToken[stream, token, FALSE]; tokLen _ token.length; tokStart _ IO.GetIndex[stream]-tokLen; remLooks _ mesaLooks; SELECT tokenKind FROM tokenEOF => NULL; tokenCOMMENT => { add _ TRUE; addLooks['c] _ TRUE; remLooks['c] _ FALSE; comments _ comments+1; }; tokenID => { allComments _ FALSE; [alpha, allcaps] _ CheckID[]; SELECT TRUE FROM allcaps => { add _ TRUE; addLooks['k] _ TRUE; remLooks['k] _ FALSE; keywords _ keywords+1; IF NOT namifyTypes AND Match["TYPE"] THEN state _ null; IF Match["PUBLIC"] OR Match["PRIVATE"] THEN NULL ELSE {state _ IF state = procNameColon THEN procNameDef ELSE null}; }; alpha AND token[0] IN ['A..'Z] AND state = null => { pStart _ tokStart; pLen _ tokLen; state _ procName; }; alpha => {state _ IF state = procNameColon AND token[0] IN ['A..'Z] THEN procNameDef ELSE null} ENDCASE; }; tokenSINGLE => { allComments _ FALSE; state _ SELECT token[0] FROM ': => SELECT state FROM procName => procNameColon ENDCASE => null, ENDCASE => null; }; ENDCASE => {allComments _ FALSE; state _ null}; IF add THEN { EditSpan.ChangeLooks[root, [[node,tokStart], [node,tokStart+tokLen-1]], remLooks, addLooks, event]; add _ FALSE; addLooks _ TextLooks.noLooks; remLooks _ mesaLooks; }; IF state = procNameDef THEN { state _ null; IF pLen > 0 THEN { procs _ procs+1; EditSpan.AddLooks[root, [[node, pStart], [node, pStart+pLen-1]], nameLooks, event] }; pLen _ 0; }; ENDLOOP; IF first=0 AND end = size THEN { isComment: BOOL _ allComments AND comments > 0; IF isComment AND NOT node.comment THEN { -- change it NextCharIsBlank: PROC RETURNS [blank: BOOL] = { blank _ RopeEdit.BlankChar[RopeReader.Peek[rdr ! RopeReader.ReadOffEnd => { blank _ FALSE; CONTINUE }]] }; commentLooks: TextLooks.Looks _ TextLooks.noLooks; commentLooks['c] _ TRUE; RopeReader.SetPosition[rdr,node.rope,0]; WHILE RopeEdit.BlankChar[RopeReader.Get[rdr]] DO --skip blanks-- ENDLOOP; IF RopeReader.PeekBackwards[rdr] # '- THEN ERROR; IF RopeReader.Get[rdr] # '- THEN ERROR; WHILE NextCharIsBlank[] DO --skip blanks [] _ RopeReader.Get[rdr]; ENDLOOP; TextEdit.DeleteText[root, node, 0, RopeReader.GetIndex[rdr], event]; EditSpan.RemoveLooks[root, [[node, 0],[node, TextNode.MaxLen]], commentLooks, event]; TextEdit.PutProp[node, $Comment, NodeProps.true, event]; }; }; }; SetMesaLooksOp: PUBLIC TEditInput.CommandProc = { procs, comments, keywords: INT _ 0; msg: REF TEXT _ NEW[TEXT[40]]; Append: PROC [value: INT, what: ROPE, dlm: ROPE] ~ { msg _ Convert.AppendInt[msg, value]; msg _ RefText.AppendRope[msg, what]; IF value # 1 THEN msg _ RefText.AppendRope[msg, "s"]; msg _ RefText.AppendRope[msg, dlm]; }; DoSet: PROC [root: TextNode.Ref, tSel: TEditDocument.Selection] = { span: TextNode.Span _ [tSel.start.pos, tSel.end.pos]; firstText: TextNode.RefTextNode ~ tSel.start.pos.node; lastText: TextNode.RefTextNode ~ tSel.end.pos.node; IF firstText # NIL THEN NodeAddrs.PutTextAddr[firstText, $Start, tSel.start.pos.where]; IF lastText # NIL THEN NodeAddrs.PutTextAddr[lastText, $End, tSel.end.pos.where+1]; IF tSel.granularity=point OR (tSel.granularity=char AND tSel.start.pos=tSel.end.pos) THEN { span.start.where _ 0; span.end.where _ TextNode.EndPos[span.end.node] }; [procs, comments, keywords] _ SetSpanMesaLooks[span, TEditInput.currentEvent]; tSel.start.pos _ [firstText, IF firstText=NIL THEN TextNode.NodeItself ELSE NodeAddrs.GetTextAddr[firstText,$Start].location]; tSel.end.pos _ [lastText, IF lastText=NIL THEN TextNode.NodeItself ELSE MAX[NodeAddrs.GetTextAddr[lastText, $End].location, 1] - 1 ]; IF firstText#NIL THEN NodeAddrs.RemTextAddr[firstText, $Start]; IF lastText#NIL THEN NodeAddrs.RemTextAddr[lastText, $End]; TEditSelection.MakeSelection[new: tSel]; TEditSelection.SetSelLooks[TEditSelection.pSel]; }; TEditInputOps.CallWithLocks[DoSet]; Append[keywords, " keyword", ", "]; Append[comments, " comment", ", "]; Append[procs, " procedure name", "."]; MessageWindow.Append[Rope.FromRefText[msg], TRUE]; }; TEditInput.Register[$SetMesaLooks, SetMesaLooksOp, FALSE]; END. TEditMesaOpsImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Paxton on November 10, 1982 7:33 am Maxwell, January 14, 1983 9:41 am Russ Atkinson, September 27, 1983 6:42 pm Doug Wyatt, March 3, 1985 6:12:43 pm PST Michael Plass, March 25, 1986 10:04:55 am PST save positions & text since may be a proc name doing entire node; check Comment property -- scan selection looking for Mesa keywords and comments -- set the keywords look k -- set the comments look c -- set procedure names look n do the entire node Κλ˜codešœ™Kšœ<™Kšœ˜—Kšœ˜—Kšœ œœ˜K˜/K˜/Kšœœœ˜Kšœœ˜!Kšœœœ˜Kšœœœ˜#Kšœœ˜Kšœ;˜;Kšœ œœ˜*Kšœ˜Kšœ0œ˜5Kšœœ˜Kšœ œN˜ašœ˜Kšœœœ˜"K˜8Kšœœ˜Kšœœœ˜