Add link identity generator

This commit is contained in:
Patrik Svensson
2020-09-12 14:47:32 +02:00
parent 101e244059
commit ce670a7ca9
20 changed files with 242 additions and 174 deletions

View File

@ -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\\";
}

View File

@ -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);
}
}
}

View File

@ -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)

View File

@ -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)

View 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));
}
}
}
}