Skip to content

[dotnet-watch] Use Spectre.Console for target framework selection#53540

Open
jonathanpeppers wants to merge 3 commits intorelease/10.0.3xxfrom
dev/peppers/dotnet-watch-spectre.console
Open

[dotnet-watch] Use Spectre.Console for target framework selection#53540
jonathanpeppers wants to merge 3 commits intorelease/10.0.3xxfrom
dev/peppers/dotnet-watch-spectre.console

Conversation

@jonathanpeppers
Copy link
Member

Replace the basic numeric-key console prompt with Spectre.Console's SelectionPrompt for target framework selection in dotnet-watch. This matches the dotnet-run behavior and provides arrow key navigation, search, and pagination.

  • Add Spectre.Console dependency to Watch library (Spectre.Console is already in source-build)

  • Add Spectre.Console.Testing for unit tests (Spectre.Console.Testing is not in source-build but is only used for tests)

  • Accept IAnsiConsole in TargetFrameworkSelectionPrompt for testability

  • Localize prompt strings in Resources.resx

  • Rewrite tests to drive the prompt via TestConsole key presses

@jonathanpeppers jonathanpeppers requested review from a team and tmat as code owners March 19, 2026 18:59
Copilot AI review requested due to automatic review settings March 19, 2026 18:59
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates dotnet-watch’s target framework selection UX to use Spectre.Console’s SelectionPrompt, enabling arrow-key navigation, search, and paging, and aligns behavior with dotnet-run.

Changes:

  • Add Spectre.Console to the watch implementation and Spectre.Console.Testing to the test project.
  • Replace the numeric-key TFM selector with a Spectre SelectionPrompt-based selector (injectable IAnsiConsole for testability).
  • Localize the new prompt strings via Resources.resx (and propagate entries to .xlf files).

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
test/dotnet-watch.Tests/dotnet-watch.Tests.csproj Adds Spectre.Console.Testing package reference for prompt-driving tests.
test/dotnet-watch.Tests/HotReload/TargetFrameworkSelectionPromptTests.cs Rewrites tests to drive Spectre prompt via key presses/search input.
src/Dotnet.Watch/dotnet-watch/Resources.resx Adds localized strings for the new prompt UI text.
src/Dotnet.Watch/dotnet-watch/xlf/Resources.*.xlf Adds localization entries for the new prompt strings across languages.
src/Dotnet.Watch/dotnet-watch/Program.cs Wires up the new prompt instance (when interactive) into Hot Reload watcher.
src/Dotnet.Watch/Watch/UI/TargetFrameworkSelectionPrompt.cs Replaces numeric input prompt with Spectre.Console SelectionPrompt.
src/Dotnet.Watch/Watch/Microsoft.DotNet.HotReload.Watch.csproj Adds Spectre.Console dependency.
src/Dotnet.Watch/Watch/HotReload/HotReloadDotNetWatcher.cs Accepts an optional prompt instance via constructor and passes selector delegate to build logic.
Directory.Packages.props Adds central version for Spectre.Console.Testing.

Replace the basic numeric-key console prompt with Spectre.Console's
SelectionPrompt for target framework selection in dotnet-watch. This
matches the dotnet-run behavior and provides arrow key navigation,
search, and pagination.

- Add Spectre.Console dependency to Watch library
- Add Spectre.Console.Testing for unit tests
- Accept IAnsiConsole in TargetFrameworkSelectionPrompt for testability
- Use ShowAsync with CancellationToken for cancellation support
- Localize prompt strings in Resources.resx
- Rewrite tests to drive the prompt via TestConsole key presses

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@jonathanpeppers jonathanpeppers force-pushed the dev/peppers/dotnet-watch-spectre.console branch from b6f35fd to e517e7e Compare March 19, 2026 19:16
namespace Microsoft.DotNet.Watch;

internal sealed class TargetFrameworkSelectionPrompt(ConsoleInputReader inputReader)
internal sealed class TargetFrameworkSelectionPrompt(string title, string moreChoicesText, string searchPlaceholderText, IAnsiConsole? console = null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be better to make this an abstract class and define a derived class in dotnet-watch. That way we can avoid adding Spectre dependency to Watch project, which is used in Aspire as a headless server.

internal Task? Test_FileChangesCompletedTask { get; set; }

public HotReloadDotNetWatcher(DotNetWatchContext context, IConsole console, IRuntimeProcessLauncherFactory? runtimeProcessLauncherFactory)
public HotReloadDotNetWatcher(DotNetWatchContext context, IConsole console, IRuntimeProcessLauncherFactory? runtimeProcessLauncherFactory, TargetFrameworkSelectionPrompt? targetFrameworkSelectionPrompt = null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not use optional parameter and pass null explicitly where needed.

jonathanpeppers and others added 2 commits March 19, 2026 16:24
… dotnet-watch

Address review feedback: make TargetFrameworkSelectionPrompt an abstract
class in the Watch library (no Spectre dependency) with a derived
SpectreTargetFrameworkSelectionPrompt in dotnet-watch. This avoids
adding the Spectre.Console dependency to the Watch library, which is
also used by Aspire as a headless server.

Also make the targetFrameworkSelectionPrompt constructor parameter
non-optional, passing null explicitly where needed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Type the target framework name via stdin to search and select it,
replacing the old numeric key approach.

Add KeyPressedAnsiConsole/KeyPressedInput to bridge IConsole.KeyPressed
events to Spectre.Console's IAnsiConsoleInput when stdin is redirected.
This lets PhysicalConsole.ListenToStandardInputAsync remain the single
stdin reader, with Spectre receiving keys through the same pipeline.

Also extend PhysicalConsole's stdin key mapping to handle '.', '-',
Enter, and use ConsoleKey.D0-D9 (matching Spectre's expectations).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants