Add UTF-8 detection with ASCII fallback for terminal compatibility
- Detect Windows Terminal (WT_SESSION), PowerShell, and non-Windows terminals to enable UTF-8 output encoding automatically - Use ★ and → when UTF-8 is supported, fall back to * and -> on cmd.exe - Set Console.OutputEncoding = UTF8 at startup for capable terminals
This commit is contained in:
parent
af13380a26
commit
240989e0ff
3 changed files with 96 additions and 14 deletions
|
|
@ -35,6 +35,8 @@ public static class Program
|
|||
|
||||
public static async Task Main(string[] args)
|
||||
{
|
||||
UnicodeSupport.Initialize();
|
||||
|
||||
// --snapshot N: directly load snapshot_N save and start playing
|
||||
int snapshotSlot = 0;
|
||||
var snapshotIdx = Array.IndexOf(args, "--snapshot");
|
||||
|
|
@ -521,8 +523,8 @@ public static class Program
|
|||
|
||||
case ResourceChangedEvent resEvt:
|
||||
var resName = _loc.Get($"resource.{resEvt.Type.ToString().ToLower()}");
|
||||
_renderer.ShowMessage($"{resName}: {resEvt.OldValue} -> {resEvt.NewValue}");
|
||||
AddEventLog($"{resName}: {resEvt.OldValue} -> {resEvt.NewValue}");
|
||||
_renderer.ShowMessage($"{resName}: {resEvt.OldValue} {UnicodeSupport.Arrow} {resEvt.NewValue}");
|
||||
AddEventLog($"{resName}: {resEvt.OldValue} {UnicodeSupport.Arrow} {resEvt.NewValue}");
|
||||
break;
|
||||
|
||||
case MessageEvent msgEvt:
|
||||
|
|
@ -758,8 +760,8 @@ public static class Program
|
|||
? _loc.Get("inventory.item_used_qty", itemName, remaining.ToString())
|
||||
: _loc.Get("inventory.item_used", itemName);
|
||||
_renderer.ShowMessage(usedMsg);
|
||||
_renderer.ShowMessage($"{resName}: {resEvt.OldValue} -> {resEvt.NewValue}");
|
||||
AddEventLog($"{itemName} -> {resName} {resEvt.OldValue}->{resEvt.NewValue}");
|
||||
_renderer.ShowMessage($"{resName}: {resEvt.OldValue} {UnicodeSupport.Arrow} {resEvt.NewValue}");
|
||||
AddEventLog($"{itemName} {UnicodeSupport.Arrow} {resName} {resEvt.OldValue}{UnicodeSupport.Arrow}{resEvt.NewValue}");
|
||||
break;
|
||||
case MessageEvent msgEvt:
|
||||
_renderer.ShowMessage(_loc.Get(msgEvt.MessageKey, msgEvt.Args ?? []));
|
||||
|
|
@ -784,7 +786,7 @@ public static class Program
|
|||
break;
|
||||
case ResourceChangedEvent resEvt:
|
||||
var cookieResName = _loc.Get($"resource.{resEvt.Type.ToString().ToLower()}");
|
||||
_renderer.ShowMessage($"{cookieResName}: {resEvt.OldValue} → {resEvt.NewValue}");
|
||||
_renderer.ShowMessage($"{cookieResName}: {resEvt.OldValue} {UnicodeSupport.Arrow} {resEvt.NewValue}");
|
||||
break;
|
||||
case MessageEvent msgEvt:
|
||||
_renderer.ShowMessage(_loc.Get(msgEvt.MessageKey, msgEvt.Args ?? []));
|
||||
|
|
|
|||
|
|
@ -323,7 +323,8 @@ public sealed class SpectreRenderer : IRenderer
|
|||
{
|
||||
if (_context.HasColors)
|
||||
{
|
||||
var panel = new Panel($"[bold yellow]* {Markup.Escape(featureName)} *[/]")
|
||||
var star = UnicodeSupport.Star;
|
||||
var panel = new Panel($"[bold yellow]{star} {Markup.Escape(featureName)} {star}[/]")
|
||||
.Border(BoxBorder.Double)
|
||||
.BorderStyle(new Style(Color.Yellow))
|
||||
.Padding(2, 0)
|
||||
|
|
@ -333,7 +334,7 @@ public sealed class SpectreRenderer : IRenderer
|
|||
else
|
||||
{
|
||||
Console.WriteLine("========================================");
|
||||
Console.WriteLine($" * {featureName} *");
|
||||
Console.WriteLine($" {UnicodeSupport.Star} {featureName} {UnicodeSupport.Star}");
|
||||
Console.WriteLine("========================================");
|
||||
}
|
||||
}
|
||||
|
|
@ -429,14 +430,18 @@ public sealed class SpectreRenderer : IRenderer
|
|||
/// <summary>
|
||||
/// Returns rarity star prefix for Rare and above items.
|
||||
/// </summary>
|
||||
private static string RarityStars(string rarity) => rarity.ToLowerInvariant() switch
|
||||
private static string RarityStars(string rarity)
|
||||
{
|
||||
"rare" => "* ",
|
||||
"epic" => "** ",
|
||||
"legendary" => "*** ",
|
||||
"mythic" => "**** ",
|
||||
_ => ""
|
||||
};
|
||||
var s = UnicodeSupport.Star;
|
||||
return rarity.ToLowerInvariant() switch
|
||||
{
|
||||
"rare" => $"{s} ",
|
||||
"epic" => $"{s}{s} ",
|
||||
"legendary" => $"{s}{s}{s} ",
|
||||
"mythic" => $"{s}{s}{s}{s} ",
|
||||
_ => ""
|
||||
};
|
||||
}
|
||||
|
||||
private static Color RarityColorValue(string rarity) => rarity.ToLowerInvariant() switch
|
||||
{
|
||||
|
|
|
|||
75
src/OpenTheBox/Rendering/UnicodeSupport.cs
Normal file
75
src/OpenTheBox/Rendering/UnicodeSupport.cs
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
using System.Text;
|
||||
|
||||
namespace OpenTheBox.Rendering;
|
||||
|
||||
/// <summary>
|
||||
/// Detects whether the terminal supports UTF-8 output and provides
|
||||
/// glyph accessors that return Unicode or ASCII equivalents accordingly.
|
||||
/// Call <see cref="Initialize"/> once at startup.
|
||||
/// </summary>
|
||||
public static class UnicodeSupport
|
||||
{
|
||||
/// <summary>True when the terminal accepts UTF-8 characters beyond CP437.</summary>
|
||||
public static bool IsUtf8 { get; private set; }
|
||||
|
||||
// ── Glyphs ──────────────────────────────────────────────────────────
|
||||
|
||||
/// <summary>Arrow: → or -></summary>
|
||||
public static string Arrow => IsUtf8 ? "→" : "->";
|
||||
|
||||
/// <summary>Star for rarity prefix: ★ or *</summary>
|
||||
public static string Star => IsUtf8 ? "★" : "*";
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to set UTF-8 output encoding and detects whether the
|
||||
/// terminal actually supports it (Windows Terminal, PowerShell, etc.).
|
||||
/// </summary>
|
||||
public static void Initialize()
|
||||
{
|
||||
// Windows Terminal always sets WT_SESSION
|
||||
if (Environment.GetEnvironmentVariable("WT_SESSION") is not null)
|
||||
{
|
||||
EnableUtf8();
|
||||
return;
|
||||
}
|
||||
|
||||
// Modern PowerShell (pwsh) or Windows PowerShell with PSModulePath
|
||||
// typically supports UTF-8 when we set the encoding
|
||||
if (Environment.GetEnvironmentVariable("PSModulePath") is not null)
|
||||
{
|
||||
EnableUtf8();
|
||||
return;
|
||||
}
|
||||
|
||||
// Non-Windows platforms (Linux, macOS) generally support UTF-8
|
||||
if (!OperatingSystem.IsWindows())
|
||||
{
|
||||
EnableUtf8();
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback: try to set UTF-8 and check if it stuck
|
||||
try
|
||||
{
|
||||
Console.OutputEncoding = Encoding.UTF8;
|
||||
IsUtf8 = Console.OutputEncoding.CodePage == 65001;
|
||||
}
|
||||
catch
|
||||
{
|
||||
IsUtf8 = false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void EnableUtf8()
|
||||
{
|
||||
try
|
||||
{
|
||||
Console.OutputEncoding = Encoding.UTF8;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore if setting encoding fails
|
||||
}
|
||||
IsUtf8 = true;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue