| File: UI\ConsoleInputReader.cs | Web Access |
| Project: src\sdk\src\Dotnet.Watch\Watch\Microsoft.DotNet.HotReload.Watch.csproj (Microsoft.DotNet.HotReload.Watch) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.Extensions.Logging; namespace Microsoft.DotNet.Watch; internal sealed class ConsoleInputReader(IConsole console, LogLevel logLevel, bool suppressEmojis) { private readonly object _writeLock = new(); public async Task<ConsoleKeyInfo> GetKeyAsync(string prompt, Func<ConsoleKeyInfo, bool> validateInput, CancellationToken cancellationToken) { if (logLevel > LogLevel.Information) { return new ConsoleKeyInfo('\u001b', ConsoleKey.Escape, shift: false, alt: false, control: false); } var questionMark = suppressEmojis ? "?" : "❔"; while (true) { // Start listening to the key before printing the prompt to avoid race condition // in tests that wait for the prompt before sending the key press. var tcs = new TaskCompletionSource<ConsoleKeyInfo>(TaskCreationOptions.RunContinuationsAsynchronously); console.KeyPressed += KeyPressed; WriteLine($" {questionMark} {prompt}"); lock (_writeLock) { console.ForegroundColor = ConsoleColor.DarkGray; console.Out.Write($" {questionMark} "); console.ResetColor(); } try { return await tcs.Task.WaitAsync(cancellationToken); } catch (ArgumentException) { // Prompt again for valid input } finally { console.KeyPressed -= KeyPressed; } void KeyPressed(ConsoleKeyInfo key) { var keyDisplay = GetDisplayString(key); if (validateInput(key)) { WriteLine(keyDisplay); tcs.TrySetResult(key); } else { WriteLine(keyDisplay, ConsoleColor.DarkRed); tcs.TrySetException(new ArgumentException($"Invalid key '{keyDisplay}' entered.")); } } static string GetDisplayString(ConsoleKeyInfo key) { var keyDisplay = (key.Modifiers == ConsoleModifiers.None) ? key.KeyChar.ToString() : key.Key.ToString(); if (key.Modifiers.HasFlag(ConsoleModifiers.Alt)) { keyDisplay = "Alt+" + keyDisplay; } if (key.Modifiers.HasFlag(ConsoleModifiers.Shift)) { keyDisplay = "Shift+" + keyDisplay; } if (key.Modifiers.HasFlag(ConsoleModifiers.Control)) { keyDisplay = "Ctrl+" + keyDisplay; } return keyDisplay; } } void WriteLine(string message, ConsoleColor color = ConsoleColor.DarkGray) { lock (_writeLock) { console.ForegroundColor = color; console.Out.WriteLine(message); console.ResetColor(); } } } }