Skip to content

Commit

Permalink
Fancy comments, part 1
Browse files Browse the repository at this point in the history
Added a "fancy" flag to MultiLineComment.  If set, we will use
formatting commands embedded in the text itself.  The max width pop-up
and "boxed" flag will be ignored in favor of width and boxing
directives.  (See issue #111.)

The current "fancy" formatter is just a placeholder that folds lines
every 10 characters.

Removed FormattedMlcCache (added two changes back).  Caching the
rendered string list in the MLC itself is simpler and more efficient
than having a separate cache, and it works for Notes as well.

Added anchors for more comments in the 20090 test.
  • Loading branch information
fadden committed Jul 5, 2024
1 parent 14cacb4 commit 83da0d9
Show file tree
Hide file tree
Showing 18 changed files with 432 additions and 179 deletions.
5 changes: 4 additions & 1 deletion CommonWPF/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ namespace CommonWPF {
/// Miscellaneous helper functions.
/// </summary>
public static class Helper {
public static Color ZeroColor = Color.FromArgb(0, 0, 0, 0);
/// <summary>
/// Transparent black.
/// </summary>
public static readonly Color ZeroColor = Color.FromArgb(0, 0, 0, 0);

/// <summary>
/// Measures the size of a string when rendered with the specified parameters. Uses
Expand Down
2 changes: 1 addition & 1 deletion CommonWPF/InverseBooleanConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace CommonWPF {
/// <summary>
/// A value inverter for negating a boolean value (value --> !value).
///
/// See https://stackoverflow.com/questions/1039636/how-to-bind-inverse-boolean-properties-in-wpf
/// From <see href="https://stackoverflow.com/a/1039681/294248"/>.
/// </summary>
[ValueConversion(typeof(bool), typeof(bool))]
public class InverseBooleanConverter : IValueConverter {
Expand Down
3 changes: 3 additions & 0 deletions SourceGen/App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ limitations under the License.
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SourceGen"
xmlns:common="clr-namespace:CommonWPF;assembly=CommonWPF"
StartupUri="WpfGui/MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<common:InverseBooleanConverter x:Key="InvertBool"/>

<FontFamily x:Key="GeneralMonoFont">Consolas</FontFamily>

<!-- gradient background for bitmap images -->
Expand Down
117 changes: 0 additions & 117 deletions SourceGen/FormattedMlcCache.cs

This file was deleted.

16 changes: 1 addition & 15 deletions SourceGen/LineListGen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,6 @@ public class LineListGen {
/// </summary>
private FormattedOperandCache mFormattedLineCache = new FormattedOperandCache();

/// <summary>
/// Cache of previous-formatted multi-line comment strings.
/// </summary>
private FormattedMlcCache mFormattedMlcCache = new FormattedMlcCache();

/// <summary>
/// Local variable table data extractor.
/// </summary>
Expand Down Expand Up @@ -1057,14 +1052,7 @@ private void GenerateLineList(int startOffset, int endOffset, List<Line> lines)
spaceAdded = true;
}
if (mProject.LongComments.TryGetValue(offset, out MultiLineComment longComment)) {
List<string> formatted = mFormattedMlcCache.GetStringEntry(offset, longComment,
mFormatter);
if (formatted == null) {
Debug.WriteLine("Render " + longComment);
formatted = longComment.FormatText(mFormatter, string.Empty);
mFormattedMlcCache.SetStringEntry(offset, formatted, longComment,
mFormatter);
}
List<string> formatted = longComment.FormatText(mFormatter, string.Empty);
StringListToLines(formatted, offset, Line.Type.LongComment,
longComment.BackgroundColor, NoteColorMultiplier, lines);
spaceAdded = true;
Expand Down Expand Up @@ -1768,11 +1756,9 @@ private FormattedParts[] GenerateStringLines(int offset, string popcode,

public void DebugResetCacheCounters() {
mFormattedLineCache.DebugResetCounters();
mFormattedMlcCache.DebugResetCounters();
}
public void DebugLogCacheCounters() {
mFormattedLineCache.DebugLogCounters();
mFormattedMlcCache.DebugLogCounters();
}
}
}
98 changes: 88 additions & 10 deletions SourceGen/MultiLineComment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@

namespace SourceGen {
/// <summary>
/// Representation of a multi-line comment, which is a string plus some format directives.
/// Used for long comments and notes.
/// <para>Representation of a multi-line comment, which is a string plus some format options.
/// Used for long comments and notes.</para>
///
/// Instances are immutable.
/// <para>Instances are effectively immutable, as the text and options can't be modified
/// after the object is created. The object does cache the result of the last FormatText()
/// call, which is determined in part by the Formatter argument, which can change between
/// calls.</para>
/// </summary>
public class MultiLineComment {
/// <summary>
Expand All @@ -37,6 +40,12 @@ public class MultiLineComment {
/// </summary>
public string Text { get; private set; }

/// <summary>
/// True if this uses "fancy" formatting. If set, the BoxMode and MaxWidth properties
/// are ignored.
/// </summary>
public bool IsFancy { get; private set; }

/// <summary>
/// Set to true to render text surrounded by a box of ASCII characters.
/// </summary>
Expand All @@ -57,27 +66,50 @@ public class MultiLineComment {
/// </summary>
private const char BASIC_BOX_CHAR = '*';

private const int DEFAULT_WIDTH = 80;
private const int MIN_WIDTH = 8;


/// <summary>
/// Constructor. Object will have a max width of 80 and not be boxed.
/// Constructor. By default, comments use basic formatting, have a basic-mode max
/// width of 80, and aren't boxed.
/// </summary>
/// <remarks>
/// We'd actually prefer to have fancy formatting be the default, but that does the
/// wrong thing when deserializing older projects.
/// </remarks>
/// <param name="text">Unformatted comment text.</param>
public MultiLineComment(string text) {
Debug.Assert(text != null); // empty string is okay
Text = text;
IsFancy = false;
BoxMode = false;
MaxWidth = 80;
MaxWidth = DEFAULT_WIDTH;
BackgroundColor = CommonWPF.Helper.ZeroColor;
}

/// <summary>
/// Constructor. Used when creating an empty MLC for editing.
/// </summary>
/// <param name="isFancy">True if we want to be in "fancy" mode initially.</param>
public MultiLineComment(bool isFancy) : this(string.Empty) {
IsFancy = isFancy;
}

/// <summary>
/// Constructor. Used for long comments.
/// </summary>
/// <param name="text">Unformatted text.</param>
/// <param name="boxMode">Set to true to enable box mode.</param>
/// <param name="maxWidth">Maximum line width.</param>
public MultiLineComment(string text, bool boxMode, int maxWidth) : this(text) {
Debug.Assert((!boxMode && maxWidth > 1) || (boxMode && maxWidth > 5));
/// <param name="isFancy">True if we're using fancy format mode.</param>
/// <param name="boxMode">For basic mode, set to true to enable box mode.</param>
/// <param name="maxWidth">For basic mode, maximum line width.</param>
public MultiLineComment(string text, bool isFancy, bool boxMode, int maxWidth)
: this(text) {
if (maxWidth < MIN_WIDTH) {
Debug.Assert(false, "unexpectedly small max width");
maxWidth = MIN_WIDTH;
}
IsFancy = isFancy;
BoxMode = boxMode;
MaxWidth = maxWidth;
}
Expand All @@ -91,14 +123,46 @@ public MultiLineComment(string text, Color bkgndColor) : this(text) {
BackgroundColor = bkgndColor;
}

private List<string> mPreviousRender = null;
private Asm65.Formatter mPreviousFormatter = null;
private string mPreviousPrefix = null;

/// <summary>
/// Generates one or more lines of formatted text.
/// </summary>
/// <param name="formatter">Formatter, with comment delimiters.</param>
/// <param name="textPrefix">String to prepend to text before formatting. If this
/// is non-empty, comment delimiters aren't emitted. (Used for notes.)</param>
/// <returns>Array of formatted strings.</returns>
/// <returns>List of formatted strings. Do not modify the list.</returns>
public List<string> FormatText(Asm65.Formatter formatter, string textPrefix) {
if (mPreviousRender != null && formatter == mPreviousFormatter &&
textPrefix == mPreviousPrefix) {
// We rendered this with the same formatter before. Return the list. It would
// be safer to clone the list, but I'm not expecting the caller to edit it.
return mPreviousRender;
}
List<string> lines;
if (IsFancy) {
Debug.Assert(string.IsNullOrEmpty(textPrefix));
lines = FormatFancyText(formatter);
} else {
lines = FormatSimpleText(formatter, textPrefix);
}
// Cache result.
mPreviousRender = lines;
mPreviousFormatter = formatter;
mPreviousPrefix = textPrefix;
return lines;
}

/// <summary>
/// Generates one or more lines of formatted text, using the basic formatter.
/// </summary>
/// <param name="formatter">Formatter, with comment delimiters.</param>
/// <param name="textPrefix">String to prepend to text before formatting. If this
/// is non-empty, comment delimiters aren't emitted. (Used for notes.)</param>
/// <returns>List of formatted strings.</returns>
private List<string> FormatSimpleText(Asm65.Formatter formatter, string textPrefix) {
const char spcRep = '\u2219'; // BULLET OPERATOR
string workString = string.IsNullOrEmpty(textPrefix) ? Text : textPrefix + Text;
List<string> lines = new List<string>();
Expand Down Expand Up @@ -263,6 +327,20 @@ public List<string> FormatText(Asm65.Formatter formatter, string textPrefix) {
return lines;
}

/// <summary>
/// Generates one or more lines of formatted text, using the fancy formatter.
/// </summary>
/// <param name="formatter">Formatter, with comment delimiters.</param>
/// <returns>List of formatted strings.</returns>
private List<string> FormatFancyText(Asm65.Formatter formatter) {
List<string> lines = new List<string>();
string mod = Text.Replace("\r\n", "CRLF");
for (int i = 0; i < mod.Length; i += 10) {
lines.Add(formatter.FullLineCommentDelimiterPlus +
mod.Substring(i, Math.Min(10, mod.Length - i)));
}
return lines;
}

public override string ToString() {
return "MLC box=" + BoxMode + " width=" + MaxWidth + " text='" + Text + "'";
Expand Down
4 changes: 3 additions & 1 deletion SourceGen/ProjectFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -283,13 +283,15 @@ public SerTypeHintRange(int low, int high, string hintStr) {
public class SerMultiLineComment {
// NOTE: Text must be CRLF at line breaks.
public string Text { get; set; }
public bool IsFancy { get; set; }
public bool BoxMode { get; set; }
public int MaxWidth { get; set; }
public int BackgroundColor { get; set; }

public SerMultiLineComment() { }
public SerMultiLineComment(MultiLineComment mlc) {
Text = mlc.Text;
IsFancy = mlc.IsFancy;
BoxMode = mlc.BoxMode;
MaxWidth = mlc.MaxWidth;
BackgroundColor = CommonWPF.Helper.ColorToInt(mlc.BackgroundColor);
Expand Down Expand Up @@ -762,7 +764,7 @@ public static bool DeserializeProject(string cereal, DisasmProject proj,
continue;
}
proj.LongComments[intKey] = new MultiLineComment(kvp.Value.Text,
kvp.Value.BoxMode, kvp.Value.MaxWidth);
kvp.Value.IsFancy, kvp.Value.BoxMode, kvp.Value.MaxWidth);
}

// Deserialize notes.
Expand Down
Binary file modified SourceGen/SGTestData/20090-notes-and-comments
Binary file not shown.
Loading

0 comments on commit 83da0d9

Please sign in to comment.