-- TiogaMesaOpsImpl.mesa Edited by Paxton on November 10, 1982 7:33 am
Last Edited by: Maxwell, January 14, 1983 9:41 am
DIRECTORY
EditSpan,
EditSpanSupport,
IO,
CedarScanner,
MessageWindow,
NodeAddrs,
NodeProps,
Rope,
RopeEdit,
RopeReader,
TiogaDocument,
TiogaInput,
TiogaInputOps,
TiogaLocks,
TiogaMesaOps,
TiogaSelection,
TextEdit,
TiogaLooks,
TiogaLooksOps,
TiogaNode,
TiogaNodeOps,
UndoEvent;
TiogaMesaOpsImpl: CEDAR PROGRAM
IMPORTS EditSpan, EditSpanSupport, IO, CedarScanner, MessageWindow, NodeAddrs, NodeProps, Rope, RopeEdit, RopeReader, TiogaInput, TiogaInputOps, TiogaLocks, TiogaSelection, TextEdit, TiogaLooksOps, TiogaNodeOps
EXPORTS TiogaMesaOps =
BEGIN
SetSpanMesaLooks: PUBLIC PROC [span: TiogaNode.Span, event: UndoEvent.Ref] RETURNS [procs, comments, keywords: INT] = {
root: TiogaNode.RefBranchNode = TiogaNodeOps.Root[span.start.node];
rdr: RopeReader.Ref ← RopeReader.Create[];
skipComments: BOOL = span.start.node # span.end.node;
SetMesaLooks: PROC [node: TiogaNode.RefTextNode, start, len: TiogaNode.Offset]
RETURNS [stop: BOOLEAN] = {
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;
[] ← TiogaLocks.Lock[root, "SetSpanMesaLooks"];
EditSpanSupport.Apply[span,SetMesaLooks];
TiogaLocks.Unlock[root] };
DoIt: PROC [node: TiogaNode.RefTextNode, start, len: TiogaNode.Offset, rdr: RopeReader.Ref, event: UndoEvent.Ref]
RETURNS [stop: BOOLEAN, procs, comments, keywords: INT] = {
root: TiogaNode.RefBranchNode = TiogaNodeOps.Root[node];
pStart, pLen, size, i, first, end: TiogaNode.Offset ← 0;
lastChar: CHAR;
GetChar: PROC [data: REF, index: TiogaNode.Offset] RETURNS [char: CHAR] = {
OPEN RopeReader;
IF index >= end THEN { done ← TRUE; RETURN [0C] };
SetIndex[rdr,index];
char ← Get[rdr ! ReadOffEnd => { done ← TRUE; char ← 0C; CONTINUE }] };
CheckID: PROC [n: TiogaNode.RefTextNode, start, len: TiogaNode.Offset]
RETURNS [alpha, allcaps: BOOLEAN] = INLINE {
alpha ← allcaps ← TRUE;
RopeReader.SetPosition[rdr,n.rope,start];
UNTIL (len ← len-1)<0 DO
IF (lastChar ← RopeReader.Get[rdr]) NOT IN ['A..'Z] THEN allcaps ← FALSE;
IF ~RopeEdit.AlphaNumericChar[lastChar] THEN { alpha ← FALSE; EXIT };
ENDLOOP };
IsProc: PROC [n: TiogaNode.RefTextNode, start, len: TiogaNode.Offset] RETURNS [BOOLEAN] = INLINE {
IF ~(SELECT len FROM
4 => lastChar = 'C,
9 => lastChar = 'E,
ENDCASE => FALSE) THEN RETURN [FALSE]; -- quick test eliminates most
RopeReader.SetPosition[rdr,n.rope,start];
IF RopeReader.Get[rdr] # 'P THEN RETURN [FALSE];
IF RopeReader.Get[rdr] # 'R THEN RETURN [FALSE];
IF RopeReader.Get[rdr] # 'O THEN RETURN [FALSE];
IF RopeReader.Get[rdr] # 'C THEN RETURN [FALSE];
IF len = 4 THEN RETURN [TRUE];
IF len # 9 THEN RETURN [FALSE];
IF RopeReader.Get[rdr] # 'E THEN RETURN [FALSE];
IF RopeReader.Get[rdr] # 'D THEN RETURN [FALSE];
IF RopeReader.Get[rdr] # 'U THEN RETURN [FALSE];
IF RopeReader.Get[rdr] # 'R THEN RETURN [FALSE];
IF RopeReader.Get[rdr] # 'E THEN RETURN [FALSE];
RETURN [TRUE] };
done: BOOLEANFALSE;
allComments: BOOLEANTRUE;
lastLoc: TiogaNode.Location;
nameLooks: TiogaLooks.Looks ← TiogaLooks.noLooks;
mesaLooks: TiogaLooks.Looks ← TiogaLooks.noLooks;
size ← RopeEdit.Size[node.rope];
start ← MIN[start, size];
len ← MIN[len, size-start];
end ← start+len;
i ← first ← start;
stop ← FALSE;
procs ← comments ← keywords ← 0;
RopeReader.SetPosition[rdr,node.rope,start];
lastLoc ← [node,start];
mesaLooks['k] ← mesaLooks['c] ← mesaLooks['n] ← TRUE;
nameLooks['n] ← TRUE;
UNTIL done DO
add, alpha, allcaps, proc: BOOLEANFALSE;
addLooks, remLooks: TiogaLooks.Looks ← TiogaLooks.noLooks;
token: CedarScanner.Token;
TRUSTED {token ← CedarScanner.GetToken[[GetChar, rdr],i]};
i ← token.next;
start ← token.start;
len ← i-start;
remLooks ← mesaLooks;
SELECT token.kind FROM
tokenCOMMENT => {
IF ~TiogaLooksOps.FetchLooks[node.runs, start]['c] THEN {
add ← TRUE; addLooks['c] ← TRUE; remLooks['c] ← FALSE }
ELSE lastLoc.where ← start+len; -- don't change comment looks
comments ← comments+1 };
tokenID => {
allComments ← FALSE;
[alpha, allcaps] ← CheckID[node,start,len];
IF allcaps THEN {
proc ← IsProc[node,start,len];
add ← TRUE; addLooks['k] ← TRUE; remLooks['k] ← FALSE;
keywords ← keywords+1 }
ELSE IF alpha THEN { -- save since may be a proc name
pStart ← start; pLen ← len }};
ENDCASE => allComments ← FALSE;
IF add THEN {
IF lastLoc.where < start THEN
EditSpan.RemoveLooks[root,[lastLoc,[node,start-1]],mesaLooks,event];
lastLoc.where ← start+len;
EditSpan.ChangeLooks[root,[[node,start],[node,start+len-1]],remLooks,addLooks,event];
add ← FALSE;
addLooks ← TiogaLooks.noLooks;
remLooks ← mesaLooks };
IF proc THEN {
ReallyIsProc: PROC RETURNS [BOOL] = {
rope: Rope.ROPE = node.rope;
-- must start with a cap alpha
IF ~Rope.Fetch[rope,pStart] IN ['A..'Z] THEN RETURN[FALSE];
-- must be followed immediately by a colon
IF pStart+pLen >= Rope.Size[rope] THEN RETURN[FALSE];
IF Rope.Fetch[rope,pStart+pLen] # ': THEN RETURN[FALSE];
RETURN [TRUE] };
proc ← FALSE;
IF pLen > 0 AND ReallyIsProc[] THEN {
procs ← procs+1;
EditSpan.AddLooks[root,[[node,pStart],[node,pStart+pLen-1]],nameLooks,event] };
pLen ← 0 };
ENDLOOP;
IF lastLoc.where < end THEN
EditSpan.RemoveLooks[root,[lastLoc,[node,end-1]],mesaLooks,event];
IF first=0 AND done THEN { -- doing entire node; check Comment property
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: TiogaLooks.Looks ← TiogaLooks.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,TiogaNode.MaxLen]],commentLooks,event];
TextEdit.PutProp[node, "Comment", NodeProps.true, event] }};
};
SetMesaLooksOp: PUBLIC TiogaInput.CommandProc = {
-- scan selection looking for Mesa keywords and comments
-- set the keywords look k
-- set the comments look c
-- set procedure names look n
procs, comments, keywords: INT;
DoSet: PROC [root: TextEdit.Ref, tSel: TiogaDocument.Selection] = {
span: TiogaNode.Span ← [tSel.start.pos, tSel.end.pos];
selStart, selEnd: TiogaNode.Ref;
firstText, lastText: TiogaNode.RefTextNode;
IF (firstText ← TiogaNodeOps.NarrowToTextNode[selStart ← tSel.start.pos.node]) # NIL THEN
NodeAddrs.PutTextAddr[firstText,$Start,tSel.start.pos.where];
IF (lastText ← TiogaNodeOps.NarrowToTextNode[selEnd ← tSel.end.pos.node]) # 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 {
do the entire node
span.start.where ← 0;
span.end.where ← TiogaNodeOps.EndPos[TiogaNodeOps.NarrowToTextNode[span.end.node]] };
[procs, comments, keywords] ← SetSpanMesaLooks[span, TiogaInput.currentEvent];
tSel.start.pos ← [selStart,
IF firstText=NIL THEN TiogaNode.NodeItself
ELSE NodeAddrs.GetTextAddr[firstText,$Start].location];
tSel.end.pos ← [selEnd,
IF lastText=NIL THEN TiogaNode.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];
TiogaSelection.MakeSelection[new: tSel];
TiogaSelection.SetSelLooks[TiogaSelection.pSel] };
TiogaInputOps.CallWithLocks[DoSet];
{ OPEN IO;
h: Handle ← CreateOutputStreamToRope[];
Put[h, int[keywords], IF keywords=1 THEN rope[" keyword, "] ELSE rope[" keywords, "]];
Put[h, int[comments], IF comments=1 THEN rope[" comment, "] ELSE rope[" comments, "]];
Put[h, int[procs], IF procs=1 THEN rope[" procedure name."] ELSE rope[" procedure names."]];
MessageWindow.Append[GetOutputStreamRope[h],TRUE] }}; 
TiogaInput.Register[$SetMesaLooks, SetMesaLooksOp];
END...