namespace ZB.MOM.WW.Tools.LdapProbe; /// Console formatting and credential prompting. public static class Ui { public static void Section(string title) { Console.WriteLine(); Write(ConsoleColor.Cyan, $"── {title} " + new string('─', Math.Max(0, 66 - title.Length))); } public static void Ok(string message) => Write(ConsoleColor.Green, " ✓ " + message); public static void Bad(string message) => Write(ConsoleColor.Red, " ✗ " + message); public static void Warn(string message) => Write(ConsoleColor.Yellow, " ! " + message); public static void Info(string message) => Console.WriteLine(" " + message); public static void Field(string name, string? value) => Console.WriteLine($" {name,-22} {value ?? "(not set)"}"); private static void Write(ConsoleColor color, string message) { var previous = Console.ForegroundColor; try { Console.ForegroundColor = color; Console.WriteLine(message); } finally { Console.ForegroundColor = previous; } } public static string Prompt(string label, string? preset = null) { if (!string.IsNullOrWhiteSpace(preset)) return preset; Console.Write($" {label}: "); return Console.ReadLine()?.Trim() ?? ""; } /// /// Reads a password without echoing it. Falls back to a plain read when input is /// redirected (a pipe has no key events), so the probe still works non-interactively. /// public static string PromptSecret(string label) { Console.Write($" {label}: "); if (Console.IsInputRedirected) { var piped = Console.ReadLine() ?? ""; Console.WriteLine("(read from stdin)"); return piped; } var buffer = new Stack(); while (true) { var key = Console.ReadKey(intercept: true); switch (key.Key) { case ConsoleKey.Enter: Console.WriteLine(); return new string(buffer.Reverse().ToArray()); case ConsoleKey.Backspace when buffer.Count > 0: buffer.Pop(); Console.Write("\b \b"); break; case ConsoleKey.Backspace: break; case ConsoleKey.Escape: Console.WriteLine(); return ""; default: if (!char.IsControl(key.KeyChar)) { buffer.Push(key.KeyChar); Console.Write('*'); } break; } } } }