11using System ;
2+ using System . Diagnostics . CodeAnalysis ;
23using System . Threading ;
34using System . Threading . Tasks ;
45using Spectre . Console ;
@@ -82,43 +83,46 @@ public static ILogger HorizontalRule(this ILogger @this, string? title = null)
8283 /// Logs a <see cref="Progress"/> to the console.
8384 /// </summary>
8485 /// <param name="this">The <see cref="ILogger"/> instance to log the progress to.</param>
85- /// <param name="action">An action that receives the <see cref="Progress "/> instance to configure it and add tasks to it.</param>
86+ /// <param name="action">An action that receives the <see cref="ProgressContext "/> instance to configure it and add tasks to it.</param>
8687 /// <param name="cancellationToken">A cancellation token that can be used to cancel the progress operation.</param>
8788 /// <returns>A <see cref="Task"/> that represents the asynchronous progress operation.</returns>
88- public static async Task ProgressAsync ( this ILogger @this , Func < Progress , Task > action , CancellationToken cancellationToken = default )
89+ public static Task ProgressAsync ( this ILogger @this , Func < ProgressContext , Task > action , CancellationToken cancellationToken = default )
8990 {
9091 ArgumentNullException . ThrowIfNull ( @this ) ;
91- ArgumentNullException . ThrowIfNull ( action ) ;
92-
93- ProgressStartPayload startPayload = new ( )
94- {
95- CancellationToken = cancellationToken ,
96- } ;
97-
98- @this . Log ( null , startPayload ) ;
99-
100- Progress progress = await startPayload . WaitForProgressAsync ( ) . ConfigureAwait ( false ) ;
10192
102- await action ( progress ) . ConfigureAwait ( false ) ;
93+ TaskCompletionSource taskCompletionSource = new ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
10394
104- ProgressFinishedPayload finishedPayload = new ( )
95+ ProgressPayload payload = new ( )
10596 {
106- CancellationToken = cancellationToken ,
97+ ExecuteAsync = async console =>
98+ {
99+ try
100+ {
101+ await console . Progress ( ) . StartAsync ( action ) . ConfigureAwait ( false ) ;
102+
103+ taskCompletionSource . SetResult ( ) ;
104+ }
105+ catch ( Exception exception )
106+ {
107+ taskCompletionSource . SetException ( exception ) ;
108+ }
109+ } ,
107110 } ;
108111
109- @this . Log ( null , finishedPayload ) ;
112+ @this . Log ( null , payload ) ;
110113
111- await finishedPayload . WaitForFinishedAsync ( ) . ConfigureAwait ( false ) ;
114+ return taskCompletionSource . Task ;
112115 }
113116
114117 /// <summary>
115118 /// Logs a <see cref="Status"/> to the console.
116119 /// </summary>
117120 /// <param name="this">The <see cref="ILogger"/> instance to log the status to.</param>
121+ /// <param name="status">The status text to display.</param>
118122 /// <param name="action">An action that receives the <see cref="Status"/> instance to configure it and add tasks to it.</param>
119123 /// <param name="cancellationToken">A cancellation token that can be used to cancel the status operation.</param>
120124 /// <returns>A <see cref="Task"/> that represents the asynchronous status operation.</returns>
121- public static async Task StatusAsync ( this ILogger @this , Func < Status , Task > action , CancellationToken cancellationToken = default )
125+ public static Task StatusAsync ( this ILogger @this , string status , Func < StatusContext , Task > action , CancellationToken cancellationToken = default )
122126 {
123127 ArgumentNullException . ThrowIfNull ( @this ) ;
124128 ArgumentNullException . ThrowIfNull ( action ) ;
@@ -128,19 +132,88 @@ public static async Task StatusAsync(this ILogger @this, Func<Status, Task> acti
128132 CancellationToken = cancellationToken ,
129133 } ;
130134
131- @this . Log ( null , startPayload ) ;
135+ TaskCompletionSource taskCompletionSource = new ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
132136
133- Status status = await startPayload . WaitForStatusAsync ( ) . ConfigureAwait ( false ) ;
137+ StatusPayload statusPayload = new ( )
138+ {
139+ ExecuteAsync = async console =>
140+ {
141+ try
142+ {
143+ await console . Status ( ) . StartAsync ( status , action ) . ConfigureAwait ( false ) ;
144+
145+ taskCompletionSource . SetResult ( ) ;
146+ }
147+ catch ( Exception exception )
148+ {
149+ taskCompletionSource . SetException ( exception ) ;
150+ }
151+ } ,
152+ } ;
134153
135- await action ( status ) . ConfigureAwait ( false ) ;
154+ @this . Log ( null , statusPayload ) ;
136155
137- StatusFinishedPayload finishedPayload = new ( )
156+ return taskCompletionSource . Task ;
157+ }
158+
159+ [ SuppressMessage ( "Design" , "CA1031:Do not catch general exception types" , Justification = "We want to catch all exceptions to set them on the payload." ) ]
160+ public static Task < bool > ConfirmAsync ( this ILogger @this , string prompt , bool defaultValue = true , CancellationToken cancellationToken = default )
161+ {
162+ ArgumentNullException . ThrowIfNull ( @this ) ;
163+ ArgumentNullException . ThrowIfNull ( prompt ) ;
164+
165+ TaskCompletionSource < bool > taskCompletionSource = new ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
166+
167+ ConfirmPayload payload = new ( )
138168 {
139- CancellationToken = cancellationToken ,
169+ ExecuteAsync = async console =>
170+ {
171+ try
172+ {
173+ bool result = await console . ConfirmAsync ( prompt , defaultValue , cancellationToken : cancellationToken ) . ConfigureAwait ( false ) ;
174+
175+ taskCompletionSource . SetResult ( result ) ;
176+ }
177+ catch ( Exception exception )
178+ {
179+ taskCompletionSource . SetException ( exception ) ;
180+ }
181+ } ,
182+ } ;
183+
184+ @this . Log ( null , payload ) ;
185+
186+ return taskCompletionSource . Task ;
187+ }
188+
189+ [ SuppressMessage ( "Design" , "CA1031:Do not catch general exception types" , Justification = "We want to catch all exceptions to set them on the payload." ) ]
190+ public static Task < T > AskAsync < T > ( this ILogger @this , string prompt , CancellationToken cancellationToken = default )
191+ where T : notnull
192+ {
193+ ArgumentNullException . ThrowIfNull ( @this ) ;
194+ ArgumentNullException . ThrowIfNull ( prompt ) ;
195+
196+ TaskCompletionSource < T > taskCompletionSource = new ( TaskCreationOptions . RunContinuationsAsynchronously ) ;
197+
198+ AskPayload payload = new ( )
199+ {
200+ ExecuteAsync = async console =>
201+ {
202+ try
203+ {
204+ T result = await console . AskAsync < T > ( prompt , cancellationToken : cancellationToken ) . ConfigureAwait ( false ) ;
205+
206+ taskCompletionSource . TrySetResult ( result ) ;
207+ }
208+ catch ( Exception exception )
209+ {
210+ taskCompletionSource . TrySetException ( exception ) ;
211+ }
212+ } ,
140213 } ;
141214
142- @this . Log ( null , finishedPayload ) ;
215+ @this . Log ( null , payload ) ;
143216
144- await finishedPayload . WaitForFinishedAsync ( ) . ConfigureAwait ( false ) ;
217+ return taskCompletionSource . Task ;
145218 }
146219}
0 commit comments