TiogaStreams.Mesa
Mike Spreitzer April 24, 1990 6:47 am PDT
DIRECTORY IO, Rope, TextNode, TiogaFileOps;
TiogaStreams: CEDAR DEFINITIONS =
BEGIN
ROPE: TYPE = Rope.ROPE;
Input
CreateInput: PROC [from: TextNode.Ref, commentHandling: CommentHandling ← discard, levelPrefix: ROPENIL] RETURNS [in: IO.STREAM];
Create a Tioga Input Stream on descendents of from.
Each subnode's chars are prefixed by levelPrefix * (-1 + its depth realtive to from), then maybe "--" for comment nodes.
CommentHandling: TYPE = {discard, useDirectly, prefixWithDashDash};
What to do about comment nodes.
CurInLoc: PROC [s: IO.STREAM] RETURNS [loc: TextNode.Location];
Where the "carat" is. This is a position between characters, or index of next character. Phony prefixes and postfixes get "squeezed" out.
SkipChildren: PROC [s: IO.STREAM];
Skips children of CurInNode[s].
Output
CreateOutput: PROC [to: TiogaFileOps.Ref, breakAtNewline: BOOLFALSE, levelPrefix, defaultFormat: ROPENIL, flexilevel: BOOLFALSE, spacesPerTab, normalNestIndent: INT ← 0] RETURNS [out: IO.STREAM];
Creates children of to.
IF breakAtNewline, THEN s.PutChar['\n] gets translated to s.EndNode[reset, FALSE].
IF (NOT flexilevel) AND levelPrefix # NIL, THEN every node that begins with N repetitions of levelPrefix will be indented N levels deeper than it otherwise would be.
IF flexilevel, THEN the depth of each node is 1 more than the depth of the most recent node with less leading whitespace. Spaces are white; tabs are white iff spacesPerTab>0; nothing else is white.
Each child node will have format=defaultFormat, unless explicitly overridden by SetFormat.
IF flexilevel AND normalNestIndent>0, THEN each node whose amout of leading white space exceeds its parent's by an amout different than normalNestIndent gets a Postfix property adjusting its appearance to match the amount of leading white space.
CurOutNode: PROC [s: IO.STREAM] RETURNS [n: TiogaFileOps.Ref];
Returns the one just before the "carat", which is, of course, between characters.
EndNode: PROC [s: IO.STREAM, depthOp: DepthOp ← reset, idempotently: BOOLEANFALSE];
depthOp says whether new node should have same depth as previous, or revert to initial (direct child of CreateOutput's to). May be further modified by ChangeDepth or receiving levelPrefixes.
DepthOp: TYPE = {same, reset};
SetFormat: PROC [of: IO.STREAM, format: ROPE];
Applies to CurOutNode only.
ChangeDepth: PROC [s: IO.STREAM, deltaDepth: INTEGER ← 0, autoEndNode: BOOLTRUE, idempotently: BOOLFALSE];
IF autoEndNode, THEN first EndNode[same, idempotently].
Must be called "between" nodes (autoEndNode trivializes that).
Changes depth of following node from what it would otherwise be.
Can't be called on flexilevel streams.
NotNow: ERROR [s: IO.STREAM];
Raised by ChangeDepth when called before node ended.
BadDepth: ERROR [s: IO.STREAM, depth: INT];
Raised when depth (relative to CreateOutput's to) goes negative --- usually from IO operations (like PutChar) that put the first character on a node.
When depth jumps deeper than Tioga will (i.e., more than one level per jump), the difference is made up by prefixing with copies of levelPrefix.
CallerBug: ERROR [s: IO.STREAM, message: ROPE];
General escape.
Other
IsATS: PROC [s: IO.STREAM] RETURNS [is: BOOLEAN];
Accepts either input or output streams.
CopyChildren: PROC [from: TextNode.Ref, to: TiogaFileOps.Ref];
END.