mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-06-19 13:28:16 +08:00

committed by
Phil Scott

parent
2e5d18fa78
commit
fd4b96944e
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