Skip to content

Commit 0abb836

Browse files
authored
Improve console output of dotnet watch ⌚ (#23318)
* Requester * Relative File Path * Updated Rude Edit Dialog * Emojify * Tests * Test fix 2 (ChangeExcludedFile still failing) * Relative path robustness * File changed test * Arg based emojis * Remove duplicate tip message (cherry picked from commit 5ae5131)
1 parent 51ed186 commit 0abb836

26 files changed

+331
-203
lines changed

src/BuiltInTools/dotnet-watch/DotNetWatcher.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public async Task WatchAsync(DotNetWatchContext context, CancellationToken cance
9393
var args = string.Join(" ", processSpec.Arguments);
9494
_reporter.Verbose($"Running {processSpec.ShortDisplayName()} with the following arguments: {args}");
9595

96-
_reporter.Output("Started");
96+
_reporter.Output("Started", emoji: "🚀");
9797

9898
Task<FileItem?> fileSetTask;
9999
Task finishedTask;
@@ -141,7 +141,7 @@ await _staticFileHandler.TryHandleFileChange(context, fileItem, combinedCancella
141141
// Process exited. Redo evaludation
142142
context.RequiresMSBuildRevaluation = true;
143143
// Now wait for a file to change before restarting process
144-
context.ChangedFile = await fileSetWatcher.GetChangedFileAsync(cancellationToken, () => _reporter.Warn("Waiting for a file to change before restarting dotnet..."));
144+
context.ChangedFile = await fileSetWatcher.GetChangedFileAsync(cancellationToken, () => _reporter.Warn("Waiting for a file to change before restarting dotnet...", emoji: "⏳"));
145145
}
146146
else
147147
{

src/BuiltInTools/dotnet-watch/Filters/DotNetBuildFilter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public async ValueTask ProcessAsync(DotNetWatchContext context, CancellationToke
3838
WorkingDirectory = context.ProcessSpec.WorkingDirectory,
3939
};
4040

41-
_reporter.Output("Building...");
41+
_reporter.Output("Building...", emoji: "🔧");
4242
var exitCode = await _processRunner.RunAsync(processSpec, cancellationToken);
4343
context.FileSet = await _fileSetFactory.CreateAsync(cancellationToken);
4444
if (exitCode == 0)
@@ -48,7 +48,7 @@ public async ValueTask ProcessAsync(DotNetWatchContext context, CancellationToke
4848

4949
// If the build fails, we'll retry until we have a successful build.
5050
using var fileSetWatcher = new FileSetWatcher(context.FileSet, _reporter);
51-
await fileSetWatcher.GetChangedFileAsync(cancellationToken, () => _reporter.Warn("Waiting for a file to change before restarting dotnet..."));
51+
await fileSetWatcher.GetChangedFileAsync(cancellationToken, () => _reporter.Warn("Waiting for a file to change before restarting dotnet...", emoji: "⏳"));
5252
}
5353
}
5454
}

src/BuiltInTools/dotnet-watch/Filters/LaunchBrowserFilter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ private void OnOutput(object sender, DataReceivedEventArgs eventArgs)
9797
// From emperical observation, it's noted that failing to launch a browser results in either Process.Start returning a null-value
9898
// or for the process to have immediately exited.
9999
// We can use this to provide a helpful message.
100-
_reporter.Output($"Unable to launch the browser. Navigate to {launchUrl}");
100+
_reporter.Output($"Unable to launch the browser. Navigate to {launchUrl}", emoji: "🌐");
101101
}
102102
}
103103
else if (_watchContext?.BrowserRefreshServer is { } browserRefresh)

src/BuiltInTools/dotnet-watch/HotReload/CompilationHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ public async ValueTask<bool> TryHandleFileChange(DotNetWatchContext context, Fil
171171
HotReloadEventSource.Log.HotReloadEnd(HotReloadEventSource.StartType.CompilationHandler);
172172
if (applyState)
173173
{
174-
_reporter.Output($"Hot reload of changes succeeded.");
174+
_reporter.Output($"Hot reload of changes succeeded.", emoji: "🔥");
175175
}
176176

177177
return applyState;

src/BuiltInTools/dotnet-watch/HotReload/CompilationWorkspaceProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ private static async Task<ImmutableArray<string>> GetHotReloadCapabilitiesAsync(
8282
try
8383
{
8484
var capabilities = await hotReloadCapabilitiesTask;
85-
reporter.Verbose($"Hot reload capabilities: {string.Join(" ", capabilities)}.");
85+
reporter.Verbose($"Hot reload capabilities: {string.Join(" ", capabilities)}.", emoji: "🔥");
8686

8787
return capabilities;
8888
}

src/BuiltInTools/dotnet-watch/HotReload/HotReloadProfileReader.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ public static HotReloadProfile InferHotReloadProfile(ProjectGraph projectGraph,
3535
// We saw a previous project that was AspNetCore. This must he a blazor hosted app.
3636
if (aspnetCoreProject is not null && aspnetCoreProject != currentNode.ProjectInstance)
3737
{
38-
reporter.Verbose($"HotReloadProfile: BlazorHosted. {aspnetCoreProject.FullPath} references BlazorWebAssembly project {currentNode.ProjectInstance.FullPath}.");
38+
reporter.Verbose($"HotReloadProfile: BlazorHosted. {aspnetCoreProject.FullPath} references BlazorWebAssembly project {currentNode.ProjectInstance.FullPath}.", emoji: "🔥");
3939
return HotReloadProfile.BlazorHosted;
4040
}
4141

42-
reporter.Verbose("HotReloadProfile: BlazorWebAssembly.");
42+
reporter.Verbose("HotReloadProfile: BlazorWebAssembly.", emoji: "🔥");
4343
return HotReloadProfile.BlazorWebAssembly;
4444
}
4545
}
@@ -50,7 +50,7 @@ public static HotReloadProfile InferHotReloadProfile(ProjectGraph projectGraph,
5050
}
5151
}
5252

