Console output fixes.

Make it not assume UTF-8 when it's not.
Try to set the console output to UTF-8 on Windows.
Remove UTF-16 output code cuz who needs it.
This commit is contained in:
Pieter-Jan Briers
2023-04-26 22:51:52 +02:00
parent cea74c63cd
commit c9042f188c
4 changed files with 29 additions and 11 deletions

View File

@@ -39,7 +39,7 @@ END TEMPLATE-->
### New features
*None yet*
* `echo` console command to echo things.
### Bugfixes
@@ -47,7 +47,7 @@ END TEMPLATE-->
### Other
*None yet*
* Set console code page to UTF-8 explicitly on Windows to fix output of non-ASCII characters.
### Internal
@@ -172,7 +172,7 @@ END TEMPLATE-->
### New features
* `RobustIntegrationTest` now has a `DoGuiEvent()` method that can directly pass `GUIBoundKeyEventArgs` to a control.
* `RobustIntegrationTest` now has a `DoGuiEvent()` method that can directly pass `GUIBoundKeyEventArgs` to a control.
## 0.96.8.2

View File

@@ -554,3 +554,6 @@ cmd-dump_netserializer_type_map-help = Usage: dump_netserializer_type_map
cmd-hub_advertise_now-desc = Immediately advertise to the master hub server
cmd-hub_advertise_now-help = Usage: hub_advertise_now
cmd-echo-desc = Echo arguments back to the console
cmd-echo-help = Usage: echo "<message>"

View File

@@ -0,0 +1,11 @@
namespace Robust.Shared.Console.Commands;
internal sealed class EchoCommand : LocalizedCommands
{
public override string Command => "echo";
public override void Execute(IConsoleShell shell, string argStr, string[] args)
{
shell.WriteLine(string.Join(" ", args));
}
}

View File

@@ -47,8 +47,6 @@ namespace Robust.Shared.Log
private readonly Timer _timer = new(0.1);
private readonly bool _isUtf16Out = System.Console.OutputEncoding.CodePage == Encoding.Unicode.CodePage;
private bool _disposed;
static ConsoleLogHandler()
@@ -58,6 +56,10 @@ namespace Robust.Shared.Log
if (WriteAnsiColors && OperatingSystem.IsWindows())
{
WriteAnsiColors = WindowsConsole.TryEnableVirtualTerminalProcessing();
// Try to set console output on Windows to UTF-8, because .NET doesn't do it built-in.
// Otherwise we can't print anything that isn't just your default Windows code page.
_ = WindowsConsole.NativeMethods.SetConsoleOutputCP(WindowsConsole.NativeMethods.CodePageUtf8);
}
}
@@ -106,9 +108,9 @@ namespace Robust.Shared.Log
_line.AppendLine(message.Exception.ToString());
}
// ReSharper disable once SuggestVarOrType_Elsewhere
if (!_isUtf16Out)
if (System.Console.OutputEncoding.CodePage == WindowsConsole.NativeMethods.CodePageUtf8)
{
// Fast path: if we can output as UTF-8, do it.
Span<byte> buf = stackalloc byte[1024];
var totalChars = _line.Length;
foreach (var chunk in _line.GetChunks())
@@ -134,10 +136,8 @@ namespace Robust.Shared.Log
}
else
{
foreach (var chunk in _line.GetChunks())
{
_stream.Write(MemoryMarshal.AsBytes(chunk.Span));
}
// Fallback path: just let .NET handle it.
System.Console.Write(_line.ToString());
}
// ReSharper disable once InvertIf
@@ -233,6 +233,7 @@ namespace Robust.Shared.Log
internal static class NativeMethods
{
public const int CodePageUtf8 = 65001;
[DllImport("kernel32", SetLastError = true)]
internal static extern bool SetConsoleMode(IntPtr hConsoleHandle, int mode);
@@ -249,6 +250,9 @@ namespace Robust.Shared.Log
[DllImport("kernel32", SetLastError = true)]
internal static extern IntPtr GetConsoleWindow();
[DllImport("kernel32", SetLastError = true)]
internal static extern int SetConsoleOutputCP(uint wCodePageID);
}
}