From 163bf677ae1575fe5f7ad499bdb30bd3b9b0bcb0 Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Wed, 4 Mar 2026 23:02:40 +0100 Subject: [PATCH] Add line formatting with auto indentation and fix syntax highlighting in editor --- YesNt.CodeEditor/Editor.cs | 112 ++++++++++++++++++++++++++ YesNt.CodeEditor/InputHandler.cs | 64 +++++++++------ YesNt.CodeEditor/SyntaxHighlighter.cs | 9 ++- 3 files changed, 158 insertions(+), 27 deletions(-) diff --git a/YesNt.CodeEditor/Editor.cs b/YesNt.CodeEditor/Editor.cs index 6bd5b21..6fead3e 100644 --- a/YesNt.CodeEditor/Editor.cs +++ b/YesNt.CodeEditor/Editor.cs @@ -203,6 +203,118 @@ internal class TextEditor return padding; } + public void FormatLines() + { + const int indentationSize = 4; + List blockStack = []; + + for (int i = 0; i < Lines.Count; i++) + { + string trimmed = Lines[i].Trim(' '); + if (string.IsNullOrWhiteSpace(trimmed)) + { + Lines[i] = string.Empty; + continue; + } + + if (trimmed.StartsWith('#')) + { + Lines[i] = trimmed; + continue; + } + + if (trimmed == "else:") + { + for (int j = blockStack.Count - 1; j >= 0; j--) + { + if (blockStack[j] is "if" or "else") + { + blockStack.RemoveAt(j); + break; + } + } + } + bool isTerminatingStatement = trimmed == "exit" + || trimmed.StartsWith("throw ", StringComparison.Ordinal) + || trimmed.StartsWith("error ", StringComparison.Ordinal); + bool closesFunctionBlock = isTerminatingStatement && blockStack.Count > 0 && blockStack[^1] == "func"; + + if (trimmed == "end_if") + { + for (int j = blockStack.Count - 1; j >= 0; j--) + { + if (blockStack[j] is "if" or "else") + { + blockStack.RemoveAt(j); + break; + } + } + } + else if (trimmed == "end_while") + { + for (int j = blockStack.Count - 1; j >= 0; j--) + { + if (blockStack[j] == "while") + { + blockStack.RemoveAt(j); + break; + } + } + } + else if (trimmed == "return") + { + for (int j = blockStack.Count - 1; j >= 0; j--) + { + if (blockStack[j] == "func") + { + blockStack.RemoveAt(j); + break; + } + } + } + + int lineIndentation = closesFunctionBlock ? Math.Max(0, blockStack.Count - 1) : blockStack.Count; + Lines[i] = new string(' ', lineIndentation * indentationSize) + trimmed; + + if (!isTerminatingStatement && ( + (trimmed.StartsWith("if ", StringComparison.Ordinal) && trimmed.EndsWith(':')) + || (trimmed.StartsWith("while ", StringComparison.Ordinal) && trimmed.EndsWith(':')) + || (trimmed.StartsWith("func ", StringComparison.Ordinal) && trimmed.EndsWith(':')) + || trimmed == "else:")) + { + if (trimmed.StartsWith("if ", StringComparison.Ordinal)) + { + blockStack.Add("if"); + } + else if (trimmed.StartsWith("while ", StringComparison.Ordinal)) + { + blockStack.Add("while"); + } + else if (trimmed.StartsWith("func ", StringComparison.Ordinal)) + { + blockStack.Add("func"); + } + else + { + blockStack.Add("else"); + } + } + + if (isTerminatingStatement) + { + while (blockStack.Count > 0 && blockStack[^1] != "func") + { + blockStack.RemoveAt(blockStack.Count - 1); + } + + if (closesFunctionBlock && blockStack.Count > 0 && blockStack[^1] == "func") + { + blockStack.RemoveAt(blockStack.Count - 1); + } + } + } + } + private static string ToLiteral(string input) { return Microsoft.CodeAnalysis.CSharp.SymbolDisplay.FormatLiteral(input, false); diff --git a/YesNt.CodeEditor/InputHandler.cs b/YesNt.CodeEditor/InputHandler.cs index bf24a9e..5eb365d 100644 --- a/YesNt.CodeEditor/InputHandler.cs +++ b/YesNt.CodeEditor/InputHandler.cs @@ -47,6 +47,12 @@ internal class InputHandler(TextEditor textEditor) case ConsoleKey.E: textEditor.CursorPosition.X = textEditor.Lines.Count > textEditor.CursorPosition.Y ? textEditor.Lines[textEditor.CursorPosition.Y].TrimEnd().Length : 0; return true; + + case ConsoleKey.F: + textEditor.FormatLines(); + textEditor.Display(true); + WriteStatus("Formatted!"); + return true; } } if (keyInfo.Key == ConsoleKey.DownArrow) @@ -274,6 +280,11 @@ internal class InputHandler(TextEditor textEditor) WriteStatus(string.Empty); break; + case "format": + textEditor.FormatLines(); + WriteStatus("Formatted!"); + break; + case "exit": return false; @@ -331,30 +342,37 @@ internal class InputHandler(TextEditor textEditor) private void ExecuteWithDebugScreen(string saveInput, bool debugMode, bool stepMode) { - if (textEditor.Save(saveInput, true)) + string[] parts = saveInput.Split(' ', StringSplitOptions.RemoveEmptyEntries); + bool hasPathArgument = parts.Length > 1; + bool canRunUnsavedBuffer = !hasPathArgument && string.IsNullOrWhiteSpace(textEditor.CurrentPath); + + bool canExecute = canRunUnsavedBuffer || textEditor.Save(saveInput, true); + if (!canExecute) { - textEditor.EditMode = Mode.Debug; - textEditor.IsStepDebugMode = stepMode; - Console.Clear(); - Console.CursorVisible = true; - - if (debugMode) - { - textEditor.YesNtInterpreter.Execute(textEditor.CurrentPath, true); - } - else - { - textEditor.YesNtInterpreter.Execute(textEditor.CurrentPath); - } - - while (Console.KeyAvailable) - { - _ = Console.ReadKey(true); - } - _ = Console.ReadKey(); - WriteStatus(string.Empty); - textEditor.IsStepDebugMode = false; - textEditor.EditMode = Mode.Command; + return; } + + textEditor.EditMode = Mode.Debug; + textEditor.IsStepDebugMode = stepMode; + Console.Clear(); + Console.CursorVisible = true; + + if (canRunUnsavedBuffer) + { + textEditor.YesNtInterpreter.Execute([.. textEditor.Lines], debugMode); + } + else + { + textEditor.YesNtInterpreter.Execute(textEditor.CurrentPath, debugMode); + } + + while (Console.KeyAvailable) + { + _ = Console.ReadKey(true); + } + _ = Console.ReadKey(); + WriteStatus(string.Empty); + textEditor.IsStepDebugMode = false; + textEditor.EditMode = Mode.Command; } } diff --git a/YesNt.CodeEditor/SyntaxHighlighter.cs b/YesNt.CodeEditor/SyntaxHighlighter.cs index 7b8daa1..8db25f7 100644 --- a/YesNt.CodeEditor/SyntaxHighlighter.cs +++ b/YesNt.CodeEditor/SyntaxHighlighter.cs @@ -30,7 +30,7 @@ internal partial class SyntaxHighlighter(ReadOnlyCollection statement.Name.Trim() }; input = input.TrimEnd(' '); - if (statement.SearchMode == SearchMode.StartOfLine && input.StartsWith(name)) + string inputTrim = input.Trim(' '); + if (statement.SearchMode == SearchMode.StartOfLine && inputTrim.StartsWith(name)) { if (statement.Separator is not null && input.Contains(statement.Separator)) { @@ -78,7 +79,7 @@ internal partial class SyntaxHighlighter(ReadOnlyCollection