53-
reporter.Verbose("HotReloadProfile: Default.");
53+
reporter.Verbose("HotReloadProfile: Default.", emoji: "🔥");
5454
return HotReloadProfile.Default;
5555
}
5656
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright (c) .NET Foundation and contributors. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
5+
using System.Threading;
6+
using System.Threading.Tasks;
7+
using Microsoft.Extensions.Tools.Internal;
8+
9+
namespace Microsoft.DotNet.Watcher.Tools
10+
{
11+
public class RudeEditDialog
12+
{
13+
private readonly IReporter _reporter;
14+
private readonly IRequester _requester;
15+
private readonly IConsole _console;
16+
private bool? _restartImmediatelySessionPreference; // Session preference
17+
18+
public RudeEditDialog(IReporter reporter, IRequester requester, IConsole console)
19+
{
20+
_reporter = reporter;
21+
_requester = requester;
22+
_console = console;
23+
24+
var alwaysRestart = Environment.GetEnvironmentVariable("DOTNET_WATCH_RESTART_ON_RUDE_EDIT");
25+
26+
if (alwaysRestart == "1" || string.Equals(alwaysRestart, "true", StringComparison.OrdinalIgnoreCase))
27+
{
28+
_reporter.Verbose($"DOTNET_WATCH_RESTART_ON_RUDE_EDIT = '{alwaysRestart}'. Restarting without prompt.");
29+
_restartImmediatelySessionPreference = true;
30+
}
31+
}
32+
33+
public async Task EvaluateAsync(CancellationToken cancellationToken)
34+
{
35+
if (_restartImmediatelySessionPreference.HasValue)
36+
{
37+
await GetRudeEditResult(_restartImmediatelySessionPreference.Value, cancellationToken);
38+
return;
39+
}
40+
41+
var key = await _requester.GetKeyAsync(
42+
"Do you want to restart your app - Yes (y) / No (n) / Always (a) / Never (v)?",
43+
KeyPressed,
44+
cancellationToken);
45+
46+
switch (key)
47+
{
48+
case ConsoleKey.Escape:
49+
case ConsoleKey.Y:
50+
await GetRudeEditResult(restartImmediately: true, cancellationToken);
51+
return;
52+
case ConsoleKey.N:
53+
await GetRudeEditResult(restartImmediately: false, cancellationToken);
54+
return;
55+
case ConsoleKey.A:
56+
_restartImmediatelySessionPreference = true;
57+
await GetRudeEditResult(restartImmediately: true, cancellationToken);
58+
return;
59+
case ConsoleKey.V:
60+
_restartImmediatelySessionPreference = false;
61+
await GetRudeEditResult(restartImmediately: false, cancellationToken);
62+
return;
63+
}
64+
65+
bool KeyPressed(ConsoleKey key)
66+
{
67+
return key is ConsoleKey.Y or ConsoleKey.N or ConsoleKey.A or ConsoleKey.V;
68+
}
69+
}
70+
71+
private Task GetRudeEditResult(bool restartImmediately, CancellationToken cancellationToken)
72+
{
73+
if (restartImmediately)
74+
{
75+
return Task.CompletedTask;
76+
}
77+
78+
_reporter.Output("Hot reload suspended. To continue hot reload, press \"Ctrl + R\".", emoji: "🔥");
79+
80+
return Task.Delay(-1, cancellationToken);
81+
}
82+
}
83+
}

src/BuiltInTools/dotnet-watch/HotReload/RudeEditPreference.cs

Lines changed: 0 additions & 95 deletions
This file was deleted.

src/BuiltInTools/dotnet-watch/HotReload/ScopedCssFileHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public async ValueTask<bool> TryHandleFileChange(DotNetWatchContext context, Fil
4040
return false;
4141
}
4242
await HandleBrowserRefresh(context.BrowserRefreshServer, file, cancellationToken);
43-
_reporter.Output("Hot reload of scoped css succeeded.");
43+
_reporter.Output("Hot reload of scoped css succeeded.", emoji: "🔥");
4444
HotReloadEventSource.Log.HotReloadEnd(HotReloadEventSource.StartType.ScopedCssHandler);
4545
return true;
4646
}

src/BuiltInTools/dotnet-watch/HotReload/StaticFileHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public async ValueTask<bool> TryHandleFileChange(DotNetWatchContext context, Fil
3434
_reporter.Verbose($"Handling file change event for static content {file.FilePath}.");
3535
await HandleBrowserRefresh(context.BrowserRefreshServer, file, cancellationToken);
3636
HotReloadEventSource.Log.HotReloadEnd(HotReloadEventSource.StartType.StaticHandler);
37-
_reporter.Output("Hot reload of static file succeeded.");
37+
_reporter.Output("Hot reload of static file succeeded.", emoji: "🔥");
3838
return true;
3939
}
4040

0 commit comments

Comments
 (0)