mirror of
https://github.com/nsnail/spectre.console.git
synced 2025-06-19 13:28:16 +08:00
Add link identity generator
This commit is contained in:
@ -55,7 +55,7 @@ namespace Spectre.Console
|
||||
/// <returns>An <see cref="IAnsiConsole"/> instance.</returns>
|
||||
public static IAnsiConsole Create(AnsiConsoleSettings settings)
|
||||
{
|
||||
return ConsoleBuilder.Build(settings);
|
||||
return AnsiConsoleBuilder.Build(settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,11 @@ namespace Spectre.Console
|
||||
/// </summary>
|
||||
public ColorSystemSupport ColorSystem { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the link identity generator.
|
||||
/// </summary>
|
||||
public ILinkIdentityGenerator? LinkIdentityGenerator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the out buffer.
|
||||
/// </summary>
|
||||
|
@ -12,6 +12,11 @@ namespace Spectre.Console
|
||||
/// </summary>
|
||||
Capabilities Capabilities { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the console output encoding.
|
||||
/// </summary>
|
||||
Encoding Encoding { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the buffer width of the console.
|
||||
/// </summary>
|
||||
@ -22,11 +27,6 @@ namespace Spectre.Console
|
||||
/// </summary>
|
||||
int Height { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the console output encoding.
|
||||
/// </summary>
|
||||
Encoding Encoding { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Writes a string followed by a line terminator to the console.
|
||||
/// </summary>
|
||||
|
16
src/Spectre.Console/ILinkIdentityGenerator.cs
Normal file
16
src/Spectre.Console/ILinkIdentityGenerator.cs
Normal file
@ -0,0 +1,16 @@
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a link identity generator.
|
||||
/// </summary>
|
||||
public interface ILinkIdentityGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates an ID for the given link.
|
||||
/// </summary>
|
||||
/// <param name="link">The link.</param>
|
||||
/// <param name="text">The link text.</param>
|
||||
/// <returns>A unique ID for the link.</returns>
|
||||
public int GenerateId(string link, string text);
|
||||
}
|
||||
}
|
@ -3,12 +3,18 @@ using System.Linq;
|
||||
|
||||
namespace Spectre.Console.Internal
|
||||
{
|
||||
internal static class AnsiBuilder
|
||||
internal sealed class AnsiBuilder
|
||||
{
|
||||
public static string GetAnsi(
|
||||
Capabilities capabilities,
|
||||
string text,
|
||||
Style style)
|
||||
private readonly Capabilities _capabilities;
|
||||
private readonly ILinkIdentityGenerator _linkHasher;
|
||||
|
||||
public AnsiBuilder(Capabilities capabilities, ILinkIdentityGenerator? linkHasher)
|
||||
{
|
||||
_capabilities = capabilities ?? throw new ArgumentNullException(nameof(capabilities));
|
||||
_linkHasher = linkHasher ?? new LinkIdentityGenerator();
|
||||
}
|
||||
|
||||
public string GetAnsi(string text, Style style)
|
||||
{
|
||||
if (style is null)
|
||||
{
|
||||
@ -22,7 +28,7 @@ namespace Spectre.Console.Internal
|
||||
{
|
||||
codes = codes.Concat(
|
||||
AnsiColorBuilder.GetAnsiCodes(
|
||||
capabilities.ColorSystem,
|
||||
_capabilities.ColorSystem,
|
||||
style.Foreground,
|
||||
true));
|
||||
}
|
||||
@ -32,7 +38,7 @@ namespace Spectre.Console.Internal
|
||||
{
|
||||
codes = codes.Concat(
|
||||
AnsiColorBuilder.GetAnsiCodes(
|
||||
capabilities.ColorSystem,
|
||||
_capabilities.ColorSystem,
|
||||
style.Background,
|
||||
false));
|
||||
}
|
||||
@ -48,7 +54,7 @@ namespace Spectre.Console.Internal
|
||||
? $"\u001b[{ansiCodes}m{text}\u001b[0m"
|
||||
: text;
|
||||
|
||||
if (style.Link != null && !capabilities.LegacyConsole)
|
||||
if (style.Link != null && !_capabilities.LegacyConsole)
|
||||
{
|
||||
var link = style.Link;
|
||||
|
||||
@ -58,7 +64,7 @@ namespace Spectre.Console.Internal
|
||||
link = text;
|
||||
}
|
||||
|
||||
var linkId = Math.Abs(link.GetDeterministicHashCode());
|
||||
var linkId = _linkHasher.GenerateId(link, text);
|
||||
ansi = $"\u001b]8;id={linkId};{link}\u001b\\{ansi}\u001b]8;;\u001b\\";
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ using System.Runtime.InteropServices;
|
||||
|
||||
namespace Spectre.Console.Internal
|
||||
{
|
||||
internal static class ConsoleBuilder
|
||||
internal static class AnsiConsoleBuilder
|
||||
{
|
||||
public static IAnsiConsole Build(AnsiConsoleSettings settings)
|
||||
{
|
||||
@ -54,12 +54,18 @@ namespace Spectre.Console.Internal
|
||||
? ColorSystemDetector.Detect(supportsAnsi)
|
||||
: (ColorSystem)settings.ColorSystem;
|
||||
|
||||
// Get the capabilities
|
||||
var capabilities = new Capabilities(supportsAnsi, colorSystem, legacyConsole);
|
||||
|
||||
// Create the renderer
|
||||
if (supportsAnsi)
|
||||
{
|
||||
return new AnsiConsoleRenderer(buffer, colorSystem, legacyConsole);
|
||||
return new AnsiConsoleRenderer(buffer, capabilities, settings.LinkIdentityGenerator);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new FallbackConsoleRenderer(buffer, capabilities);
|
||||
}
|
||||
|
||||
return new FallbackConsoleRenderer(buffer, colorSystem, legacyConsole);
|
||||
}
|
||||
}
|
||||
}
|
@ -7,6 +7,7 @@ namespace Spectre.Console.Internal
|
||||
internal sealed class AnsiConsoleRenderer : IAnsiConsole
|
||||
{
|
||||
private readonly TextWriter _out;
|
||||
private readonly AnsiBuilder _ansiBuilder;
|
||||
|
||||
public Capabilities Capabilities { get; }
|
||||
public Encoding Encoding { get; }
|
||||
@ -37,12 +38,14 @@ namespace Spectre.Console.Internal
|
||||
}
|
||||
}
|
||||
|
||||
public AnsiConsoleRenderer(TextWriter @out, ColorSystem system, bool legacyConsole)
|
||||
public AnsiConsoleRenderer(TextWriter @out, Capabilities capabilities, ILinkIdentityGenerator? linkHasher)
|
||||
{
|
||||
_out = @out ?? throw new ArgumentNullException(nameof(@out));
|
||||
|
||||
Capabilities = new Capabilities(true, system, legacyConsole);
|
||||
Encoding = @out.IsStandardOut() ? System.Console.OutputEncoding : Encoding.UTF8;
|
||||
Capabilities = capabilities ?? throw new ArgumentNullException(nameof(capabilities));
|
||||
Encoding = _out.IsStandardOut() ? System.Console.OutputEncoding : Encoding.UTF8;
|
||||
|
||||
_ansiBuilder = new AnsiBuilder(Capabilities, linkHasher);
|
||||
}
|
||||
|
||||
public void Write(string text, Style style)
|
||||
@ -59,7 +62,7 @@ namespace Spectre.Console.Internal
|
||||
{
|
||||
if (!string.IsNullOrEmpty(part))
|
||||
{
|
||||
_out.Write(AnsiBuilder.GetAnsi(Capabilities, part, style));
|
||||
_out.Write(_ansiBuilder.GetAnsi(part, style));
|
||||
}
|
||||
|
||||
if (!last)
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
@ -38,10 +39,15 @@ namespace Spectre.Console.Internal
|
||||
}
|
||||
}
|
||||
|
||||
public FallbackConsoleRenderer(TextWriter @out, ColorSystem system, bool legacyConsole)
|
||||
public FallbackConsoleRenderer(TextWriter @out, Capabilities capabilities)
|
||||
{
|
||||
_out = @out;
|
||||
_system = system;
|
||||
if (capabilities == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(capabilities));
|
||||
}
|
||||
|
||||
_out = @out ?? throw new ArgumentNullException(nameof(@out));
|
||||
_system = capabilities.ColorSystem;
|
||||
|
||||
if (_out.IsStandardOut())
|
||||
{
|
||||
@ -52,7 +58,7 @@ namespace Spectre.Console.Internal
|
||||
Encoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
Capabilities = new Capabilities(false, _system, legacyConsole);
|
||||
Capabilities = capabilities;
|
||||
}
|
||||
|
||||
public void Write(string text, Style style)
|
||||
|
31
src/Spectre.Console/Internal/LinkIdentityGenerator.cs
Normal file
31
src/Spectre.Console/Internal/LinkIdentityGenerator.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console.Internal
|
||||
{
|
||||
internal sealed class LinkIdentityGenerator : ILinkIdentityGenerator
|
||||
{
|
||||
private readonly Random _random;
|
||||
|
||||
public LinkIdentityGenerator()
|
||||
{
|
||||
_random = new Random(DateTime.Now.Millisecond);
|
||||
}
|
||||
|
||||
public int GenerateId(string link, string text)
|
||||
{
|
||||
if (link is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(link));
|
||||
}
|
||||
|
||||
link += text ?? string.Empty;
|
||||
|
||||
unchecked
|
||||
{
|
||||
return Math.Abs(
|
||||
link.GetHashCode() +
|
||||
_random.Next(0, int.MaxValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user