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