Add link support for supported terminals

Also refactors the code quite a bit, to make it a bit more
easier to add features like this in the future.

Closes #75
This commit is contained in:
Patrik Svensson
2020-09-11 00:34:45 +02:00
committed by Patrik Svensson
parent 1601ef24b3
commit 504746c5dc
33 changed files with 574 additions and 1539 deletions

View File

@ -1,6 +1,5 @@
using System;
using System.Linq;
using Spectre.Console.Internal;
using Spectre.Console.Rendering;
namespace Spectre.Console
@ -28,30 +27,18 @@ namespace Spectre.Console
}
var options = new RenderContext(console.Encoding, console.Capabilities.LegacyConsole);
var segments = renderable.Render(options, console.Width).Where(x => !(x.Text.Length == 0 && !x.IsLineBreak)).ToArray();
segments = Segment.Merge(segments).ToArray();
using (console.PushStyle(Style.Plain))
var current = Style.Plain;
foreach (var segment in segments)
{
var segments = renderable.Render(options, console.Width).Where(x => !(x.Text.Length == 0 && !x.IsLineBreak)).ToArray();
segments = Segment.Merge(segments).ToArray();
var current = Style.Plain;
foreach (var segment in segments)
if (string.IsNullOrEmpty(segment.Text))
{
if (string.IsNullOrEmpty(segment.Text))
{
continue;
}
if (!segment.Style.Equals(current))
{
console.Foreground = segment.Style.Foreground;
console.Background = segment.Style.Background;
console.Decoration = segment.Style.Decoration;
current = segment.Style;
}
console.Write(segment.Text);
continue;
}
console.Write(segment.Text, segment.Style);
}
}
}

View File

@ -1,339 +0,0 @@
using System;
using System.Globalization;
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="IAnsiConsole"/>.
/// </summary>
public static partial class AnsiConsoleExtensions
{
/// <summary>
/// Writes the specified string value to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void Write(this IAnsiConsole console, string value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
if (value != null)
{
console.Write(value);
}
}
/// <summary>
/// Writes the text representation of the specified 32-bit
/// signed integer value to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void Write(this IAnsiConsole console, int value)
{
Write(console, CultureInfo.CurrentCulture, value);
}
/// <summary>
/// Writes the text representation of the specified 32-bit
/// signed integer value to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="value">The value to write.</param>
public static void Write(this IAnsiConsole console, IFormatProvider provider, int value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
console.Write(value.ToString(provider));
}
/// <summary>
/// Writes the text representation of the specified 32-bit
/// unsigned integer value to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void Write(this IAnsiConsole console, uint value)
{
Write(console, CultureInfo.CurrentCulture, value);
}
/// <summary>
/// Writes the text representation of the specified 32-bit
/// unsigned integer value to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="value">The value to write.</param>
public static void Write(this IAnsiConsole console, IFormatProvider provider, uint value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
console.Write(value.ToString(provider));
}
/// <summary>
/// Writes the text representation of the specified 64-bit
/// signed integer value to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void Write(this IAnsiConsole console, long value)
{
Write(console, CultureInfo.CurrentCulture, value);
}
/// <summary>
/// Writes the text representation of the specified 64-bit
/// signed integer value to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="value">The value to write.</param>
public static void Write(this IAnsiConsole console, IFormatProvider provider, long value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
console.Write(value.ToString(provider));
}
/// <summary>
/// Writes the text representation of the specified 64-bit
/// unsigned integer value to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void Write(this IAnsiConsole console, ulong value)
{
Write(console, CultureInfo.CurrentCulture, value);
}
/// <summary>
/// Writes the text representation of the specified 64-bit
/// unsigned integer value to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="value">The value to write.</param>
public static void Write(this IAnsiConsole console, IFormatProvider provider, ulong value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
console.Write(value.ToString(provider));
}
/// <summary>
/// Writes the text representation of the specified single-precision
/// floating-point value to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void Write(this IAnsiConsole console, float value)
{
Write(console, CultureInfo.CurrentCulture, value);
}
/// <summary>
/// Writes the text representation of the specified single-precision
/// floating-point value to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="value">The value to write.</param>
public static void Write(this IAnsiConsole console, IFormatProvider provider, float value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
console.Write(value.ToString(provider));
}
/// <summary>
/// Writes the text representation of the specified double-precision
/// floating-point value to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void Write(this IAnsiConsole console, double value)
{
Write(console, CultureInfo.CurrentCulture, value);
}
/// <summary>
/// Writes the text representation of the specified double-precision
/// floating-point value to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="value">The value to write.</param>
public static void Write(this IAnsiConsole console, IFormatProvider provider, double value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
console.Write(value.ToString(provider));
}
/// <summary>
/// Writes the text representation of the specified decimal value, to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void Write(this IAnsiConsole console, decimal value)
{
Write(console, CultureInfo.CurrentCulture, value);
}
/// <summary>
/// Writes the text representation of the specified decimal value, to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="value">The value to write.</param>
public static void Write(this IAnsiConsole console, IFormatProvider provider, decimal value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
Write(console, value.ToString(provider));
}
/// <summary>
/// Writes the text representation of the specified boolean value to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void Write(this IAnsiConsole console, bool value)
{
Write(console, CultureInfo.CurrentCulture, value);
}
/// <summary>
/// Writes the text representation of the specified boolean value to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="value">The value to write.</param>
public static void Write(this IAnsiConsole console, IFormatProvider provider, bool value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
Write(console, value.ToString(provider));
}
/// <summary>
/// Writes the specified Unicode character to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void Write(this IAnsiConsole console, char value)
{
Write(console, CultureInfo.CurrentCulture, value);
}
/// <summary>
/// Writes the specified Unicode character to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="value">The value to write.</param>
public static void Write(this IAnsiConsole console, IFormatProvider provider, char value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
Write(console, value.ToString(provider));
}
/// <summary>
/// Writes the specified array of Unicode characters to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void Write(this IAnsiConsole console, char[] value)
{
Write(console, CultureInfo.CurrentCulture, value);
}
/// <summary>
/// Writes the specified array of Unicode characters to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="value">The value to write.</param>
public static void Write(this IAnsiConsole console, IFormatProvider provider, char[] value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
if (value is null)
{
throw new ArgumentNullException(nameof(value));
}
for (var index = 0; index < value.Length; index++)
{
console.Write(value[index].ToString(provider));
}
}
/// <summary>
/// Writes the text representation of the specified array of objects,
/// to the console using the specified format information.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="format">A composite format string.</param>
/// <param name="args">An array of objects to write.</param>
public static void Write(this IAnsiConsole console, string format, params object[] args)
{
Write(console, CultureInfo.CurrentCulture, format, args);
}
/// <summary>
/// Writes the text representation of the specified array of objects,
/// to the console using the specified format information.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="format">A composite format string.</param>
/// <param name="args">An array of objects to write.</param>
public static void Write(this IAnsiConsole console, IFormatProvider provider, string format, params object[] args)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
Write(console, string.Format(provider, format, args));
}
}
}

