1
0
mirror of https://github.com/fadden/6502bench.git synced 2025-01-14 07:29:44 +00:00

Fancy comments, part 3

Handle [br], [hr], [hr char='x'], and [width=nn].
This commit is contained in:
Andy McFadden 2024-07-07 08:48:58 -07:00
parent 1c84357bbf
commit 227cdaab30
6 changed files with 448 additions and 72 deletions

View File

@ -332,22 +332,33 @@ namespace SourceGen {
#region Fancy #region Fancy
private enum Tag { /// <summary>
Unknown = 0, Width, HorizRule, Break, /// Input data source.
BoxStart, BoxEnd, UrlStart, UrlEnd, SymStart, SymEnd /// </summary>
}
private class DataSource { private class DataSource {
private string mString; private string mString;
private int mPosn; private int mPosn;
public bool mInBox, mInUrl, mInSym;
public char this[int i] { public string Text => mString;
get { return mString[i]; } public char this[int i] { get { return mString[i]; } }
}
public int Posn { get { return mPosn; } set { mPosn = value; } } public int Posn { get { return mPosn; } set { mPosn = value; } }
public int Length => mString.Length; public int Length => mString.Length;
public char CurChar => mString[mPosn]; // mostly for debugger public char CurChar => mString[mPosn];
// These are true if the text is appearing inside start/end tags.
public bool InBox { get; set; }
public bool InUrl { get; set; }
public bool InSym { get; set; }
public bool InsideElement { get { return InBox || InsideNonBoxElement; } }
public bool InsideNonBoxElement { get { return InUrl || InSym; } }
// If true, don't prefix lines with the comment delimiter.
public bool SuppressPrefix { get; set; }
// True if using default char (comment delimiter) for boxes.
public bool BoxCharIsDefault { get; set; } = true;
public char BoxChar { get; set; } = '?';
public DataSource(string str, int posn, DataSource outer) { public DataSource(string str, int posn, DataSource outer) {
mString = str; mString = str;
@ -355,30 +366,49 @@ namespace SourceGen {
if (outer != null) { if (outer != null) {
// Inherit the values from the "outer" source. // Inherit the values from the "outer" source.
mInBox = outer.mInBox; InBox = outer.InBox;
mInUrl = outer.mInUrl; InUrl = outer.InUrl;
mInSym = outer.mInSym; InSym = outer.InSym;
SuppressPrefix = outer.SuppressPrefix;
BoxCharIsDefault = outer.BoxCharIsDefault;
BoxChar = outer.BoxChar;
} }
} }
/// <summary>
/// Returns true if the string at the current position matches the argument. The
/// comparison is case-insensitive.
/// </summary>
public bool Match(string str, int offset) {
if (mPosn + offset + str.Length > mString.Length) {
return false;
}
for (int i = 0; i < str.Length; i++) {
if (char.ToUpper(str[i]) != char.ToUpper(mString[mPosn + offset + i])) {
return false;
}
}
return true;
}
} }
private Stack<DataSource> mSourceStack = new Stack<DataSource>(); private Stack<DataSource> mSourceStack = new Stack<DataSource>();
private StringBuilder mLineBuilder = new StringBuilder(MAX_WIDTH); private StringBuilder mLineBuilder = new StringBuilder(MAX_WIDTH);
private const char DEFAULT_CHAR = '\0'; //private const char DEFAULT_CHAR = '\0';
private const char DEFAULT_RULE_CHAR = '-';
private int mLineWidth; private int mLineWidth;
private char mBoxCharOrDef, mHorizRuleCharOrDef;
private char mBoxCharActual; private char mBoxCharActual;
private bool mEscapeNext, mEatNextIfNewline;
private string mLinePrefix, mBoxPrefix; private string mLinePrefix, mBoxPrefix;
private bool mDebugMode; private bool mDebugMode;
/// <summary> /// <summary>
/// Calculates the width of the usable text area, given the current attributes. /// Calculates the width of the usable text area, given the current attributes.
/// </summary> /// </summary>
private int CalcTextWidth(DataSource source) { private int CalcTextWidth(DataSource source) {
if (source.mInBox) { if (source.InBox) {
if (mBoxCharOrDef == DEFAULT_CHAR) { if (source.BoxCharIsDefault) {
// Leave space for left/right box edges. // Leave space for left/right box edges.
return mLineWidth - mBoxPrefix.Length - 4; return mLineWidth - mBoxPrefix.Length - 4;
} else { } else {
@ -395,14 +425,12 @@ namespace SourceGen {
/// <summary> /// <summary>
/// Generates one or more lines of formatted text, using the fancy formatter. /// Generates one or more lines of formatted text, using the fancy formatter.
/// </summary> /// </summary>
/// <param name="formatter">Formatter, with comment delimiters.</param> /// <param name="formatter">Formatter, which specifies comment delimiters.</param>
/// <returns>List of formatted strings.</returns> /// <returns>List of formatted strings.</returns>
private List<string> FormatFancyText(Asm65.Formatter formatter) { private List<string> FormatFancyText(Asm65.Formatter formatter) {
Debug.Assert(SPACES.Length == MAX_WIDTH); Debug.Assert(SPACES.Length == MAX_WIDTH);
mLineWidth = DEFAULT_WIDTH; mLineWidth = DEFAULT_WIDTH; // could make this a setting
mBoxCharOrDef = mHorizRuleCharOrDef = DEFAULT_CHAR;
mEscapeNext = mEatNextIfNewline = false;
mDebugMode = formatter.DebugLongComments; mDebugMode = formatter.DebugLongComments;
mSourceStack.Clear(); mSourceStack.Clear();
@ -412,6 +440,8 @@ namespace SourceGen {
DataSource source = new DataSource(Text, 0, null); DataSource source = new DataSource(Text, 0, null);
int textWidth = CalcTextWidth(source); int textWidth = CalcTextWidth(source);
bool escapeNext = false;
//bool eatNextIfNewline = false;
char[] outBuf = new char[MAX_WIDTH]; char[] outBuf = new char[MAX_WIDTH];
int outIndex = 0; int outIndex = 0;
@ -428,12 +458,13 @@ namespace SourceGen {
// Walk through the input source. // Walk through the input source.
while (true) { while (true) {
if (source.Posn == source.Length) { if (source.Posn == source.Length) {
if (mSourceStack.Count != 0) { if (mSourceStack.Count == 0) {
source = mSourceStack.Pop(); break; // all done
textWidth = CalcTextWidth(source);
continue; // resume earlier string
} }
break; // all done
source = mSourceStack.Pop();
textWidth = CalcTextWidth(source);
continue; // resume earlier string
} }
if (source.CurChar == '\r' || source.CurChar == '\n') { if (source.CurChar == '\r' || source.CurChar == '\n') {
@ -443,37 +474,38 @@ namespace SourceGen {
source.Posn++; source.Posn++;
} }
mEscapeNext = false; // can't escape newlines escapeNext = false; // can't escape newlines
if (mEatNextIfNewline) { // Output what we have.
mEatNextIfNewline = false; OutputLine(outBuf, outIndex, source, lines);
} else { outIndex = 0;
// Output what we have. outBreakIndex = -1;
OutputLine(outBuf, outIndex, source.mInBox, lines);
outIndex = 0;
outBreakIndex = -1;
}
source.Posn++; source.Posn++;
continue; continue;
} }
mEatNextIfNewline = false;
char thisCh = source.CurChar; char thisCh = source.CurChar;
if (thisCh == '\\') { if (thisCh == '\\') {
if (!mEscapeNext) { if (!escapeNext) {
mEscapeNext = true; escapeNext = true;
source.Posn++; // eat the backslash source.Posn++; // eat the backslash
continue; // restart loop; backslash might have been last char continue; // restart loop to get next char (if any)
} }
} else if (thisCh == '[' && !mEscapeNext) { } else if (thisCh == '[' && !escapeNext) {
// Start of format tag? // Start of format tag?
if (TryParseTag(source, out int skipLen, out DataSource subSource)) { if (TryParseTag(source, out int skipLen, out DataSource subSource,
out bool requireLineStart)) {
if (requireLineStart && outIndex != 0) {
OutputLine(outBuf, outIndex, source, lines);
outIndex = 0;
outBreakIndex = -1;
}
source.Posn += skipLen; source.Posn += skipLen;
if (subSource != null) { if (subSource != null) {
mSourceStack.Push(source); mSourceStack.Push(source);
source = subSource; source = subSource;
textWidth = CalcTextWidth(source);
} }
textWidth = CalcTextWidth(source);
continue; continue;
} }
} else if (thisCh == ' ') { } else if (thisCh == ' ') {
@ -484,14 +516,18 @@ namespace SourceGen {
outBreakIndex = outIndex; outBreakIndex = outIndex;
} }
} }
escapeNext = false;
// We need to add a character to the buffer. Will this put us over the limit? // We need to add a character to the out buffer. Will this put us over the limit?
if (outIndex == textWidth) { if (outIndex == textWidth) {
int outputCount; int outputCount;
if (outBreakIndex <= 0) { if (outBreakIndex <= 0) {
// No break found, or break char was at start of line. Just chop what // No break found, or break char was at start of line. Just chop what
// we have. // we have.
outputCount = outIndex; outputCount = outIndex;
if (outputCount > 0 && char.IsSurrogate(outBuf[outIndex - 1])) {
outputCount--; // don't split surrogate pairs
}
} else { } else {
// Break was a hyphen or space. // Break was a hyphen or space.
outputCount = outBreakIndex; outputCount = outBreakIndex;
@ -505,7 +541,7 @@ namespace SourceGen {
// Output everything up to the break point, but not the break char itself // Output everything up to the break point, but not the break char itself
// unless it's a hyphen. // unless it's a hyphen.
OutputLine(outBuf, outputCount + adj, source.mInBox, lines); OutputLine(outBuf, outputCount + adj, source, lines);
// Consume any trailing spaces (which are about to become leading spaces). // Consume any trailing spaces (which are about to become leading spaces).
while (outputCount < outIndex && outBuf[outputCount] == ' ') { while (outputCount < outIndex && outBuf[outputCount] == ' ') {
@ -534,8 +570,9 @@ namespace SourceGen {
} }
} }
// Fold lines at hyphens. We need to check for it after the "line full" test
// because we want to retain it at the end of the line.
if (source.CurChar == '-') { if (source.CurChar == '-') {
// Can break on hyphen if it fits in line.
outBreakIndex = outIndex; outBreakIndex = outIndex;
} }
@ -544,12 +581,70 @@ namespace SourceGen {
// If we didn't end with a CRLF, output the last bits. // If we didn't end with a CRLF, output the last bits.
if (outIndex > 0) { if (outIndex > 0) {
OutputLine(outBuf, outIndex, source.mInBox, lines); OutputLine(outBuf, outIndex, source, lines);
} }
return lines; return lines;
} }
/// <summary>
/// Adds the contents of the output buffer to the line list, prefixing it with comment
/// delimiters and/or wrapping it in a box.
/// </summary>
/// <param name="outBuf">Output buffer.</param>
/// <param name="length">Length of data in output buffer.</param>
/// <param name="inBox">True if we're inside a box.</param>
/// <param name="lines">Line list to add the line to.</param>
private void OutputLine(char[] outBuf, int length, DataSource source, List<string> lines) {
Debug.Assert(length >= 0);
mLineBuilder.Clear();
if (source.InBox) {
mLineBuilder.Append(mBoxPrefix);
mLineBuilder.Append(outBuf, 0, length);
int trailingCount = mLineWidth - mBoxPrefix.Length - length - 1;
if (trailingCount > 0) {
mLineBuilder.Append(SPACES, 0, trailingCount);
}
mLineBuilder.Append(mBoxCharActual);
} else {
if (!source.SuppressPrefix) {
mLineBuilder.Append(mLinePrefix);
}
mLineBuilder.Append(outBuf, 0, length);
}
string str = mLineBuilder.ToString();
if (mDebugMode) {
str = str.Replace(' ', '\u2219'); // replace spaces with BULLET OPERATOR
}
lines.Add(str);
}
private enum Tag {
Unknown = 0, Break, HorizRule, Width,
BoxStart, BoxEnd, UrlStart, UrlEnd, SymStart, SymEnd
}
private class TagMatch {
public string mPatStr;
public Tag mTag;
public TagMatch(string pat, Tag tag) {
mPatStr = pat;
mTag = tag;
}
}
private static readonly TagMatch[] sTagTable = {
new TagMatch("br", Tag.Break),
new TagMatch("hr", Tag.HorizRule),
new TagMatch("width", Tag.Width),
new TagMatch("box", Tag.BoxStart),
new TagMatch("/box", Tag.BoxEnd),
new TagMatch("url", Tag.UrlStart),
new TagMatch("/url", Tag.UrlEnd),
new TagMatch("sym", Tag.SymStart),
new TagMatch("/sym", Tag.SymEnd),
};
/// <summary> /// <summary>
/// Attempts to parse a tag at the current source position. /// Attempts to parse a tag at the current source position.
/// </summary> /// </summary>
@ -560,42 +655,171 @@ namespace SourceGen {
/// <param name="source">Input data source.</param> /// <param name="source">Input data source.</param>
/// <param name="skipLen">Number of characters to advance in data source.</param> /// <param name="skipLen">Number of characters to advance in data source.</param>
/// <param name="subSource">Result: data source with tag contents. May be null.</param> /// <param name="subSource">Result: data source with tag contents. May be null.</param>
/// <param name="requireLineStart">Result: if true, and the output buffer has characters
/// in it, they must be flushed before continuing.</param>
/// <returns>True if the tag was successfully parsed.</returns> /// <returns>True if the tag was successfully parsed.</returns>
private bool TryParseTag(DataSource source, out int skipLen, out DataSource subSource) { private bool TryParseTag(DataSource source, out int skipLen, out DataSource subSource,
out bool requireLineStart) {
skipLen = 0; skipLen = 0;
requireLineStart = false;
subSource = null; subSource = null;
// TODO
return false; Tag tag = Tag.Unknown;
foreach (TagMatch pat in sTagTable) {
if (source.Match(pat.mPatStr, 1)) {
tag = pat.mTag;
break;
}
}
string tagStr = null;
if (tag != Tag.Unknown) {
// Look for the end.
for (int endpos = source.Posn + 2; endpos < source.Length; endpos++) {
if (source[endpos] == ']') {
// Found the end of the tag.
tagStr = source.Text.Substring(source.Posn, endpos - source.Posn + 1);
break;
}
}
}
if (tagStr == null) {
Debug.WriteLine("Unterminated match at " + source.Posn + ": " + tag);
return false;
}
Debug.WriteLine("Probable match at " + source.Posn + ": " + tag + " '" + tagStr + "'");
bool eatNextIfNewline = false;
switch (tag) {
case Tag.Break:
int brWidth = "[br]".Length;
if (tagStr.Length != brWidth) {
return false;
}
if (source.InBox) {
Debug.WriteLine("Can't use [br] inside a box");
return false;
}
skipLen = brWidth;
// Just a blank line, but with "suppress prefix" enabled.
requireLineStart = eatNextIfNewline = true;
subSource = new DataSource("\r\n", 0, source);
subSource.SuppressPrefix = true;
break;
case Tag.HorizRule:
if (source.InsideNonBoxElement) {
return false;
}
char defaultCh;
if (source.InBox) {
defaultCh = source.BoxChar;
} else {
defaultCh = DEFAULT_RULE_CHAR;
}
char hrChar = HandleHorizRule(tagStr, defaultCh, out skipLen);
if (hrChar == '\0') {
return false;
}
int ruleWidth = CalcTextWidth(source);
StringBuilder rulerSb = new StringBuilder(ruleWidth);
for (int i = 0; i < ruleWidth; i++) {
rulerSb.Append(hrChar);
}
subSource = new DataSource(rulerSb.ToString(), 0, source);
requireLineStart = eatNextIfNewline = true;
break;
case Tag.Width:
if (source.InsideNonBoxElement) {
return false;
}
int newWidth = HandleWidth(tagStr, out skipLen);
if (newWidth < 0) {
return false;
}
requireLineStart = eatNextIfNewline = true;
mLineWidth = newWidth;
break;
default:
return false;
}
// Some tags cause a newline to happen, e.g. [box] and [hr] always start on a new line
// of output. It can feel natural to type these on a line by themselves, but that
// will generate an extra newline unless we suppress it here.
if (eatNextIfNewline) {
if (source.Posn + skipLen < source.Length &&
source[source.Posn + skipLen] == '\r') {
skipLen++;
}
if (source.Posn + skipLen < source.Length &&
source[source.Posn + skipLen] == '\n') {
skipLen++;
}
}
return true;
} }
/// <summary> /// <summary>
/// Adds the contents of the output buffer to the line list, prefixing it with comment /// Parses an [hr] or [hr char='x'] tag. Returns the ruler char, or '\0' on error.
/// delimiters and/or wrapping it in a box.
/// </summary> /// </summary>
/// <param name="outBuf">Output buffer.</param> private static char HandleHorizRule(string tagStr, char defaultChar, out int skipLen) {
/// <param name="length">Length of data in output buffer.</param> const string simpleForm = "[hr]";
/// <param name="inBox">True if we're inside a box.</param> const string prefix = "[hr char='";
/// <param name="lines">Line list to add the line to.</param> const string suffix = "']";
private void OutputLine(char[] outBuf, int length, bool inBox, List<string> lines) { const char FAILED = '\0';
Debug.Assert(length >= 0); skipLen = tagStr.Length;
mLineBuilder.Clear();
if (inBox) { char hrChar;
mLineBuilder.Append(mBoxPrefix); if (tagStr.Equals(simpleForm, StringComparison.OrdinalIgnoreCase)) {
mLineBuilder.Append(outBuf, 0, length); // use default char
int trailingCount = mLineWidth - mBoxPrefix.Length - length - 1; hrChar = defaultChar;
if (trailingCount > 0) { } else if (tagStr.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase)) {
mLineBuilder.Append(SPACES, 0, trailingCount); // char explicitly set
int charStrLen = tagStr.Length - prefix.Length - suffix.Length;
if (charStrLen != 1) {
return FAILED;
} }
mLineBuilder.Append(mBoxCharActual); if (!tagStr.EndsWith(suffix, StringComparison.InvariantCultureIgnoreCase)) {
return FAILED;
}
hrChar = tagStr[prefix.Length];
} else { } else {
mLineBuilder.Append(mLinePrefix); return FAILED;
mLineBuilder.Append(outBuf, 0, length);
} }
string str = mLineBuilder.ToString(); return hrChar;
if (mDebugMode) { }
str = str.Replace(' ', '\u2219'); // replace spaces with BULLET OPERATOR
/// <summary>
/// Parses a [width] tag. Returns the width, or -1 on error.
/// </summary>
private static int HandleWidth(string tagStr, out int skipLen) {
const string prefix = "[width=";
const string suffix = "]";
skipLen = 0;
int widthStrLen = tagStr.Length - prefix.Length - suffix.Length;
if (widthStrLen <= 0) {
return -1;
} }
lines.Add(str); if (!tagStr.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase)) {
return -1;
}
if (!tagStr.EndsWith(suffix, StringComparison.InvariantCultureIgnoreCase)) {
return -1;
}
string widthStr = tagStr.Substring(prefix.Length, widthStrLen);
int newWidth;
if (widthStr == "*") {
newWidth = DEFAULT_WIDTH;
} else if (!int.TryParse(widthStr, out newWidth)) {
Debug.WriteLine("Unable to parse width '" + widthStr + "'");
return -1;
}
if (newWidth < MIN_WIDTH || newWidth > MAX_WIDTH) {
return -1;
}
skipLen = tagStr.Length;
return newWidth;
} }
#endregion Fancy #endregion Fancy

View File

@ -122,6 +122,34 @@
"IsFancy":true, "IsFancy":true,
"BoxMode":false, "BoxMode":false,
"MaxWidth":80, "MaxWidth":80,
"BackgroundColor":0},
"103":{
"Text":"Check for surrogate pair splitting. 1/2 should be split:\r\nzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzxxxxxxxxxxxxxxxxxxx12x\r\nzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzUnicode_Character_“😊”_(U+1F60A)",
"IsFancy":true,
"BoxMode":false,
"MaxWidth":80,
"BackgroundColor":0},
"105":{
"Text":"Test \\[width]. This line has the default width of 80, so things break way out here.\r\nLines with width=8, width=10, and width=*: [width=8]012345678901234567890123456789[width=10]012345678901234567890123456789[width=*]012345678901234567890123456789\r\n",
"IsFancy":true,
"BoxMode":false,
"MaxWidth":80,
"BackgroundColor":0},
"109":{
"Text":"[br]\r\nTesting \\[br] blank lines.[br][br]\r\n[br]three above, one below\r\n[br]\r\n",
"IsFancy":true,
"BoxMode":false,
"MaxWidth":80,
"BackgroundColor":0},
"107":{
"Text":"Test \\[hr] and \\[hr char=\u0027#\u0027].[hr][hr]x[hr char=\u0027#\u0027]y",
"IsFancy":true,
"BoxMode":false,
"MaxWidth":80,
"BackgroundColor":0}}, "BackgroundColor":0}},
"Notes":{ "Notes":{

View File

@ -94,9 +94,40 @@ L1062 bit plataddr ;Pull in plataddr to see the comment on the platform
;business. ;business.
; ;
lda #$10 lda #$10
;Check for surrogate pair splitting. 1/2 should be split:
;zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzxxxxxxxxxxxxxxxxxxx1
;2x
;zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzUnicode_Character_“
;😊”_(U+1F60A)
lda #$11 lda #$11
;Test [width]. This line has the default width of 80, so things break way out
;here.
;Lines with width=8, width=10, and width=*:
;0123456
;7890123
;4567890
;1234567
;89
;012345678
;901234567
;890123456
;789
;012345678901234567890123456789
lda #$12 lda #$12
;Test [hr] and [hr char='#'].
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
;x
;###############################################################################
;y
lda #$13 lda #$13
;Testing [br] blank lines.
;three above, one below
lda #$14 lda #$14
lda #$15 lda #$15
lda #$16 lda #$16

View File

@ -92,9 +92,40 @@ L1062 bit plataddr ;Pull in plataddr to see the comment on the platform
;business. ;business.
; ;
lda #$10 lda #$10
;Check for surrogate pair splitting. 1/2 should be split:
;zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzxxxxxxxxxxxxxxxxxxx1
;2x
;zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzUnicode_Character_“
;😊”_(U+1F60A)
lda #$11 lda #$11
;Test [width]. This line has the default width of 80, so things break way out
;here.
;Lines with width=8, width=10, and width=*:
;0123456
;7890123
;4567890
;1234567
;89
;012345678
;901234567
;890123456
;789
;012345678901234567890123456789
lda #$12 lda #$12
;Test [hr] and [hr char='#'].
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
;x
;###############################################################################
;y
lda #$13 lda #$13
;Testing [br] blank lines.
;three above, one below
lda #$14 lda #$14
lda #$15 lda #$15
lda #$16 lda #$16

View File

@ -94,9 +94,40 @@ L1062: bit plataddr ;Pull in plataddr to see the comment on the platform
;business. ;business.
; ;
lda #$10 lda #$10
;Check for surrogate pair splitting. 1/2 should be split:
;zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzxxxxxxxxxxxxxxxxxxx1
;2x
;zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzUnicode_Character_“
;😊”_(U+1F60A)
lda #$11 lda #$11
;Test [width]. This line has the default width of 80, so things break way out
;here.
;Lines with width=8, width=10, and width=*:
;0123456
;7890123
;4567890
;1234567
;89
;012345678
;901234567
;890123456
;789
;012345678901234567890123456789
lda #$12 lda #$12
;Test [hr] and [hr char='#'].
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
;x
;###############################################################################
;y
lda #$13 lda #$13
;Testing [br] blank lines.
;three above, one below
lda #$14 lda #$14
lda #$15 lda #$15
lda #$16 lda #$16

View File

@ -89,9 +89,40 @@ L1062 bit plataddr ;Pull in plataddr to see the comment on the platform f
*business. *business.
* *
lda #$10 lda #$10
*Check for surrogate pair splitting. 1/2 should be split:
*zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzxxxxxxxxxxxxxxxxxxx1
*2x
*zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzUnicode_Character_
*😊_(U+1F60A)
lda #$11 lda #$11
*Test [width]. This line has the default width of 80, so things break way out
*here.
*Lines with width=8, width=10, and width=*:
*0123456
*7890123
*4567890
*1234567
*89
*012345678
*901234567
*890123456
*789
*012345678901234567890123456789
lda #$12 lda #$12
*Test [hr] and [hr char='#'].
*-------------------------------------------------------------------------------
*-------------------------------------------------------------------------------
*x
*###############################################################################
*y
lda #$13 lda #$13
*Testing [br] blank lines.
*three above, one below
lda #$14 lda #$14
lda #$15 lda #$15
lda #$16 lda #$16