From ad55d26d58bd422613949504da05dbb23b00d6ca Mon Sep 17 00:00:00 2001 From: NotroDev Date: Tue, 20 Aug 2024 10:06:16 +0200 Subject: [PATCH 01/28] Fix close project functionality --- SkEditor/Utilities/Projects/Elements/Folder.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/SkEditor/Utilities/Projects/Elements/Folder.cs b/SkEditor/Utilities/Projects/Elements/Folder.cs index 8f97c85..51955a4 100644 --- a/SkEditor/Utilities/Projects/Elements/Folder.cs +++ b/SkEditor/Utilities/Projects/Elements/Folder.cs @@ -1,6 +1,8 @@ -using Avalonia.Threading; +using Avalonia.Controls; +using Avalonia.Threading; using CommunityToolkit.Mvvm.Input; using SkEditor.API; +using SkEditor.Controls.Sidebar; using SkEditor.Utilities.Files; using SkEditor.Views; using SkEditor.Views.Projects; @@ -9,6 +11,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; +using static SkEditor.Controls.Sidebar.ExplorerSidebarPanel; namespace SkEditor.Utilities.Projects.Elements; @@ -24,6 +27,7 @@ public Folder(string folder, Folder? parent = null) StorageFolderPath = folder; Name = Path.GetFileName(folder); IsFile = false; + IsRootFolder = parent is null; Children = []; LoadChildren(); @@ -34,6 +38,7 @@ public Folder(string folder, Folder? parent = null) CopyAbsolutePathCommand = new RelayCommand(CopyAbsolutePath); CreateNewFileCommand = new RelayCommand(() => CreateNewElement(true)); CreateNewFolderCommand = new RelayCommand(() => CreateNewElement(false)); + CloseProjectCommand = new RelayCommand(CloseProject); } private async void LoadChildren() @@ -56,6 +61,15 @@ public void DeleteFolder() Parent.Children.Remove(this); } + private static void CloseProject() + { + ProjectOpener.FileTreeView.ItemsSource = null; + Folder? ProjectRootFolder = null; + ExplorerPanel? Panel = Registries.SidebarPanels.FirstOrDefault(x => x is ExplorerPanel) as ExplorerPanel; + StackPanel NoFolderMessage = Panel.Panel.NoFolderMessage; + NoFolderMessage.IsVisible = ProjectRootFolder == null; + } + public override void RenameElement(string newName, bool move = true) { var newPath = Path.Combine(Parent.StorageFolderPath, newName); From 0096a885ec288a3d3135c105930e56a4a07c11b0 Mon Sep 17 00:00:00 2001 From: NotroDev Date: Sun, 1 Sep 2024 09:53:35 +0200 Subject: [PATCH 02/28] closes #121 --- SkEditor/Controls/Sidebar/ExplorerSidebarPanel.axaml | 2 +- SkEditor/Languages/English.xaml | 1 + SkEditor/Languages/Polish.xaml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/SkEditor/Controls/Sidebar/ExplorerSidebarPanel.axaml b/SkEditor/Controls/Sidebar/ExplorerSidebarPanel.axaml index 5df6b52..7ec04d6 100644 --- a/SkEditor/Controls/Sidebar/ExplorerSidebarPanel.axaml +++ b/SkEditor/Controls/Sidebar/ExplorerSidebarPanel.axaml @@ -81,7 +81,7 @@ - + diff --git a/SkEditor/Languages/English.xaml b/SkEditor/Languages/English.xaml index ff93d26..4498eec 100644 --- a/SkEditor/Languages/English.xaml +++ b/SkEditor/Languages/English.xaml @@ -66,6 +66,7 @@ Refresh syntax + Delete from Disk Open in explorer Copy relative path Copy absolute path diff --git a/SkEditor/Languages/Polish.xaml b/SkEditor/Languages/Polish.xaml index 2cd1304..4f274fe 100644 --- a/SkEditor/Languages/Polish.xaml +++ b/SkEditor/Languages/Polish.xaml @@ -66,6 +66,7 @@ Odśwież składnię + Usuń z dysku Otwórz w eksploratorze Skopiuj ścieżkę względną Skopiuj ścieżkę bezwzględną From f91d59186dcb732b806f66512fd7561401c65dc1 Mon Sep 17 00:00:00 2001 From: NotroDev Date: Fri, 20 Sep 2024 21:01:22 +0200 Subject: [PATCH 03/28] Fix button texts in the dialog not respecting the translate parameter --- SkEditor/Utilities/InternalAPI/Classes/Windows.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SkEditor/Utilities/InternalAPI/Classes/Windows.cs b/SkEditor/Utilities/InternalAPI/Classes/Windows.cs index 2f8cbad..067e744 100644 --- a/SkEditor/Utilities/InternalAPI/Classes/Windows.cs +++ b/SkEditor/Utilities/InternalAPI/Classes/Windows.cs @@ -47,8 +47,8 @@ public async Task ShowDialog(string title, { Title = translate ? TryGetTranslation(title) : title, Background = background as ImmutableSolidColorBrush, - PrimaryButtonText = TryGetTranslation(primaryButtonText), - CloseButtonText = TryGetTranslation(cancelButtonText), + PrimaryButtonText = translate ? TryGetTranslation(primaryButtonText) : primaryButtonText, + CloseButtonText = translate ? TryGetTranslation(cancelButtonText) : cancelButtonText, }; icon = icon switch From 8d734fe7d0c4890a85b170cc3cd4fd61fa535562 Mon Sep 17 00:00:00 2001 From: NotroDev Date: Fri, 20 Sep 2024 21:02:04 +0200 Subject: [PATCH 04/28] Add a confirmation dialog for deleting a folder/file in the project --- SkEditor/Utilities/Projects/Elements/File.cs | 9 ++++++++- SkEditor/Utilities/Projects/Elements/Folder.cs | 12 ++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/SkEditor/Utilities/Projects/Elements/File.cs b/SkEditor/Utilities/Projects/Elements/File.cs index 2586ba7..c8cef2f 100644 --- a/SkEditor/Utilities/Projects/Elements/File.cs +++ b/SkEditor/Utilities/Projects/Elements/File.cs @@ -1,4 +1,5 @@ using CommunityToolkit.Mvvm.Input; +using FluentAvalonia.UI.Controls; using SkEditor.API; using SkEditor.Utilities.Files; using System; @@ -36,8 +37,14 @@ public void OpenInExplorer() Process.Start(new ProcessStartInfo(Parent.StorageFolderPath) { UseShellExecute = true }); } - public void DeleteFile() + public async void DeleteFile() { + var result = await SkEditorAPI.Windows.ShowDialog("Delete File", + $"Are you sure you want to delete {Name} from the file system?", + icon: Symbol.Delete, primaryButtonText: "Delete", cancelButtonText: "Cancel", translate: false); + + if (result != ContentDialogResult.Primary) return; + System.IO.File.Delete(StorageFilePath); Parent.Children.Remove(this); } diff --git a/SkEditor/Utilities/Projects/Elements/Folder.cs b/SkEditor/Utilities/Projects/Elements/Folder.cs index 51955a4..e4e80ee 100644 --- a/SkEditor/Utilities/Projects/Elements/Folder.cs +++ b/SkEditor/Utilities/Projects/Elements/Folder.cs @@ -1,6 +1,7 @@ using Avalonia.Controls; using Avalonia.Threading; using CommunityToolkit.Mvvm.Input; +using FluentAvalonia.UI.Controls; using SkEditor.API; using SkEditor.Controls.Sidebar; using SkEditor.Utilities.Files; @@ -55,10 +56,17 @@ public void OpenInExplorer() Process.Start(new ProcessStartInfo(StorageFolderPath) { UseShellExecute = true }); } - public void DeleteFolder() + public async void DeleteFolder() { + var result = await SkEditorAPI.Windows.ShowDialog("Delete File", + $"Are you sure you want to delete {Name} from the file system?", + icon: Symbol.Delete, primaryButtonText: "Delete", cancelButtonText: "Cancel", translate: false); + + if (result != ContentDialogResult.Primary) return; + Directory.Delete(StorageFolderPath, true); - Parent.Children.Remove(this); + Parent?.Children?.Remove(this); + if (Parent is null) CloseProject(); } private static void CloseProject() From b7e2ee819b044f4d1d5aeebb9db0c85e9d68c9bf Mon Sep 17 00:00:00 2001 From: NotroDev Date: Fri, 20 Sep 2024 21:03:30 +0200 Subject: [PATCH 05/28] Update libraries --- SkEditor/SkEditor.csproj | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/SkEditor/SkEditor.csproj b/SkEditor/SkEditor.csproj index 4b091fd..a94224e 100644 --- a/SkEditor/SkEditor.csproj +++ b/SkEditor/SkEditor.csproj @@ -48,18 +48,18 @@ - + - - + + - + @@ -67,7 +67,7 @@ - + From 4446213a11e4da4d5560016c6c5e5f65cee528a0 Mon Sep 17 00:00:00 2001 From: NotroDev Date: Sat, 28 Sep 2024 15:29:26 +0200 Subject: [PATCH 06/28] Correct margin of the tabs --- SkEditor/Views/MainWindow.axaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SkEditor/Views/MainWindow.axaml b/SkEditor/Views/MainWindow.axaml index 2e2e19c..7bb1948 100644 --- a/SkEditor/Views/MainWindow.axaml +++ b/SkEditor/Views/MainWindow.axaml @@ -23,7 +23,7 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/SkEditor/Views/TerminalWindow.axaml.cs b/SkEditor/Views/TerminalWindow.axaml.cs new file mode 100644 index 0000000..9561cc9 --- /dev/null +++ b/SkEditor/Views/TerminalWindow.axaml.cs @@ -0,0 +1,101 @@ +using Avalonia.Input; +using Avalonia.Media; +using Avalonia.Threading; +using CommunityToolkit.Mvvm.Input; +using FluentAvalonia.UI.Windowing; +using Serilog; +using System; +using System.Diagnostics; + +namespace SkEditor.Views; +public partial class TerminalWindow : AppWindow +{ + private Process _process; + + public TerminalWindow() + { + InitializeComponent(); + Focusable = true; + + LoadTerminal(); + AssignEvents(); + } + + private void LoadTerminal() + { + InitializeProcess(); + _process.Start(); + + SetupProcessHandlers(); + } + + private void InitializeProcess() + { + ProcessStartInfo startInfo = new() + { + FileName = "cmd.exe", + RedirectStandardInput = true, + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true, + WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), + }; + + _process = new Process + { + StartInfo = startInfo, + EnableRaisingEvents = true + }; + } + + private void SetupProcessHandlers() + { + _process.OutputDataReceived += HandleOutput; + _process.ErrorDataReceived += HandleOutput; + + _process.BeginOutputReadLine(); + _process.BeginErrorReadLine(); + } + + private void HandleOutput(object sender, DataReceivedEventArgs e) + { + Dispatcher.UIThread.InvokeAsync(() => OutputTextBox.Text += e.Data + Environment.NewLine); + } + + private void AssignEvents() + { + InputTextBox.KeyDown += (sender, e) => + { + if (e.Key == Key.Enter) + { + var text = InputTextBox.Text; + InputTextBox.Text = string.Empty; + + _process.StandardInput.WriteLine(text); + _process.StandardInput.Flush(); + } + }; + + Closing += (sender, e) => + { + try + { + _process.StandardInput.Close(); + + if (!_process.WaitForExit(1000)) + { + _process.Kill(entireProcessTree: true); + } + + _process.CancelOutputRead(); + _process.CancelErrorRead(); + _process.Dispose(); + } + catch (Exception ex) + { + Log.Error(ex, "Error while closing terminal process"); + } + }; + } +} \ No newline at end of file From 91fd93e085ee89df804e716c69dfec74bb07e5a9 Mon Sep 17 00:00:00 2001 From: GliczDev <67753196+GliczDev@users.noreply.github.com> Date: Sun, 6 Oct 2024 21:28:25 +0200 Subject: [PATCH 10/28] More terminal window work --- SkEditor/App.axaml.cs | 2 + SkEditor/Views/TerminalWindow.axaml.cs | 78 +++++++++++++++++--------- 2 files changed, 55 insertions(+), 25 deletions(-) diff --git a/SkEditor/App.axaml.cs b/SkEditor/App.axaml.cs index 767ec96..75c6608 100644 --- a/SkEditor/App.axaml.cs +++ b/SkEditor/App.axaml.cs @@ -29,6 +29,8 @@ public override async void OnFrameworkInitializationCompleted() { base.OnFrameworkInitializationCompleted(); + Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); + Log.Logger = new LoggerConfiguration() .MinimumLevel.Debug() .WriteTo.File(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), diff --git a/SkEditor/Views/TerminalWindow.axaml.cs b/SkEditor/Views/TerminalWindow.axaml.cs index 9561cc9..8aaa136 100644 --- a/SkEditor/Views/TerminalWindow.axaml.cs +++ b/SkEditor/Views/TerminalWindow.axaml.cs @@ -1,15 +1,19 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Text; +using System.Threading.Tasks; using Avalonia.Input; -using Avalonia.Media; using Avalonia.Threading; -using CommunityToolkit.Mvvm.Input; using FluentAvalonia.UI.Windowing; using Serilog; -using System; -using System.Diagnostics; namespace SkEditor.Views; + public partial class TerminalWindow : AppWindow { + private StreamWriter _inputWriter; private Process _process; public TerminalWindow() @@ -21,6 +25,11 @@ public TerminalWindow() AssignEvents(); } + private static Encoding GetTerminalEncoding() + { + return Encoding.GetEncoding(CultureInfo.CurrentCulture.TextInfo.OEMCodePage); + } + private void LoadTerminal() { InitializeProcess(); @@ -31,15 +40,22 @@ private void LoadTerminal() private void InitializeProcess() { + Encoding encoding = GetTerminalEncoding(); + ProcessStartInfo startInfo = new() { FileName = "cmd.exe", + UseShellExecute = false, + CreateNoWindow = true, + RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, - UseShellExecute = false, - CreateNoWindow = true, - WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), + + StandardOutputEncoding = encoding, + StandardErrorEncoding = encoding, + + WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) }; _process = new Process @@ -51,45 +67,57 @@ private void InitializeProcess() private void SetupProcessHandlers() { - _process.OutputDataReceived += HandleOutput; - _process.ErrorDataReceived += HandleOutput; + Task.Run(() => ReadAsync(_process.StandardOutput)); + Task.Run(() => ReadAsync(_process.StandardError)); - _process.BeginOutputReadLine(); - _process.BeginErrorReadLine(); + _inputWriter = new StreamWriter(_process.StandardInput.BaseStream, GetTerminalEncoding()) + { + AutoFlush = true + }; } - private void HandleOutput(object sender, DataReceivedEventArgs e) + private async Task ReadAsync(StreamReader reader) { - Dispatcher.UIThread.InvokeAsync(() => OutputTextBox.Text += e.Data + Environment.NewLine); + while (!_process.HasExited) + { + char[] buffer = new char[1024]; + + int bytesRead = await reader.ReadAsync(buffer, 0, buffer.Length); + if (bytesRead <= 0) + { + continue; + } + + string output = new(buffer, 0, bytesRead); + + Dispatcher.UIThread.Invoke(() => OutputTextBox.Text += output); + } } private void AssignEvents() { - InputTextBox.KeyDown += (sender, e) => + InputTextBox.KeyDown += (_, e) => { - if (e.Key == Key.Enter) + if (e.Key != Key.Enter) { - var text = InputTextBox.Text; - InputTextBox.Text = string.Empty; - - _process.StandardInput.WriteLine(text); - _process.StandardInput.Flush(); + return; } + + _inputWriter.WriteLine(InputTextBox.Text); + InputTextBox.Text = string.Empty; }; - Closing += (sender, e) => + Closing += (_, _) => { try { - _process.StandardInput.Close(); + _inputWriter.Close(); if (!_process.WaitForExit(1000)) { - _process.Kill(entireProcessTree: true); + _process.Kill(true); } - _process.CancelOutputRead(); - _process.CancelErrorRead(); _process.Dispose(); } catch (Exception ex) From b805036f035f3087baefbb9b6f633aa4cc1dd302 Mon Sep 17 00:00:00 2001 From: GliczDev <67753196+GliczDev@users.noreply.github.com> Date: Thu, 10 Oct 2024 11:30:13 +0200 Subject: [PATCH 11/28] Replace TextBox with TextEditor in TerminalWindow --- SkEditor/Views/TerminalWindow.axaml | 50 +++++++++++++---------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/SkEditor/Views/TerminalWindow.axaml b/SkEditor/Views/TerminalWindow.axaml index 996e7eb..bf9d154 100644 --- a/SkEditor/Views/TerminalWindow.axaml +++ b/SkEditor/Views/TerminalWindow.axaml @@ -2,37 +2,33 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:ui="using:FluentAvalonia.UI.Controls" + xmlns:ae="using:AvaloniaEdit" + xmlns:aee="using:AvaloniaEdit.Editing" mc:Ignorable="d" x:Class="SkEditor.Views.TerminalWindow" Icon="/Assets/SkEditor.ico" - Title="Terminal" Height="400" Width="800" CanResize="False" WindowStartupLocation="CenterOwner" Theme="{StaticResource SmallWindowTheme}"> + Title="Terminal" Height="400" Width="800" CanResize="False" WindowStartupLocation="CenterOwner" + Theme="{StaticResource SmallWindowTheme}"> - - - - + + + - - + + - - - - - + + \ No newline at end of file From 1302d528ba316a5f0ae5db1325fdae0fb8d28b27 Mon Sep 17 00:00:00 2001 From: NotroDev Date: Thu, 10 Oct 2024 16:18:06 +0200 Subject: [PATCH 12/28] Fix rounded corners in terminal --- SkEditor/Views/TerminalWindow.axaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/SkEditor/Views/TerminalWindow.axaml b/SkEditor/Views/TerminalWindow.axaml index bf9d154..b862049 100644 --- a/SkEditor/Views/TerminalWindow.axaml +++ b/SkEditor/Views/TerminalWindow.axaml @@ -15,13 +15,16 @@ - + + From 16f3904df7c1b3bfd81fa918a83b9de898492d65 Mon Sep 17 00:00:00 2001 From: NotroDev Date: Thu, 10 Oct 2024 16:38:04 +0200 Subject: [PATCH 13/28] Make caret transparent --- SkEditor/Views/TerminalWindow.axaml | 2 +- SkEditor/Views/TerminalWindow.axaml.cs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/SkEditor/Views/TerminalWindow.axaml b/SkEditor/Views/TerminalWindow.axaml index b862049..232da18 100644 --- a/SkEditor/Views/TerminalWindow.axaml +++ b/SkEditor/Views/TerminalWindow.axaml @@ -30,7 +30,7 @@ - + diff --git a/SkEditor/Views/TerminalWindow.axaml.cs b/SkEditor/Views/TerminalWindow.axaml.cs index 8aaa136..89f9a51 100644 --- a/SkEditor/Views/TerminalWindow.axaml.cs +++ b/SkEditor/Views/TerminalWindow.axaml.cs @@ -5,6 +5,7 @@ using System.Text; using System.Threading.Tasks; using Avalonia.Input; +using Avalonia.Media; using Avalonia.Threading; using FluentAvalonia.UI.Windowing; using Serilog; @@ -23,6 +24,8 @@ public TerminalWindow() LoadTerminal(); AssignEvents(); + + OutputTextBox.TextArea.Caret.CaretBrush = Brushes.Transparent; } private static Encoding GetTerminalEncoding() From 7136755a3115d5f3c61e95e5d9d87013c3eeac12 Mon Sep 17 00:00:00 2001 From: NotroDev Date: Thu, 10 Oct 2024 16:41:43 +0200 Subject: [PATCH 14/28] Correct hard-coded terminal corner radius --- SkEditor/Views/TerminalWindow.axaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SkEditor/Views/TerminalWindow.axaml b/SkEditor/Views/TerminalWindow.axaml index 232da18..c7f3df6 100644 --- a/SkEditor/Views/TerminalWindow.axaml +++ b/SkEditor/Views/TerminalWindow.axaml @@ -24,7 +24,7 @@ From 31739a15d8e3a21105a6688fa452d269ad5ce395 Mon Sep 17 00:00:00 2001 From: GliczDev <67753196+GliczDev@users.noreply.github.com> Date: Fri, 11 Oct 2024 17:48:24 +0200 Subject: [PATCH 15/28] Even more terminal window work --- SkEditor/Views/TerminalWindow.axaml.cs | 52 +++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/SkEditor/Views/TerminalWindow.axaml.cs b/SkEditor/Views/TerminalWindow.axaml.cs index 89f9a51..a69e595 100644 --- a/SkEditor/Views/TerminalWindow.axaml.cs +++ b/SkEditor/Views/TerminalWindow.axaml.cs @@ -2,11 +2,14 @@ using System.Diagnostics; using System.Globalization; using System.IO; +using System.Linq; using System.Text; +using System.Text.RegularExpressions; using System.Threading.Tasks; using Avalonia.Input; using Avalonia.Media; using Avalonia.Threading; +using AvaloniaEdit.Document; using FluentAvalonia.UI.Windowing; using Serilog; @@ -14,6 +17,7 @@ namespace SkEditor.Views; public partial class TerminalWindow : AppWindow { + private readonly object _lock = new (); private StreamWriter _inputWriter; private Process _process; @@ -93,8 +97,54 @@ private async Task ReadAsync(StreamReader reader) string output = new(buffer, 0, bytesRead); - Dispatcher.UIThread.Invoke(() => OutputTextBox.Text += output); + Dispatcher.UIThread.Invoke(() => + { + lock (_lock) + { + foreach (string part in Regex.Split(output, "(?=\r)")) + { + AppendPart(part); + } + } + }); + } + } + + private void AppendPart(string part) + { + if (part.StartsWith("\r\n")) + { + OutputTextBox.Text += part; + OutputTextBox.CaretOffset = OutputTextBox.Text.Length; + return; + } + + TextDocument document = OutputTextBox.Document; + DocumentLine caretLine = document.GetLineByOffset(OutputTextBox.CaretOffset); + + if (part.Length > 0 && part.First() == '\r') + { + OutputTextBox.CaretOffset = caretLine.Offset; + part = part[1..]; + } + + if (part.Length > 0 && part.First() == '\n') + { + OutputTextBox.Document.Text += '\n'; + OutputTextBox.CaretOffset = caretLine.NextLine.Offset; + part = part[1..]; } + + if (part.Length <= 0) + { + return; + } + + int caretOffset = OutputTextBox.CaretOffset; + int lineLength = document.GetLineByOffset(caretOffset).EndOffset - caretOffset; + + document.Replace(caretOffset, Math.Min(part.Length, lineLength), part); + OutputTextBox.CaretOffset = OutputTextBox.Text.Length; } private void AssignEvents() From df354c5ee949d4666cbf063830a2bbc9cc6a06fa Mon Sep 17 00:00:00 2001 From: GliczDev <67753196+GliczDev@users.noreply.github.com> Date: Fri, 11 Oct 2024 19:24:01 +0200 Subject: [PATCH 16/28] Fix unhandled exception in terminal window --- SkEditor/Views/TerminalWindow.axaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SkEditor/Views/TerminalWindow.axaml.cs b/SkEditor/Views/TerminalWindow.axaml.cs index a69e595..9864c4a 100644 --- a/SkEditor/Views/TerminalWindow.axaml.cs +++ b/SkEditor/Views/TerminalWindow.axaml.cs @@ -131,7 +131,7 @@ private void AppendPart(string part) if (part.Length > 0 && part.First() == '\n') { OutputTextBox.Document.Text += '\n'; - OutputTextBox.CaretOffset = caretLine.NextLine.Offset; + OutputTextBox.CaretOffset = caretLine.EndOffset + 1; part = part[1..]; } From 706f86c884ca702d0fdc47208b4c718a4f9189e3 Mon Sep 17 00:00:00 2001 From: GliczDev <67753196+GliczDev@users.noreply.github.com> Date: Fri, 11 Oct 2024 19:56:14 +0200 Subject: [PATCH 17/28] Small TerminalWindow code reformat --- SkEditor/Views/TerminalWindow.axaml.cs | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/SkEditor/Views/TerminalWindow.axaml.cs b/SkEditor/Views/TerminalWindow.axaml.cs index 9864c4a..a5f4419 100644 --- a/SkEditor/Views/TerminalWindow.axaml.cs +++ b/SkEditor/Views/TerminalWindow.axaml.cs @@ -17,7 +17,9 @@ namespace SkEditor.Views; public partial class TerminalWindow : AppWindow { - private readonly object _lock = new (); + private const string CrSplitPattern = "(?=\r)"; + + private readonly object _lock = new(); private StreamWriter _inputWriter; private Process _process; @@ -32,6 +34,9 @@ public TerminalWindow() OutputTextBox.TextArea.Caret.CaretBrush = Brushes.Transparent; } + [GeneratedRegex(CrSplitPattern)] + private static partial Regex CrSplitter(); + private static Encoding GetTerminalEncoding() { return Encoding.GetEncoding(CultureInfo.CurrentCulture.TextInfo.OEMCodePage); @@ -97,16 +102,15 @@ private async Task ReadAsync(StreamReader reader) string output = new(buffer, 0, bytesRead); - Dispatcher.UIThread.Invoke(() => - { - lock (_lock) - { - foreach (string part in Regex.Split(output, "(?=\r)")) - { - AppendPart(part); - } - } - }); + Dispatcher.UIThread.Invoke(() => AppendText(output)); + } + } + + private void AppendText(string text) + { + lock (_lock) + { + Array.ForEach(CrSplitter().Split(text), AppendPart); } } From 2e2aff163759ef97748286110525576eec0da147 Mon Sep 17 00:00:00 2001 From: GliczDev <67753196+GliczDev@users.noreply.github.com> Date: Fri, 11 Oct 2024 20:21:12 +0200 Subject: [PATCH 18/28] Some more terminal window tweaks --- SkEditor/Views/TerminalWindow.axaml.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/SkEditor/Views/TerminalWindow.axaml.cs b/SkEditor/Views/TerminalWindow.axaml.cs index a5f4419..4943f2f 100644 --- a/SkEditor/Views/TerminalWindow.axaml.cs +++ b/SkEditor/Views/TerminalWindow.axaml.cs @@ -32,6 +32,9 @@ public TerminalWindow() AssignEvents(); OutputTextBox.TextArea.Caret.CaretBrush = Brushes.Transparent; + + OutputTextBox.Options.EnableHyperlinks = false; + OutputTextBox.Options.AllowScrollBelowDocument = false; } [GeneratedRegex(CrSplitPattern)] @@ -110,7 +113,14 @@ private void AppendText(string text) { lock (_lock) { + bool atEnd = OutputTextBox.ExtentHeight <= OutputTextBox.VerticalOffset + OutputTextBox.ViewportHeight; + Array.ForEach(CrSplitter().Split(text), AppendPart); + + if (atEnd) + { + OutputTextBox.ScrollToEnd(); + } } } From 77b345b8e93e3ae6a4d26b6e58aa5e23225130b6 Mon Sep 17 00:00:00 2001 From: GliczDev <67753196+GliczDev@users.noreply.github.com> Date: Fri, 11 Oct 2024 21:51:18 +0200 Subject: [PATCH 19/28] Simplify AppendPart CRLF handling in TerminalWindow --- SkEditor/Views/TerminalWindow.axaml.cs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/SkEditor/Views/TerminalWindow.axaml.cs b/SkEditor/Views/TerminalWindow.axaml.cs index 4943f2f..3b0e17e 100644 --- a/SkEditor/Views/TerminalWindow.axaml.cs +++ b/SkEditor/Views/TerminalWindow.axaml.cs @@ -126,26 +126,21 @@ private void AppendText(string text) private void AppendPart(string part) { - if (part.StartsWith("\r\n")) - { - OutputTextBox.Text += part; - OutputTextBox.CaretOffset = OutputTextBox.Text.Length; - return; - } - TextDocument document = OutputTextBox.Document; DocumentLine caretLine = document.GetLineByOffset(OutputTextBox.CaretOffset); + int offset = caretLine.Offset; + int endOffset = caretLine.EndOffset; if (part.Length > 0 && part.First() == '\r') { - OutputTextBox.CaretOffset = caretLine.Offset; + OutputTextBox.CaretOffset = offset; part = part[1..]; } if (part.Length > 0 && part.First() == '\n') { OutputTextBox.Document.Text += '\n'; - OutputTextBox.CaretOffset = caretLine.EndOffset + 1; + OutputTextBox.CaretOffset = endOffset + 1; part = part[1..]; } From c8aa54009391126077853afe946242b92a373e93 Mon Sep 17 00:00:00 2001 From: GliczDev <67753196+GliczDev@users.noreply.github.com> Date: Sat, 12 Oct 2024 18:59:14 +0200 Subject: [PATCH 20/28] Indicate that the terminal does not support colors --- SkEditor/Views/TerminalWindow.axaml.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/SkEditor/Views/TerminalWindow.axaml.cs b/SkEditor/Views/TerminalWindow.axaml.cs index 3b0e17e..eb0d60f 100644 --- a/SkEditor/Views/TerminalWindow.axaml.cs +++ b/SkEditor/Views/TerminalWindow.axaml.cs @@ -70,7 +70,14 @@ private void InitializeProcess() StandardOutputEncoding = encoding, StandardErrorEncoding = encoding, - WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), + + EnvironmentVariables = + { + ["COLORTERM"] = "", + ["NO_COLOR"] = "1", + ["TERM"] = "dumb" + } }; _process = new Process From 541007b1b58d890e93bc96677ba0db447024b88c Mon Sep 17 00:00:00 2001 From: NotroDev Date: Thu, 31 Oct 2024 20:17:28 +0100 Subject: [PATCH 21/28] Update Avalonia and libs --- SkEditor/SkEditor.csproj | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/SkEditor/SkEditor.csproj b/SkEditor/SkEditor.csproj index 9bf6fb7..8ab00dd 100644 --- a/SkEditor/SkEditor.csproj +++ b/SkEditor/SkEditor.csproj @@ -44,30 +44,30 @@ - - - - - - - - + + + + + + + + - + - + - + - + From 5c5a951e0ff135679376b1dc4b578940c0306900 Mon Sep 17 00:00:00 2001 From: NotroDev Date: Wed, 20 Nov 2024 21:26:41 +0100 Subject: [PATCH 22/28] update libs --- SkEditor/SkEditor.csproj | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/SkEditor/SkEditor.csproj b/SkEditor/SkEditor.csproj index 8ab00dd..354ee35 100644 --- a/SkEditor/SkEditor.csproj +++ b/SkEditor/SkEditor.csproj @@ -44,31 +44,31 @@ - - - - + + + + - - - + + + - - + + - + - + - + - + From be583a81d368b9f46425a5fbc3e8b537d14ca41d Mon Sep 17 00:00:00 2001 From: NotroDev Date: Sat, 30 Nov 2024 16:59:54 +0100 Subject: [PATCH 23/28] Correct the Program namespace --- SkEditor/Program.cs | 63 ++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/SkEditor/Program.cs b/SkEditor/Program.cs index d905878..dfb153f 100644 --- a/SkEditor/Program.cs +++ b/SkEditor/Program.cs @@ -2,45 +2,44 @@ using Avalonia.Data; using System; -namespace SkEditor.Desktop +namespace SkEditor; + +class Program { - class Program + // Initialization code. Don't use any Avalonia, third-party APIs or any + // SynchronizationContext-reliant code before AppMain is called: things aren't initialized + // yet and stuff might break. + [STAThread] + public static void Main(string[] args) { - // Initialization code. Don't use any Avalonia, third-party APIs or any - // SynchronizationContext-reliant code before AppMain is called: things aren't initialized - // yet and stuff might break. - [STAThread] - public static void Main(string[] args) - { - GC.KeepAlive(typeof(RelativeSource)); - CheckTest(args); + GC.KeepAlive(typeof(RelativeSource)); + CheckTest(args); - BuildAvaloniaApp() - .StartWithClassicDesktopLifetime(args); - } + BuildAvaloniaApp() + .StartWithClassicDesktopLifetime(args); + } - private static void CheckTest(string[] args) + private static void CheckTest(string[] args) + { + if (args.Length > 0 && args[0] == "--test") { - if (args.Length > 0 && args[0] == "--test") + try { - try - { - Console.WriteLine("Test passed"); - } - catch (Exception e) - { - Console.Error.WriteLine($"Test failed: {e.Message}"); - Environment.Exit(1); - } - return; + Console.WriteLine("Test passed"); } + catch (Exception e) + { + Console.Error.WriteLine($"Test failed: {e.Message}"); + Environment.Exit(1); + } + return; } - - // Avalonia configuration, don't remove; also used by visual designer. - public static AppBuilder BuildAvaloniaApp() - => AppBuilder.Configure() - .UsePlatformDetect() - .LogToTrace() - .WithInterFont(); } + + // Avalonia configuration, don't remove; also used by visual designer. + public static AppBuilder BuildAvaloniaApp() + => AppBuilder.Configure() + .UsePlatformDetect() + .LogToTrace() + .WithInterFont(); } From 80b0901da57013466b4ba48f8984f9fc6374e9b4 Mon Sep 17 00:00:00 2001 From: NotroDev Date: Sat, 7 Dec 2024 11:01:02 +0100 Subject: [PATCH 24/28] Refresh icon in project tree after renaming --- SkEditor/Utilities/Projects/Elements/File.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/SkEditor/Utilities/Projects/Elements/File.cs b/SkEditor/Utilities/Projects/Elements/File.cs index c8cef2f..9092dcd 100644 --- a/SkEditor/Utilities/Projects/Elements/File.cs +++ b/SkEditor/Utilities/Projects/Elements/File.cs @@ -23,8 +23,7 @@ public File(string file, Folder? parent = null) Name = Path.GetFileName(file); IsFile = true; - var icon = Files.Icon.GetIcon(Path.GetExtension(file)); - if (icon is not null) Icon = icon; + UpdateIcon(); OpenInExplorerCommand = new RelayCommand(OpenInExplorer); DeleteCommand = new RelayCommand(DeleteFile); @@ -68,11 +67,18 @@ public override void RenameElement(string newName, bool move = true) StorageFilePath = newPath; Name = newName; + UpdateIcon(); RefreshSelf(); } public override void HandleClick() => FileHandler.OpenFile(StorageFilePath); + public void UpdateIcon() + { + var icon = Files.Icon.GetIcon(Path.GetExtension(StorageFilePath)); + if (icon is not null) Icon = icon; + } + public void CopyAbsolutePath() { SkEditorAPI.Windows.GetMainWindow().Clipboard.SetTextAsync(Path.GetFullPath(StorageFilePath)); From cc8c32dfb650259710c949b12c9ccc2cb001d7ac Mon Sep 17 00:00:00 2001 From: NotroDev Date: Sat, 7 Dec 2024 11:04:09 +0100 Subject: [PATCH 25/28] Update libs --- SkEditor/SkEditor.csproj | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/SkEditor/SkEditor.csproj b/SkEditor/SkEditor.csproj index 354ee35..df2cf38 100644 --- a/SkEditor/SkEditor.csproj +++ b/SkEditor/SkEditor.csproj @@ -44,22 +44,22 @@ - + - - - - - + + + + + - - + + - + @@ -67,7 +67,7 @@ - + From b2c9ab13d91d8e0e035e54869565adf9cb16d502 Mon Sep 17 00:00:00 2001 From: NotroDev Date: Sat, 7 Dec 2024 11:08:03 +0100 Subject: [PATCH 26/28] Fix project root folder having an empty name --- SkEditor/Utilities/Projects/Elements/Folder.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SkEditor/Utilities/Projects/Elements/Folder.cs b/SkEditor/Utilities/Projects/Elements/Folder.cs index e4e80ee..91c3e69 100644 --- a/SkEditor/Utilities/Projects/Elements/Folder.cs +++ b/SkEditor/Utilities/Projects/Elements/Folder.cs @@ -2,6 +2,7 @@ using Avalonia.Threading; using CommunityToolkit.Mvvm.Input; using FluentAvalonia.UI.Controls; +using Serilog; using SkEditor.API; using SkEditor.Controls.Sidebar; using SkEditor.Utilities.Files; @@ -22,7 +23,7 @@ public class Folder : StorageElement public Folder(string folder, Folder? parent = null) { - folder = Uri.UnescapeDataString(folder).FixLinuxPath(); + folder = Uri.UnescapeDataString(folder).FixLinuxPath().TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); Parent = parent; StorageFolderPath = folder; From b0a83380ff6f266f1ca28551bae3c14190a40969 Mon Sep 17 00:00:00 2001 From: NotroDev Date: Sat, 7 Dec 2024 11:53:20 +0100 Subject: [PATCH 27/28] Bump version to 2.8.2 --- SkEditor/SkEditor.csproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SkEditor/SkEditor.csproj b/SkEditor/SkEditor.csproj index df2cf38..150cb50 100644 --- a/SkEditor/SkEditor.csproj +++ b/SkEditor/SkEditor.csproj @@ -8,10 +8,10 @@ app.manifest SkEditor.ico true - 2.8.1 - 2.8.1 - 2.8.1 - 2.8.1 + 2.8.2 + 2.8.2 + 2.8.2 + 2.8.2 false true From 6732ee0b8fe4b1845379b8fa712bf1342e2ea4af Mon Sep 17 00:00:00 2001 From: NotroDev Date: Sat, 7 Dec 2024 11:53:36 +0100 Subject: [PATCH 28/28] Upgrade installer to Wix v5 --- Installer/Folders.wxs | 14 ++++----- Installer/LanguagesComponents.wxs | 34 ---------------------- Installer/Package.wxs | 45 ++++++++++++++--------------- Installer/SkEditorComponents.wxs | 15 ++++------ Installer/SkEditorInstaller.wixproj | 6 ++-- 5 files changed, 35 insertions(+), 79 deletions(-) delete mode 100644 Installer/LanguagesComponents.wxs diff --git a/Installer/Folders.wxs b/Installer/Folders.wxs index dc1f0f2..71509cf 100644 --- a/Installer/Folders.wxs +++ b/Installer/Folders.wxs @@ -1,9 +1,7 @@ - - - - - - - - + + + + + + \ No newline at end of file diff --git a/Installer/LanguagesComponents.wxs b/Installer/LanguagesComponents.wxs deleted file mode 100644 index b6becf6..0000000 --- a/Installer/LanguagesComponents.wxs +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Installer/Package.wxs b/Installer/Package.wxs index 89d3fe2..f1d6719 100644 --- a/Installer/Package.wxs +++ b/Installer/Package.wxs @@ -1,34 +1,31 @@ - - - + + - - + Id="SkEditorInstaller_InstallDir" + InstallDirectory="INSTALLFOLDER" /> + - - - - - - - + + + + + + + - + \ No newline at end of file diff --git a/Installer/SkEditorComponents.wxs b/Installer/SkEditorComponents.wxs index 8c43e15..f90d631 100644 --- a/Installer/SkEditorComponents.wxs +++ b/Installer/SkEditorComponents.wxs @@ -1,23 +1,18 @@ + + + + - - - - - - - - - - + \ No newline at end of file diff --git a/Installer/SkEditorInstaller.wixproj b/Installer/SkEditorInstaller.wixproj index 1a983db..491eea6 100644 --- a/Installer/SkEditorInstaller.wixproj +++ b/Installer/SkEditorInstaller.wixproj @@ -1,10 +1,10 @@ - + - - + + \ No newline at end of file