View File

@ -1,368 +0,0 @@
using System;
using System.Globalization;
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="IAnsiConsole"/>.
/// </summary>
public static partial class AnsiConsoleExtensions
{
/// <summary>
/// Writes an empty line to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
public static void WriteLine(this IAnsiConsole console)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
console.Write(Environment.NewLine);
}
/// <summary>
/// Writes the specified string value, followed by the
/// current line terminator, to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void WriteLine(this IAnsiConsole console, string value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
if (value != null)
{
console.Write(value);
}
console.WriteLine();
}
/// <summary>
/// Writes the text representation of the specified 32-bit signed integer value,
/// followed by the current line terminator, to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void WriteLine(this IAnsiConsole console, int value)
{
WriteLine(console, CultureInfo.CurrentCulture, value);
}
/// <summary>
/// Writes the text representation of the specified 32-bit signed integer value,
/// followed by the current line terminator, to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="value">The value to write.</param>
public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, int value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
console.WriteLine(value.ToString(provider));
}
/// <summary>
/// Writes the text representation of the specified 32-bit unsigned integer value,
/// followed by the current line terminator, to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void WriteLine(this IAnsiConsole console, uint value)
{
WriteLine(console, CultureInfo.CurrentCulture, value);
}
/// <summary>
/// Writes the text representation of the specified 32-bit unsigned integer value,
/// followed by the current line terminator, to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="value">The value to write.</param>
public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, uint value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
console.WriteLine(value.ToString(provider));
}
/// <summary>
/// Writes the text representation of the specified 64-bit signed integer value,
/// followed by the current line terminator, to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void WriteLine(this IAnsiConsole console, long value)
{
WriteLine(console, CultureInfo.CurrentCulture, value);
}
/// <summary>
/// Writes the text representation of the specified 64-bit signed integer value,
/// followed by the current line terminator, to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="value">The value to write.</param>
public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, long value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
console.WriteLine(value.ToString(provider));
}
/// <summary>
/// Writes the text representation of the specified 64-bit unsigned integer value,
/// followed by the current line terminator, to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void WriteLine(this IAnsiConsole console, ulong value)
{
WriteLine(console, CultureInfo.CurrentCulture, value);
}
/// <summary>
/// Writes the text representation of the specified 64-bit unsigned integer value,
/// followed by the current line terminator, to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="value">The value to write.</param>
public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, ulong value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
console.WriteLine(value.ToString(provider));
}
/// <summary>
/// Writes the text representation of the specified single-precision floating-point
/// value, followed by the current line terminator, to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void WriteLine(this IAnsiConsole console, float value)
{
WriteLine(console, CultureInfo.CurrentCulture, value);
}
/// <summary>
/// Writes the text representation of the specified single-precision floating-point
/// value, followed by the current line terminator, to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="value">The value to write.</param>
public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, float value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
console.WriteLine(value.ToString(provider));
}
/// <summary>
/// Writes the text representation of the specified double-precision floating-point
/// value, followed by the current line terminator, to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void WriteLine(this IAnsiConsole console, double value)
{
WriteLine(console, CultureInfo.CurrentCulture, value);
}
/// <summary>
/// Writes the text representation of the specified double-precision floating-point
/// value, followed by the current line terminator, to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="value">The value to write.</param>
public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, double value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
console.WriteLine(value.ToString(provider));
}
/// <summary>
/// Writes the text representation of the specified decimal value,
/// followed by the current line terminator, to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void WriteLine(this IAnsiConsole console, decimal value)
{
WriteLine(console, CultureInfo.CurrentCulture, value);
}
/// <summary>
/// Writes the text representation of the specified decimal value,
/// followed by the current line terminator, to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="value">The value to write.</param>
public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, decimal value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
WriteLine(console, value.ToString(provider));
}
/// <summary>
/// Writes the text representation of the specified boolean value,
/// followed by the current line terminator, to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void WriteLine(this IAnsiConsole console, bool value)
{
WriteLine(console, CultureInfo.CurrentCulture, value);
}
/// <summary>
/// Writes the text representation of the specified boolean value,
/// followed by the current line terminator, to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="value">The value to write.</param>
public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, bool value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
WriteLine(console, value.ToString(provider));
}
/// <summary>
/// Writes the specified Unicode character, followed by the current
/// line terminator, value to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void WriteLine(this IAnsiConsole console, char value)
{
WriteLine(console, CultureInfo.CurrentCulture, value);
}
/// <summary>
/// Writes the specified Unicode character, followed by the current
/// line terminator, value to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="value">The value to write.</param>
public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, char value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
WriteLine(console, value.ToString(provider));
}
/// <summary>
/// Writes the specified array of Unicode characters, followed by the current
/// line terminator, value to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="value">The value to write.</param>
public static void WriteLine(this IAnsiConsole console, char[] value)
{
WriteLine(console, CultureInfo.CurrentCulture, value);
}
/// <summary>
/// Writes the specified array of Unicode characters, followed by the current
/// line terminator, value to the console.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="value">The value to write.</param>
public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, char[] value)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
if (value is null)
{
throw new ArgumentNullException(nameof(value));
}
for (var index = 0; index < value.Length; index++)
{
console.Write(value[index].ToString(provider));
}
console.WriteLine();
}
/// <summary>
/// Writes the text representation of the specified array of objects,
/// followed by the current line terminator, to the console
/// using the specified format information.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="format">A composite format string.</param>
/// <param name="args">An array of objects to write.</param>
public static void WriteLine(this IAnsiConsole console, string format, params object[] args)
{
WriteLine(console, CultureInfo.CurrentCulture, format, args);
}
/// <summary>
/// Writes the text representation of the specified array of objects,
/// followed by the current line terminator, to the console
/// using the specified format information.
/// </summary>
/// <param name="console">The console to write to.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <param name="format">A composite format string.</param>
/// <param name="args">An array of objects to write.</param>
public static void WriteLine(this IAnsiConsole console, IFormatProvider provider, string format, params object[] args)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
WriteLine(console, string.Format(provider, format, args));
}
}
}

