mirror of
				https://github.com/nsnail/spectre.console.git
				synced 2025-11-01 01:25:27 +08:00 
			
		
		
		
	 Patrik Svensson
					Patrik Svensson
				
			
				
					committed by
					
						 Phil Scott
						Phil Scott
					
				
			
			
				
	
			
			
			 Phil Scott
						Phil Scott
					
				
			
						parent
						
							2e5d18fa78
						
					
				
				
					commit
					fd4b96944e
				
			| @@ -10,7 +10,7 @@ namespace Spectre.Console.Testing | ||||
|             return func(); | ||||
|         } | ||||
|  | ||||
|         public async Task<T> Run<T>(Func<Task<T>> func) | ||||
|         public async Task<T> RunAsync<T>(Func<Task<T>> func) | ||||
|         { | ||||
|             return await func().ConfigureAwait(false); | ||||
|         } | ||||
|   | ||||
| @@ -66,6 +66,12 @@ namespace Spectre.Console.Testing | ||||
|             _input.Enqueue(new ConsoleKeyInfo((char)input, input, false, false, false)); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public bool IsKeyAvailable() | ||||
|         { | ||||
|             return _input.Count > 0; | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public ConsoleKeyInfo? ReadKey(bool intercept) | ||||
|         { | ||||
|   | ||||
							
								
								
									
										19
									
								
								src/Spectre.Console/AnsiConsole.Screen.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/Spectre.Console/AnsiConsole.Screen.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// A console capable of writing ANSI escape sequences. | ||||
|     /// </summary> | ||||
|     public static partial class AnsiConsole | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Switches to an alternate screen buffer if the terminal supports it. | ||||
|         /// </summary> | ||||
|         /// <param name="action">The action to execute within the alternate screen buffer.</param> | ||||
|         public static void AlternateScreen(Action action) | ||||
|         { | ||||
|             Console.AlternateScreen(action); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -55,6 +55,7 @@ namespace Spectre.Console | ||||
|             profile.Capabilities.Legacy = legacyConsole; | ||||
|             profile.Capabilities.Interactive = interactive; | ||||
|             profile.Capabilities.Unicode = encoding.EncodingName.ContainsExact("Unicode"); | ||||
|             profile.Capabilities.AlternateBuffer = supportsAnsi && !legacyConsole; | ||||
|  | ||||
|             // Enrich the profile | ||||
|             ProfileEnricher.Enrich( | ||||
|   | ||||
| @@ -55,6 +55,12 @@ namespace Spectre.Console | ||||
|         /// </summary> | ||||
|         public bool Unicode { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets a value indicating whether | ||||
|         /// or not the console supports alternate buffers. | ||||
|         /// </summary> | ||||
|         public bool AlternateBuffer { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the | ||||
|         /// <see cref="Capabilities"/> class. | ||||
|   | ||||
| @@ -29,7 +29,7 @@ namespace Spectre.Console | ||||
|         /// <returns>The result of the function.</returns> | ||||
|         public static Task<T> RunExclusive<T>(this IAnsiConsole console, Func<Task<T>> func) | ||||
|         { | ||||
|             return console.ExclusivityMode.Run(func); | ||||
|             return console.ExclusivityMode.RunAsync(func); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,48 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Contains extension methods for <see cref="IAnsiConsole"/>. | ||||
|     /// </summary> | ||||
|     public static partial class AnsiConsoleExtensions | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Switches to an alternate screen buffer if the terminal supports it. | ||||
|         /// </summary> | ||||
|         /// <param name="console">The console.</param> | ||||
|         /// <param name="action">The action to execute within the alternate screen buffer.</param> | ||||
|         public static void AlternateScreen(this IAnsiConsole console, Action action) | ||||
|         { | ||||
|             if (console is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(console)); | ||||
|             } | ||||
|  | ||||
|             if (!console.Profile.Capabilities.Ansi) | ||||
|             { | ||||
|                 throw new NotSupportedException("Alternate buffers are not supported since your terminal does not support ANSI."); | ||||
|             } | ||||
|  | ||||
|             if (!console.Profile.Capabilities.AlternateBuffer) | ||||
|             { | ||||
|                 throw new NotSupportedException("Alternate buffers are not supported by your terminal."); | ||||
|             } | ||||
|  | ||||
|             console.ExclusivityMode.Run<object?>(() => | ||||
|             { | ||||
|                 // Switch to alternate screen | ||||
|                 console.Write(new ControlCode("\u001b[?1049h\u001b[H")); | ||||
|  | ||||
|                 // Execute custom action | ||||
|                 action(); | ||||
|  | ||||
|                 // Switch back to primary screen | ||||
|                 console.Write(new ControlCode("\u001b[?1049l")); | ||||
|  | ||||
|                 // Dummy result | ||||
|                 return null; | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -9,6 +9,13 @@ namespace Spectre.Console | ||||
|     /// </summary> | ||||
|     public interface IAnsiConsoleInput | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets a value indicating whether or not | ||||
|         /// there is a key available. | ||||
|         /// </summary> | ||||
|         /// <returns><c>true</c> if there's a key available, otherwise <c>false</c>.</returns> | ||||
|         bool IsKeyAvailable(); | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Reads a key from the console. | ||||
|         /// </summary> | ||||
|   | ||||
| @@ -22,6 +22,6 @@ namespace Spectre.Console | ||||
|         /// <typeparam name="T">The result type.</typeparam> | ||||
|         /// <param name="func">The func to run in exclusive mode.</param> | ||||
|         /// <returns>The result of the function.</returns> | ||||
|         Task<T> Run<T>(Func<Task<T>> func); | ||||
|         Task<T> RunAsync<T>(Func<Task<T>> func); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -31,7 +31,7 @@ namespace Spectre.Console.Internal | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         public async Task<T> Run<T>(Func<Task<T>> func) | ||||
|         public async Task<T> RunAsync<T>(Func<Task<T>> func) | ||||
|         { | ||||
|             // Try acquiring the exclusivity semaphore | ||||
|             if (!await _semaphore.WaitAsync(0).ConfigureAwait(false)) | ||||
|   | ||||
| @@ -13,6 +13,16 @@ namespace Spectre.Console | ||||
|             _profile = profile ?? throw new ArgumentNullException(nameof(profile)); | ||||
|         } | ||||
|  | ||||
|         public bool IsKeyAvailable() | ||||
|         { | ||||
|             if (!_profile.Capabilities.Interactive) | ||||
|             { | ||||
|                 throw new InvalidOperationException("Failed to read input in non-interactive mode."); | ||||
|             } | ||||
|  | ||||
|             return System.Console.KeyAvailable; | ||||
|         } | ||||
|  | ||||
|         public ConsoleKeyInfo? ReadKey(bool intercept) | ||||
|         { | ||||
|             if (!_profile.Capabilities.Interactive) | ||||
| @@ -20,16 +30,16 @@ namespace Spectre.Console | ||||
|                 throw new InvalidOperationException("Failed to read input in non-interactive mode."); | ||||
|             } | ||||
|  | ||||
|             if (!System.Console.KeyAvailable) | ||||
|             { | ||||
|                 return null; | ||||
|             } | ||||
|  | ||||
|             return System.Console.ReadKey(intercept); | ||||
|         } | ||||
|  | ||||
|         public async Task<ConsoleKeyInfo?> ReadKeyAsync(bool intercept, CancellationToken cancellationToken) | ||||
|         { | ||||
|             if (!_profile.Capabilities.Interactive) | ||||
|             { | ||||
|                 throw new InvalidOperationException("Failed to read input in non-interactive mode."); | ||||
|             } | ||||
|  | ||||
|             while (true) | ||||
|             { | ||||
|                 if (cancellationToken.IsCancellationRequested) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user