Fix diagnostic print
This commit is contained in:
@@ -82,121 +82,124 @@ public class Diagnostic
|
||||
|
||||
public string FormatANSI()
|
||||
{
|
||||
try
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.Append(Severity switch
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
DiagnosticSeverity.Error => ConsoleColors.Colorize("error", ConsoleColors.Bold + ConsoleColors.Red),
|
||||
DiagnosticSeverity.Warning => ConsoleColors.Colorize("warning", ConsoleColors.Bold + ConsoleColors.Yellow),
|
||||
DiagnosticSeverity.Info => ConsoleColors.Colorize("info", ConsoleColors.Bold + ConsoleColors.Blue),
|
||||
_ => ConsoleColors.Colorize("unknown", ConsoleColors.Bold + ConsoleColors.White)
|
||||
});
|
||||
|
||||
sb.Append(Severity switch
|
||||
{
|
||||
DiagnosticSeverity.Error => ConsoleColors.Colorize("error", ConsoleColors.Bold + ConsoleColors.Red),
|
||||
DiagnosticSeverity.Warning => ConsoleColors.Colorize("warning", ConsoleColors.Bold + ConsoleColors.Yellow),
|
||||
DiagnosticSeverity.Info => ConsoleColors.Colorize("info", ConsoleColors.Bold + ConsoleColors.Blue),
|
||||
_ => ConsoleColors.Colorize("unknown", ConsoleColors.Bold + ConsoleColors.White)
|
||||
});
|
||||
if (Span.HasValue)
|
||||
{
|
||||
sb.Append(ConsoleColors.Colorize($" at {Span.Value}", ConsoleColors.Faint));
|
||||
}
|
||||
|
||||
if (Span.HasValue)
|
||||
sb.Append(": ");
|
||||
sb.Append(ConsoleColors.Colorize(Message, ConsoleColors.BrightWhite));
|
||||
|
||||
if (Span.HasValue)
|
||||
{
|
||||
sb.AppendLine();
|
||||
var text = File.ReadAllText(Span.Value.FilePath);
|
||||
|
||||
var tokenizer = new Tokenizer(Span.Value.FilePath, text);
|
||||
tokenizer.Tokenize();
|
||||
|
||||
var lines = text.Split('\n');
|
||||
|
||||
var startLine = Span.Value.Start.Line;
|
||||
var endLine = Span.Value.End.Line;
|
||||
|
||||
const int CONTEXT_LINES = 3;
|
||||
|
||||
var contextStartLine = Math.Max(1, startLine - CONTEXT_LINES);
|
||||
var contextEndLine = Math.Min(lines.Length, endLine + CONTEXT_LINES);
|
||||
|
||||
var numberPadding = contextEndLine.ToString().Length;
|
||||
|
||||
var codePadding = 0;
|
||||
for (var i = contextStartLine - 1; i < contextEndLine && i < lines.Length; i++)
|
||||
{
|
||||
sb.Append(ConsoleColors.Colorize($" at {Span.Value}", ConsoleColors.Faint));
|
||||
var lineLength = lines[i].Length;
|
||||
if (lineLength > codePadding)
|
||||
{
|
||||
codePadding = lineLength;
|
||||
}
|
||||
}
|
||||
|
||||
sb.Append(": ");
|
||||
sb.Append(ConsoleColors.Colorize(Message, ConsoleColors.BrightWhite));
|
||||
sb.Append('╭');
|
||||
sb.Append(new string('─', numberPadding + 2));
|
||||
sb.Append('┬');
|
||||
sb.Append(new string('─', codePadding + 2));
|
||||
sb.Append('╮');
|
||||
sb.AppendLine();
|
||||
|
||||
if (Span.HasValue)
|
||||
for (var i = contextStartLine; i <= contextEndLine; i++)
|
||||
{
|
||||
sb.AppendLine();
|
||||
var text = File.ReadAllText(Span.Value.FilePath);
|
||||
var line = lines[i - 1];
|
||||
|
||||
var lines = text.Split('\n');
|
||||
|
||||
var startLine = Span.Value.Start.Line;
|
||||
var endLine = Span.Value.End.Line;
|
||||
|
||||
const int CONTEXT_LINES = 3;
|
||||
|
||||
var contextStartLine = Math.Max(1, startLine - CONTEXT_LINES);
|
||||
var contextEndLine = Math.Min(lines.Length, endLine + CONTEXT_LINES);
|
||||
|
||||
var numberPadding = contextEndLine.ToString().Length;
|
||||
var codePadding = lines.Skip(contextStartLine - 1).Take(contextEndLine - contextStartLine + 1).Max(x => x.Length);
|
||||
|
||||
sb.Append('╭');
|
||||
sb.Append(new string('─', numberPadding + 2));
|
||||
sb.Append('┬');
|
||||
sb.Append(new string('─', codePadding + 2));
|
||||
sb.Append('╮');
|
||||
sb.Append("│ ");
|
||||
sb.Append(i.ToString().PadRight(numberPadding));
|
||||
sb.Append(" │ ");
|
||||
sb.Append(ApplySyntaxHighlighting(line.PadRight(codePadding), i, tokenizer.Tokens));
|
||||
// sb.Append(line.PadRight(codePadding));
|
||||
sb.Append(" │");
|
||||
sb.AppendLine();
|
||||
|
||||
var tokenizer = new Tokenizer(Span.Value.FilePath, text);
|
||||
tokenizer.Tokenize();
|
||||
|
||||
for (var i = contextStartLine; i <= contextEndLine; i++)
|
||||
if (i >= startLine && i <= endLine)
|
||||
{
|
||||
var line = lines[i - 1];
|
||||
var markerStartColumn = 1;
|
||||
var markerEndColumn = line.Length;
|
||||
|
||||
if (i == startLine)
|
||||
{
|
||||
markerStartColumn = Span.Value.Start.Column;
|
||||
}
|
||||
|
||||
if (i == endLine)
|
||||
{
|
||||
markerEndColumn = Span.Value.End.Column;
|
||||
}
|
||||
|
||||
var markerLength = markerEndColumn - markerStartColumn;
|
||||
var marker = new string('^', markerLength);
|
||||
|
||||
var markerColor = Severity switch
|
||||
{
|
||||
DiagnosticSeverity.Info => ConsoleColors.Blue,
|
||||
DiagnosticSeverity.Warning => ConsoleColors.Yellow,
|
||||
DiagnosticSeverity.Error => ConsoleColors.Red,
|
||||
_ => ConsoleColors.White
|
||||
};
|
||||
|
||||
sb.Append("│ ");
|
||||
sb.Append(i.ToString().PadRight(numberPadding));
|
||||
sb.Append(new string(' ', numberPadding));
|
||||
sb.Append(" │ ");
|
||||
sb.Append(ApplySyntaxHighlighting(line.PadRight(codePadding), i, tokenizer.Tokens));
|
||||
sb.Append(new string(' ', markerStartColumn - 1));
|
||||
sb.Append(ConsoleColors.Colorize(marker, markerColor));
|
||||
sb.Append(new string(' ', codePadding - (markerStartColumn - 1) - markerLength));
|
||||
sb.Append(" │");
|
||||
sb.AppendLine();
|
||||
|
||||
if (i >= startLine && i <= endLine)
|
||||
{
|
||||
var markerStartColumn = 1;
|
||||
var markerEndColumn = line.Length;
|
||||
|
||||
if (i == startLine)
|
||||
{
|
||||
markerStartColumn = Math.Min(Span.Value.Start.Column, 1);
|
||||
}
|
||||
|
||||
if (i == endLine)
|
||||
{
|
||||
markerEndColumn = Math.Min(Span.Value.End.Column, line.Length);
|
||||
}
|
||||
|
||||
var markerLength = markerEndColumn - markerStartColumn;
|
||||
var marker = new string('^', markerLength);
|
||||
|
||||
var markerColor = Severity switch
|
||||
{
|
||||
DiagnosticSeverity.Info => ConsoleColors.Blue,
|
||||
DiagnosticSeverity.Warning => ConsoleColors.Yellow,
|
||||
DiagnosticSeverity.Error => ConsoleColors.Red,
|
||||
_ => ConsoleColors.White
|
||||
};
|
||||
|
||||
sb.Append("│ ");
|
||||
sb.Append(new string(' ', numberPadding));
|
||||
sb.Append(" │ ");
|
||||
sb.Append(new string(' ', markerStartColumn - 1));
|
||||
sb.Append(ConsoleColors.Colorize(marker, markerColor));
|
||||
sb.Append(new string(' ', codePadding - markerEndColumn + 1));
|
||||
sb.Append(" │");
|
||||
sb.AppendLine();
|
||||
}
|
||||
}
|
||||
|
||||
sb.Append('╰');
|
||||
sb.Append(new string('─', numberPadding + 2));
|
||||
sb.Append('┴');
|
||||
sb.Append(new string('─', codePadding + 2));
|
||||
sb.Append('╯');
|
||||
}
|
||||
|
||||
if (Help != null)
|
||||
{
|
||||
sb.AppendLine();
|
||||
sb.Append(ConsoleColors.Colorize($"help: {Help}", ConsoleColors.Cyan));
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
sb.Append('╰');
|
||||
sb.Append(new string('─', numberPadding + 2));
|
||||
sb.Append('┴');
|
||||
sb.Append(new string('─', codePadding + 2));
|
||||
sb.Append('╯');
|
||||
}
|
||||
catch (Exception)
|
||||
|
||||
if (Help != null)
|
||||
{
|
||||
return ConsoleColors.Colorize("Failed to generate error message", ConsoleColors.Red);
|
||||
sb.AppendLine();
|
||||
sb.Append(ConsoleColors.Colorize($"help: {Help}", ConsoleColors.Cyan));
|
||||
}
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static string ApplySyntaxHighlighting(string line, int lineNumber, List<Token> tokens)
|
||||
@@ -219,25 +222,34 @@ public class Diagnostic
|
||||
var tokenStart = token.Span.Start.Column;
|
||||
var tokenEnd = token.Span.End.Column;
|
||||
|
||||
if (tokenStart > currentColumn)
|
||||
if (tokenStart > currentColumn && currentColumn - 1 < line.Length)
|
||||
{
|
||||
var beforeToken = line.Substring(currentColumn - 1, tokenStart - currentColumn);
|
||||
sb.Append(beforeToken);
|
||||
var beforeLength = Math.Min(tokenStart - currentColumn, line.Length - (currentColumn - 1));
|
||||
if (beforeLength > 0)
|
||||
{
|
||||
var beforeToken = line.Substring(currentColumn - 1, beforeLength);
|
||||
sb.Append(beforeToken);
|
||||
}
|
||||
}
|
||||
|
||||
var tokenLength = tokenEnd - tokenStart;
|
||||
if (tokenStart - 1 + tokenLength <= line.Length)
|
||||
if (tokenStart >= 1 && tokenStart - 1 < line.Length && tokenLength > 0)
|
||||
{
|
||||
var tokenText = line.Substring(tokenStart - 1, tokenLength);
|
||||
var availableLength = line.Length - (tokenStart - 1);
|
||||
var actualLength = Math.Min(tokenLength, availableLength);
|
||||
|
||||
var coloredToken = ColorizeToken(token, tokenText);
|
||||
sb.Append(coloredToken);
|
||||
if (actualLength > 0)
|
||||
{
|
||||
var tokenText = line.Substring(tokenStart - 1, actualLength);
|
||||
var coloredToken = ColorizeToken(token, tokenText);
|
||||
sb.Append(coloredToken);
|
||||
}
|
||||
}
|
||||
|
||||
currentColumn = tokenEnd;
|
||||
}
|
||||
|
||||
if (currentColumn <= line.Length)
|
||||
if (currentColumn - 1 < line.Length)
|
||||
{
|
||||
var remaining = line[(currentColumn - 1)..];
|
||||
sb.Append(remaining);
|
||||
|
||||
@@ -90,23 +90,23 @@ public sealed class Tokenizer
|
||||
{
|
||||
try
|
||||
{
|
||||
// Skip whitespace and increment line counter if newline
|
||||
var current = Peek()!.Value;
|
||||
if (char.IsWhiteSpace(current))
|
||||
{
|
||||
if (current is '\n')
|
||||
{
|
||||
_line += 1;
|
||||
_column = 1;
|
||||
// note(nub31): Next increments the column, so 0 is correct here
|
||||
_column = 0;
|
||||
}
|
||||
|
||||
Next();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip single line comments but keep newline so next iteration increments the line counter
|
||||
if (current == '/' && Peek(1) == '/')
|
||||
{
|
||||
// note(nub31): Keep newline so next iteration increments the line counter
|
||||
while (Peek() is not '\n')
|
||||
{
|
||||
Next();
|
||||
|
||||
@@ -4,7 +4,7 @@ module "main"
|
||||
|
||||
extern "main" func main(args: []cstring): i64
|
||||
{
|
||||
raylib::SetConfigFlags(4 | 64)
|
||||
raylib: :SetConfigFlags(4 | 64)
|
||||
|
||||
raylib::InitWindow(1600, 900, "Hi from nub-lang")
|
||||
defer raylib::CloseWindow()
|
||||
|
||||
Reference in New Issue
Block a user