fix color formatting core dump
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
using HanaTui.Hana;
|
using HanaTui.Hana;
|
||||||
using Spectre.Console;
|
using Spectre.Console;
|
||||||
|
using SysText = System.Text;
|
||||||
|
|
||||||
namespace HanaTui.Tui;
|
namespace HanaTui.Tui;
|
||||||
|
|
||||||
@@ -9,6 +10,10 @@ namespace HanaTui.Tui;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class KeySelectionScreen
|
public static class KeySelectionScreen
|
||||||
{
|
{
|
||||||
|
// Sentinel values for the non-key choices
|
||||||
|
private const string ManualEntry = "__MANUAL__";
|
||||||
|
private const string ExitChoice = "__EXIT__";
|
||||||
|
|
||||||
public static string? Run()
|
public static string? Run()
|
||||||
{
|
{
|
||||||
AnsiConsole.Clear();
|
AnsiConsole.Clear();
|
||||||
@@ -28,7 +33,7 @@ public static class KeySelectionScreen
|
|||||||
// Show client path for reference
|
// Show client path for reference
|
||||||
var clientDir = HdbClientLocator.ClientDirectory;
|
var clientDir = HdbClientLocator.ClientDirectory;
|
||||||
if (clientDir is not null)
|
if (clientDir is not null)
|
||||||
AnsiConsole.MarkupLine($"[dim]HDB client: {clientDir}[/]\n");
|
AnsiConsole.MarkupLine($"[dim]HDB client: {Markup.Escape(clientDir)}[/]\n");
|
||||||
|
|
||||||
// Load keys with a spinner
|
// Load keys with a spinner
|
||||||
List<HdbUserstoreKey> keys = [];
|
List<HdbUserstoreKey> keys = [];
|
||||||
@@ -47,49 +52,77 @@ public static class KeySelectionScreen
|
|||||||
AnsiConsole.MarkupLine("You can still enter a key name manually.\n");
|
AnsiConsole.MarkupLine("You can still enter a key name manually.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build selection choices
|
// Build a plain-string list where the value IS the key name (or sentinel).
|
||||||
var choices = new List<string>();
|
// We use SelectionPrompt<string> with a display converter so Spectre renders
|
||||||
|
// the label as markup but we always get back the plain key name.
|
||||||
|
var choiceNames = new List<string>();
|
||||||
|
var displayMap = new Dictionary<string, string>(); // name -> display label
|
||||||
|
|
||||||
foreach (var k in keys)
|
foreach (var k in keys)
|
||||||
{
|
{
|
||||||
var detail = BuildKeyDetail(k);
|
choiceNames.Add(k.Name);
|
||||||
choices.Add(detail);
|
displayMap[k.Name] = BuildKeyDisplay(k);
|
||||||
}
|
}
|
||||||
choices.Add("[dim][ Enter key name manually ][/]");
|
|
||||||
choices.Add("[red][ Exit ][/]");
|
choiceNames.Add(ManualEntry);
|
||||||
|
displayMap[ManualEntry] = "[ Enter key name manually ]";
|
||||||
|
|
||||||
|
choiceNames.Add(ExitChoice);
|
||||||
|
displayMap[ExitChoice] = "[ Exit ]";
|
||||||
|
|
||||||
var prompt = new SelectionPrompt<string>()
|
var prompt = new SelectionPrompt<string>()
|
||||||
.Title("[bold]Select HDBUSERSTORE key:[/]")
|
.Title("[bold]Select HDBUSERSTORE key:[/]")
|
||||||
.PageSize(15)
|
.PageSize(15)
|
||||||
.HighlightStyle(Style.Parse("bold dodgerblue1"))
|
.HighlightStyle(Style.Parse("bold dodgerblue1"))
|
||||||
.AddChoices(choices);
|
.UseConverter(name => displayMap.TryGetValue(name, out var label) ? label : name)
|
||||||
|
.AddChoices(choiceNames);
|
||||||
|
|
||||||
var selected = AnsiConsole.Prompt(prompt);
|
var selected = AnsiConsole.Prompt(prompt);
|
||||||
|
|
||||||
if (selected.Contains("Exit"))
|
if (selected == ExitChoice)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (selected.Contains("manually"))
|
if (selected == ManualEntry)
|
||||||
{
|
{
|
||||||
var manual = AnsiConsole.Ask<string>("[bold]Enter HDBUSERSTORE key name:[/]").Trim();
|
var manual = AnsiConsole.Ask<string>("[bold]Enter HDBUSERSTORE key name:[/]").Trim();
|
||||||
return string.IsNullOrWhiteSpace(manual) ? null : manual;
|
return string.IsNullOrWhiteSpace(manual) ? null : manual;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract the key name from the formatted string (it's always the first word)
|
// selected is already the plain key name
|
||||||
var keyName = selected.Split(' ')[0].Trim();
|
return selected;
|
||||||
return keyName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string BuildKeyDetail(HdbUserstoreKey k)
|
/// <summary>
|
||||||
|
/// Builds a plain-text display label (no markup) for a key.
|
||||||
|
/// Spectre's UseConverter renders the returned string as plain text.
|
||||||
|
/// </summary>
|
||||||
|
private static string BuildKeyDisplay(HdbUserstoreKey k)
|
||||||
{
|
{
|
||||||
var parts = new List<string> { k.Name };
|
var sb = new SysText.StringBuilder(k.Name);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(k.Host))
|
if (!string.IsNullOrEmpty(k.Host))
|
||||||
parts.Add($"[dim]{k.Host}:{k.Port}[/]");
|
{
|
||||||
if (!string.IsNullOrEmpty(k.Tenant))
|
sb.Append(" ");
|
||||||
parts.Add($"[dim]@{k.Tenant}[/]");
|
sb.Append(k.Host);
|
||||||
if (!string.IsNullOrEmpty(k.User))
|
if (!string.IsNullOrEmpty(k.Port))
|
||||||
parts.Add($"[dim]user={k.User}[/]");
|
{
|
||||||
|
sb.Append(':');
|
||||||
|
sb.Append(k.Port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return string.Join(" ", parts);
|
if (!string.IsNullOrEmpty(k.Tenant))
|
||||||
|
{
|
||||||
|
sb.Append('@');
|
||||||
|
sb.Append(k.Tenant);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(k.User))
|
||||||
|
{
|
||||||
|
sb.Append(" user=");
|
||||||
|
sb.Append(k.User);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,15 +32,15 @@ public static class MainMenuScreen
|
|||||||
|
|
||||||
if (key is not null)
|
if (key is not null)
|
||||||
{
|
{
|
||||||
|
var conn = key.Host + ":" + key.Port +
|
||||||
|
(string.IsNullOrEmpty(key.Tenant) ? "" : "@" + key.Tenant) +
|
||||||
|
" user=" + key.User;
|
||||||
AnsiConsole.MarkupLine(
|
AnsiConsole.MarkupLine(
|
||||||
$" Key: [bold yellow]{key.Name}[/] " +
|
$" Key: [bold yellow]{Markup.Escape(key.Name)}[/] [dim]{Markup.Escape(conn)}[/]");
|
||||||
$"[dim]{key.Host}:{key.Port}" +
|
|
||||||
(string.IsNullOrEmpty(key.Tenant) ? "" : $"@{key.Tenant}") +
|
|
||||||
$" user={key.User}[/]");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
AnsiConsole.MarkupLine($" Key: [bold yellow]{keyName}[/]");
|
AnsiConsole.MarkupLine($" Key: [bold yellow]{Markup.Escape(keyName)}[/]");
|
||||||
}
|
}
|
||||||
|
|
||||||
AnsiConsole.WriteLine();
|
AnsiConsole.WriteLine();
|
||||||
|
|||||||
@@ -38,22 +38,30 @@ public static class OperationForms
|
|||||||
if (error is not null)
|
if (error is not null)
|
||||||
AnsiConsole.MarkupLine($"[yellow][[WARN]] Could not fetch schemas: {Markup.Escape(error)}[/]");
|
AnsiConsole.MarkupLine($"[yellow][[WARN]] Could not fetch schemas: {Markup.Escape(error)}[/]");
|
||||||
|
|
||||||
var choices = new List<string>(schemas);
|
// Use sentinel strings as values so no markup leaks into choice labels
|
||||||
choices.Add("[dim][ Enter manually ][/]");
|
const string manualSentinel = "__MANUAL__";
|
||||||
choices.Add("[dim][ Cancel ][/]");
|
const string cancelSentinel = "__CANCEL__";
|
||||||
|
|
||||||
|
var choiceValues = new List<string>(schemas) { manualSentinel, cancelSentinel };
|
||||||
|
|
||||||
var prompt = new SelectionPrompt<string>()
|
var prompt = new SelectionPrompt<string>()
|
||||||
.Title($"[bold]{title}[/]")
|
.Title($"[bold]{Markup.Escape(title)}[/]")
|
||||||
.PageSize(15)
|
.PageSize(15)
|
||||||
.HighlightStyle(Style.Parse("bold dodgerblue1"))
|
.HighlightStyle(Style.Parse("bold dodgerblue1"))
|
||||||
.AddChoices(choices);
|
.UseConverter(v => v switch
|
||||||
|
{
|
||||||
|
manualSentinel => "[ Enter manually ]",
|
||||||
|
cancelSentinel => "[ Cancel ]",
|
||||||
|
_ => v,
|
||||||
|
})
|
||||||
|
.AddChoices(choiceValues);
|
||||||
|
|
||||||
var selected = AnsiConsole.Prompt(prompt);
|
var selected = AnsiConsole.Prompt(prompt);
|
||||||
|
|
||||||
if (selected.Contains("Cancel"))
|
if (selected == cancelSentinel)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
if (selected.Contains("manually"))
|
if (selected == manualSentinel)
|
||||||
{
|
{
|
||||||
var manual = AnsiConsole.Ask<string>("Enter schema name:").Trim();
|
var manual = AnsiConsole.Ask<string>("Enter schema name:").Trim();
|
||||||
return string.IsNullOrWhiteSpace(manual) ? null : manual;
|
return string.IsNullOrWhiteSpace(manual) ? null : manual;
|
||||||
|
|||||||
Reference in New Issue
Block a user