|
Enhanced C#
Loyc library documentation
|
Enhances ILNodePrinterHelper{Self} with an ability to revoke newlines. More...
Enhances ILNodePrinterHelper{Self} with an ability to revoke newlines.
| Self | The return type of methods in the base interface. |
| Checkpoint | A type returned by GetCheckpoint representing a location in the output stream. |
When pretty-printing any language as text, it's a challenge to decide where to place newlines. You may want to break up long lines into shorter ones, as in
if (ReallyLongIdentifier[Fully.Qualified.Name(multiple, parameters)]
> SomeConstant)
{
return ReallyLongIdentifier[firstThing + secondThing]
+ thirdThing + fourthThing;
}
Conversely, you may want to print something on one line that you would ordinarily print on two:
if (c) break;
Of course, the problem is, you don't know how long the syntax tree will be in text form until after you try to print it.
My first idea to solve this problem was to use a rope tree data structure - inner syntax trees would produce small strings that could be "roped" together to produce a bigger tree. But ropes tend not to use memory efficiently, and there was the challenge, which I didn't see how to solve, of how to keep the tree balanced efficiently (for this particular application perhaps a balanced tree wasn't needed, but as a perfectionist I didn't want to implement a "half-baked" data structure.)
Next I thought of a simpler solution based on an ordinary StringBuilder. My idea was to insert newlines "pessimistically" - insert them everywhere in which they might be needed - and then selectively "revoke" them later if they turn out to be unnecessary. Only the most recently-written newline(s) can be revoked, which keeps the implementation simple and also limits the performance cost of deleting the newlines.
To use, call Newline() to write a newline (with indentation). To make a decision about whether to keep or revoke the most recent newline(s), call RevokeOrCommitNewlines(cp, maxLineLength) where cp is a "checkpoint" representing some point before the first newline you want to potentially revoke, and maxLineLength is the line length threshold: if the line length after combining lines, starting at the line on which the checkpoint is located, does not exceed maxLineLength, then the newlines are revoked, otherwise ALL newlines are committed (so earlier newlines can no longer be revoked.)
This design allows a potentially long series of newlines to be deleted in the reverse order that they were created, but if any newline is kept then previous ones can no longer be deleted.
For an example of how this is used, see the JSON printer in LLLPG samples or look at the implementation of the LESv3 printer.
| Self | : | ILNodePrinterHelperWithRevokableNewlines | |
| Self | : | Checkpoint | |
| Self | : | Self |
Properties | |
| int | LineWidth [get] |
| Gets the current width of the current line (typically measured in characters). More... | |
Properties inherited from Loyc.Syntax.Impl.IPrinterHelper< out Self > | |
| bool | IsAtStartOfLine [get] |
| Returns true iff nothing has been written since the last call to Newline or NewlineIsRequiredHere. More... | |
| char | LastCharWritten [get] |
| Gets the character most recently written to the stream, or '' if no characters have been written. More... | |
Public Member Functions | |
| Checkpoint | NewlineAfterCheckpoint () |
| Appends a newline, returning a checkpoint from with indentation afterward according to the current indentation level. More... | |
| Checkpoint | GetCheckpoint () |
| Gets a value that can be passed later to RevokeNewlinesSince(Checkpoint). More... | |
| int | RevokeNewlinesSince (Checkpoint cp) |
| Deletes uncommitted newlines that were written after the specified checkpoint. More... | |
| Self | CommitNewlines () |
| Commits all uncommitted newlines permanently. More... | |
| int | RevokeOrCommitNewlines (Checkpoint cp, int maxLineWidth) |
Revokes or commits newlines added since the specified checkpoint. Recent newlines are revoked if the combined line length after revokation does not exceed maxLineWidth, otherwise ALL newlines are committed permanently. More... | |
Public Member Functions inherited from Loyc.Syntax.Impl.ILNodePrinterHelper< out Self > | |
| Self | BeginNode (ILNode node) |
| Self | EndNode () |
| Informs the helper that the printer is done writing the most recently started node. The helper may save the range of the node, e.g. by calling ILNodePrinterOptions.SaveRange. More... | |
| Self | BeginNode (ILNode node, PrinterIndentHint indentHint) |
| Combines the BeginNode and Indent operations. More... | |
| Self | EndNode (PrinterIndentHint indentHint) |
| Combines the EndNode and Dedent operations. More... | |
Public Member Functions inherited from Loyc.Syntax.Impl.IPrinterHelper< out Self > | |
| Self | Write (char c) |
| Appends a character to the output stream or StringBuilder. More... | |
| Self | Write (string s) |
| Appends a string to the output stream or StringBuilder. More... | |
| Self | Write (UString s) |
| Appends a string to the output stream or StringBuilder. More... | |
| Self | Space () |
| Writes a space character unless the last character written was a space. More... | |
| Self | Newline (bool deferIndent=false) |
| Appends a newline, with indentation afterward according to the current indentation level. More... | |
| Self | FlushIndent () |
| Writes the pending indent, if applicable. This allows you to call Indent or Dedent afterward while making sure the indentation on the current line is unaffected. More... | |
| Self | NewlineIsRequiredHere () |
| Requests that a newline be written at this location. If this method is called multiple times at the same location, or if Newline(int) is called immediately afterward, only a single newline is written. More... | |
| Self | Indent (PrinterIndentHint?hint=null) |
| Informs the helper that the printer is starting to write the specified node. The printer must call EndNode when it is done. This information may be used to record range information (to understand why this is useful, please read about LNodeRangeMapper) More... | |
| Self | Dedent (PrinterIndentHint?hint=null) |
| Decreases the current indent level. More... | |
| Self Loyc.Syntax.Impl.ILNodePrinterHelperWithRevokableNewlines< Checkpoint, out Self >.CommitNewlines | ( | ) |
Commits all uncommitted newlines permanently.
Also causes ranges after the uncommitted newlines to be saved.
Implemented in Loyc.Syntax.Impl.LNodePrinterHelper.
| Checkpoint Loyc.Syntax.Impl.ILNodePrinterHelperWithRevokableNewlines< Checkpoint, out Self >.GetCheckpoint | ( | ) |
Gets a value that can be passed later to RevokeNewlinesSince(Checkpoint).
Implemented in Loyc.Syntax.Impl.LNodePrinterHelper.
| Checkpoint Loyc.Syntax.Impl.ILNodePrinterHelperWithRevokableNewlines< Checkpoint, out Self >.NewlineAfterCheckpoint | ( | ) |
Appends a newline, returning a checkpoint from with indentation afterward according to the current indentation level.
Implemented in Loyc.Syntax.Impl.LNodePrinterHelper.
| int Loyc.Syntax.Impl.ILNodePrinterHelperWithRevokableNewlines< Checkpoint, out Self >.RevokeNewlinesSince | ( | Checkpoint | cp | ) |
Deletes uncommitted newlines that were written after the specified checkpoint.
Newlines created after a call to ILNodePrinterHelper{Self}.NewlineIsRequiredHere or LNodePrinterHelperExt.IrrevokableNewline are not revoked.
| int Loyc.Syntax.Impl.ILNodePrinterHelperWithRevokableNewlines< Checkpoint, out Self >.RevokeOrCommitNewlines | ( | Checkpoint | cp, |
| int | maxLineWidth | ||
| ) |
Revokes or commits newlines added since the specified checkpoint. Recent newlines are revoked if the combined line length after revokation does not exceed maxLineWidth, otherwise ALL newlines are committed permanently.
This method does not affect the indent level.
|
get |
Gets the current width of the current line (typically measured in characters).
1.8.7