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)
|
public static async Task Main(string[] args)
|
||||||
{
|
{
|
||||||
|
UnicodeSupport.Initialize();
|
||||||
|
|
||||||
// --snapshot N: directly load snapshot_N save and start playing
|
// --snapshot N: directly load snapshot_N save and start playing
|
||||||
int snapshotSlot = 0;
|
int snapshotSlot = 0;
|
||||||
var snapshotIdx = Array.IndexOf(args, "--snapshot");
|
var snapshotIdx = Array.IndexOf(args, "--snapshot");
|
||||||
|
|
@ -521,8 +523,8 @@ public static class Program
|
||||||
|
|
||||||
case ResourceChangedEvent resEvt:
|
case ResourceChangedEvent resEvt:
|
||||||
var resName = _loc.Get($"resource.{resEvt.Type.ToString().ToLower()}");
|
var resName = _loc.Get($"resource.{resEvt.Type.ToString().ToLower()}");
|
||||||
_renderer.ShowMessage($"{resName}: {resEvt.OldValue} -> {resEvt.NewValue}");
|
_renderer.ShowMessage($"{resName}: {resEvt.OldValue} {UnicodeSupport.Arrow} {resEvt.NewValue}");
|
||||||
AddEventLog($"{resName}: {resEvt.OldValue} -> {resEvt.NewValue}");
|
AddEventLog($"{resName}: {resEvt.OldValue} {UnicodeSupport.Arrow} {resEvt.NewValue}");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MessageEvent msgEvt:
|
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_qty", itemName, remaining.ToString())
|
||||||
: _loc.Get("inventory.item_used", itemName);
|
: _loc.Get("inventory.item_used", itemName);
|
||||||
_renderer.ShowMessage(usedMsg);
|
_renderer.ShowMessage(usedMsg);
|
||||||
_renderer.ShowMessage($"{resName}: {resEvt.OldValue} -> {resEvt.NewValue}");
|
_renderer.ShowMessage($"{resName}: {resEvt.OldValue} {UnicodeSupport.Arrow} {resEvt.NewValue}");
|
||||||
AddEventLog($"{itemName} -> {resName} {resEvt.OldValue}->{resEvt.NewValue}");
|
AddEventLog($"{itemName} {UnicodeSupport.Arrow} {resName} {resEvt.OldValue}{UnicodeSupport.Arrow}{resEvt.NewValue}");
|
||||||
break;
|
break;
|
||||||
case MessageEvent msgEvt:
|
case MessageEvent msgEvt:
|
||||||
_renderer.ShowMessage(_loc.Get(msgEvt.MessageKey, msgEvt.Args ?? []));
|
_renderer.ShowMessage(_loc.Get(msgEvt.MessageKey, msgEvt.Args ?? []));
|
||||||
|
|
@ -784,7 +786,7 @@ public static class Program
|
||||||
break;
|
break;
|
||||||
case ResourceChangedEvent resEvt:
|
case ResourceChangedEvent resEvt:
|
||||||
var cookieResName = _loc.Get($"resource.{resEvt.Type.ToString().ToLower()}");
|
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;
|
break;
|
||||||
case MessageEvent msgEvt:
|
case MessageEvent msgEvt:
|
||||||
_renderer.ShowMessage(_loc.Get(msgEvt.MessageKey, msgEvt.Args ?? []));
|
_renderer.ShowMessage(_loc.Get(msgEvt.MessageKey, msgEvt.Args ?? []));
|
||||||
|
|
|
||||||
|
|
@ -323,7 +323,8 @@ public sealed class SpectreRenderer : IRenderer
|
||||||
{
|
{
|
||||||
if (_context.HasColors)
|
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)
|
.Border(BoxBorder.Double)
|
||||||
.BorderStyle(new Style(Color.Yellow))
|
.BorderStyle(new Style(Color.Yellow))
|
||||||
.Padding(2, 0)
|
.Padding(2, 0)
|
||||||
|
|
@ -333,7 +334,7 @@ public sealed class SpectreRenderer : IRenderer
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine("========================================");
|
Console.WriteLine("========================================");
|
||||||
Console.WriteLine($" * {featureName} *");
|
Console.WriteLine($" {UnicodeSupport.Star} {featureName} {UnicodeSupport.Star}");
|
||||||
Console.WriteLine("========================================");
|
Console.WriteLine("========================================");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -429,14 +430,18 @@ public sealed class SpectreRenderer : IRenderer
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns rarity star prefix for Rare and above items.
|
/// Returns rarity star prefix for Rare and above items.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static string RarityStars(string rarity) => rarity.ToLowerInvariant() switch
|
private static string RarityStars(string rarity)
|
||||||
{
|
{
|
||||||
"rare" => "* ",
|
var s = UnicodeSupport.Star;
|
||||||
"epic" => "** ",
|
return rarity.ToLowerInvariant() switch
|
||||||
"legendary" => "*** ",
|
{
|
||||||
"mythic" => "**** ",
|
"rare" => $"{s} ",
|
||||||
_ => ""
|
"epic" => $"{s}{s} ",
|
||||||
};
|
"legendary" => $"{s}{s}{s} ",
|
||||||
|
"mythic" => $"{s}{s}{s}{s} ",
|
||||||
|
_ => ""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private static Color RarityColorValue(string rarity) => rarity.ToLowerInvariant() switch
|
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