View File

@ -8,47 +8,34 @@ namespace Spectre.Console
public static partial class AnsiConsoleExtensions
{
/// <summary>
/// Resets colors and text decorations.
/// Writes an empty line to the console.
/// </summary>
/// <param name="console">The console to reset.</param>
public static void Reset(this IAnsiConsole console)
/// <param name="console">The console to write to.</param>
public static void WriteLine(this IAnsiConsole console)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
console.ResetColors();
console.ResetDecoration();
console.Write(Environment.NewLine, Style.Plain);
}
/// <summary>
/// Resets the current applied text decorations.
/// Writes the specified string value, followed by the current line terminator, to the console.
/// </summary>
/// <param name="console">The console to reset the text decorations for.</param>
public static void ResetDecoration(this IAnsiConsole console)
/// <param name="console">The console to write to.</param>
/// <param name="text">The text to write.</param>
/// <param name="style">The text style.</param>
public static void WriteLine(this IAnsiConsole console, string text, Style style)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
console.Decoration = Decoration.None;
}
/// <summary>
/// Resets the current applied foreground and background colors.
/// </summary>
/// <param name="console">The console to reset colors for.</param>
public static void ResetColors(this IAnsiConsole console)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
console.Foreground = Color.Default;
console.Background = Color.Default;
console.Write(text, style);
console.WriteLine();
}
}
}

View File

@ -66,5 +66,26 @@ namespace Spectre.Console
background: style.Background,
decoration: decoration);
}
/// <summary>
/// Creates a new style from the specified one with
/// the specified link.
/// </summary>
/// <param name="style">The style.</param>
/// <param name="link">The link.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static Style WithLink(this Style style, string link)
{
if (style is null)
{
throw new ArgumentNullException(nameof(style));
}
return new Style(
foreground: style.Foreground,
background: style.Background,
decoration: style.Decoration,
link: link);
}
}
}