Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
761 changes: 761 additions & 0 deletions DEPLOYMENT_STACKS_WHATIF_MODELS_GUIDE.md

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/Resources/ResourceManager/Formatters/Color.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public class Color : IEquatable<Color>

public static Color Blue { get; } = new Color($"{Esc}[38;5;39m");

public static Color Cyan { get; } = new Color($"{Esc}[38;5;51m");

public static Color Gray { get; } = new Color($"{Esc}[38;5;246m");

public static Color Reset { get; } = new Color($"{Esc}[0m");
Expand Down
78 changes: 76 additions & 2 deletions src/Resources/ResourceManager/Formatters/ColoredStringBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public class ColoredStringBuilder

private readonly Stack<Color> colorStack = new Stack<Color>();

private readonly List<string> indentStack = new List<string>();

public override string ToString()
{
return stringBuilder.ToString();
Expand Down Expand Up @@ -89,6 +91,78 @@ public AnsiColorScope NewColorScope(Color color)
return new AnsiColorScope(this, color);
}

public void Insert(int index, string value)
{
if (index >= 0 && index <= this.stringBuilder.Length)
{
this.stringBuilder.Insert(index, value);
}
}

public void InsertLine(int index, string value, Color color)
{
if (color != Color.Reset)
{
this.Insert(index, Color.Reset.ToString());
}
this.Insert(index, value + Environment.NewLine);
if (color != Color.Reset)
{
this.Insert(index, color.ToString());
}
}

public int GetCurrentIndex()
{
return this.stringBuilder.Length;
}

public void PushIndent(string indent)
{
this.indentStack.Add(indent);
}

public void PopIndent()
{
if (this.indentStack.Count > 0)
{
this.indentStack.RemoveAt(this.indentStack.Count - 1);
}
}
Comment on lines +120 to +131
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PushIndent/PopIndent maintain an indentStack, but the stack is never applied by Append*/AppendLine*. As a result, callers (e.g., formatters) can push indentation without any effect on output. Either implement indentation application (e.g., automatically prefix the current indent at the start of each new line) or remove these methods/state to avoid misleading consumers.

Copilot uses AI. Check for mistakes.

public void EnsureNumNewLines(int numNewLines)
{
if (this.stringBuilder.Length == 0)
{
for (int i = 0; i < numNewLines; i++)
{
this.stringBuilder.AppendLine();
}
return;
}

string currentText = this.stringBuilder.ToString();
int existingNewlines = 0;

for (int i = currentText.Length - 1; i >= 0 && currentText[i] == '\n'; i--)
{
existingNewlines++;
Comment on lines +146 to +149
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EnsureNumNewLines counts only consecutive '\n' characters at the end of the buffer. When the buffer contains Windows newlines ("\r\n" from AppendLine/Environment.NewLine), the trailing characters are not consecutive '\n', so this undercounts existing newlines and may append extra blank lines. Consider counting trailing newline sequences in an OS-agnostic way (e.g., trim trailing "\r"/"\n" and compute how many newline sequences are present, or iterate from the end handling "\r\n" as one).

Suggested change
for (int i = currentText.Length - 1; i >= 0 && currentText[i] == '\n'; i--)
{
existingNewlines++;
int index = currentText.Length - 1;
// Count trailing newline sequences in an OS-agnostic way:
// - Treat "\r\n" as a single newline
// - Also handle lone '\n' and lone '\r'
while (index >= 0)
{
if (currentText[index] == '\n')
{
existingNewlines++;
index--;
// Consume preceding '\r' if this is a Windows newline sequence "\r\n"
if (index >= 0 && currentText[index] == '\r')
{
index--;
}
}
else if (currentText[index] == '\r')
{
existingNewlines++;
index--;
}
else
{
break;
}

Copilot uses AI. Check for mistakes.
}

int remainingNewlines = numNewLines - existingNewlines;
for (int i = 0; i < remainingNewlines; i++)
{
this.stringBuilder.AppendLine();
}
Comment on lines +133 to +156
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EnsureNumNewLines counts only trailing '\n' characters, but AppendLine() uses Environment.NewLine (typically \r\n on Windows). With multiple trailing blank lines (e.g., \r\n\r\n), this will undercount and append extra newlines. Update the logic to count trailing Environment.NewLine sequences (or handle both \n and \r\n) so the requested number of newlines is enforced correctly.

Copilot uses AI. Check for mistakes.
}

public void Clear()
{
this.stringBuilder.Clear();
this.colorStack.Clear();
this.indentStack.Clear();
}

private void PushColor(Color color)
{
this.colorStack.Push(color);
Expand All @@ -101,7 +175,7 @@ private void PopColor()
this.stringBuilder.Append(this.colorStack.Count > 0 ? this.colorStack.Peek() : Color.Reset);
}

public class AnsiColorScope: IDisposable
public class AnsiColorScope : IDisposable
{
private readonly ColoredStringBuilder builder;

Expand All @@ -117,4 +191,4 @@ public void Dispose()
}
}
}
}
}
Loading
Loading