diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 87cccc0..c939ba5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -21,7 +21,7 @@ jobs: - name: Setup dotnet uses: actions/setup-dotnet@v1 with: - dotnet-version: '3.1.301' # SDK Version to use. + dotnet-version: 5.0.100 - name: Build shell: bash @@ -55,10 +55,15 @@ jobs: with: fetch-depth: 0 - - name: Setup dotnet + - name: Setup dotnet 3.1.402 uses: actions/setup-dotnet@v1 with: - dotnet-version: 3.1.301 + dotnet-version: 3.1.402 + + - name: Setup dotnet 5.0.100 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 5.0.100 - name: Integration Tests shell: bash diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index abe1a91..da9e941 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -24,7 +24,7 @@ jobs: - name: Setup dotnet uses: actions/setup-dotnet@v1 with: - dotnet-version: '3.1.301' # SDK Version to use. + dotnet-version: 5.0.100 - name: Publish shell: bash diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 4b9f6b4..8adfa0c 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -29,7 +29,7 @@ jobs: - name: Setup dotnet uses: actions/setup-dotnet@v1 with: - dotnet-version: '3.1.301' # SDK Version to use. + dotnet-version: 5.0.100 - name: Build shell: bash @@ -64,10 +64,15 @@ jobs: with: fetch-depth: 0 - - name: Setup dotnet + - name: Setup dotnet 3.1.402 uses: actions/setup-dotnet@v1 with: - dotnet-version: 3.1.301 + dotnet-version: 3.1.402 + + - name: Setup dotnet 5.0.100 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 5.0.100 - name: Build shell: bash @@ -90,10 +95,15 @@ jobs: with: fetch-depth: 0 - - name: Setup dotnet + - name: Setup dotnet 3.1.402 uses: actions/setup-dotnet@v1 with: - dotnet-version: 3.1.301 + dotnet-version: 3.1.402 + + - name: Setup dotnet 5.0.100 + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 5.0.100 - name: Publish shell: bash diff --git a/docs/Docs.csproj b/docs/Docs.csproj index 088a316..b398bd3 100644 --- a/docs/Docs.csproj +++ b/docs/Docs.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 $(MSBuildProjectDirectory) $(DefaultItemExcludes);output\**;.gitignore true diff --git a/dotnet-tools.json b/dotnet-tools.json index b1854bc..57b0606 100644 --- a/dotnet-tools.json +++ b/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "cake.tool": { - "version": "0.38.4", + "version": "1.0.0-rc0001", "commands": [ "dotnet-cake" ] @@ -15,7 +15,7 @@ ] }, "dotnet-example": { - "version": "1.0.0", + "version": "1.1.0", "commands": [ "dotnet-example" ] diff --git a/examples/Borders/Borders.csproj b/examples/Borders/Borders.csproj index a0950b5..492bbd5 100644 --- a/examples/Borders/Borders.csproj +++ b/examples/Borders/Borders.csproj @@ -1,8 +1,8 @@ - + Exe - netcoreapp3.1 + net5.0 false Borders Demonstrates the different kind of borders. diff --git a/examples/Calendars/Calendars.csproj b/examples/Calendars/Calendars.csproj index fbc20a6..116dfa2 100644 --- a/examples/Calendars/Calendars.csproj +++ b/examples/Calendars/Calendars.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 false Calendars Demonstrates how to render calendars. diff --git a/examples/Colors/Colors.csproj b/examples/Colors/Colors.csproj index 4d5a1c5..55ab209 100644 --- a/examples/Colors/Colors.csproj +++ b/examples/Colors/Colors.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 false Colors Demonstrates how to use [yellow]c[/][red]o[/][green]l[/][blue]o[/][aqua]r[/][lime]s[/] in the console. diff --git a/examples/Columns/Columns.csproj b/examples/Columns/Columns.csproj index 3232517..efbe910 100644 --- a/examples/Columns/Columns.csproj +++ b/examples/Columns/Columns.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 false Columns Demonstrates how to render data into columns. diff --git a/examples/Cursor/Cursor.csproj b/examples/Cursor/Cursor.csproj index 1c06842..721c41b 100644 --- a/examples/Cursor/Cursor.csproj +++ b/examples/Cursor/Cursor.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 false Cursor Demonstrates how to move the cursor. diff --git a/examples/Emojis/Emojis.csproj b/examples/Emojis/Emojis.csproj index 56d9359..7fa39a9 100644 --- a/examples/Emojis/Emojis.csproj +++ b/examples/Emojis/Emojis.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 false Emojis Demonstrates how to render emojis. diff --git a/examples/Exceptions/Exceptions.csproj b/examples/Exceptions/Exceptions.csproj index 19d600a..7ff8afa 100644 --- a/examples/Exceptions/Exceptions.csproj +++ b/examples/Exceptions/Exceptions.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 false Exceptions Demonstrates how to render formatted exceptions. diff --git a/examples/Grids/Grids.csproj b/examples/Grids/Grids.csproj index eb186e2..914a1de 100644 --- a/examples/Grids/Grids.csproj +++ b/examples/Grids/Grids.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 false Grids Demonstrates how to render grids in a console. diff --git a/examples/Info/Info.csproj b/examples/Info/Info.csproj index c481f99..bde96a4 100644 --- a/examples/Info/Info.csproj +++ b/examples/Info/Info.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 false Info Displays the capabilities of the current console. diff --git a/examples/Links/Links.csproj b/examples/Links/Links.csproj index 20480bb..3b91568 100644 --- a/examples/Links/Links.csproj +++ b/examples/Links/Links.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 false Links Demonstrates how to render links in a console. diff --git a/examples/Panels/Panels.csproj b/examples/Panels/Panels.csproj index 125afa8..21abf28 100644 --- a/examples/Panels/Panels.csproj +++ b/examples/Panels/Panels.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 false Panels Demonstrates how to render items in panels. diff --git a/examples/Rules/Rules.csproj b/examples/Rules/Rules.csproj index b07b72c..9522281 100644 --- a/examples/Rules/Rules.csproj +++ b/examples/Rules/Rules.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 false Rules Demonstrates how to render horizontal rules (lines). diff --git a/examples/Tables/Tables.csproj b/examples/Tables/Tables.csproj index 3b4c13e..287b416 100644 --- a/examples/Tables/Tables.csproj +++ b/examples/Tables/Tables.csproj @@ -2,7 +2,7 @@ Exe - netcoreapp3.1 + net5.0 false Tables Demonstrates how to render tables in a console. diff --git a/global.json b/global.json index 54ed6bc..edc20ab 100644 --- a/global.json +++ b/global.json @@ -1,7 +1,7 @@ { "projects": [ "src" ], "sdk": { - "version": "3.1.301", + "version": "5.0.100", "rollForward": "latestPatch" } } \ No newline at end of file diff --git a/src/Spectre.Console.Tests/Spectre.Console.Tests.csproj b/src/Spectre.Console.Tests/Spectre.Console.Tests.csproj index ee1aa9b..5c43420 100644 --- a/src/Spectre.Console.Tests/Spectre.Console.Tests.csproj +++ b/src/Spectre.Console.Tests/Spectre.Console.Tests.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net5.0;netcoreapp3.1 false diff --git a/src/Spectre.Console/Internal/Extensions/DayOfWeekExtensions.cs b/src/Spectre.Console/Extensions/DayOfWeekExtensions.cs similarity index 100% rename from src/Spectre.Console/Internal/Extensions/DayOfWeekExtensions.cs rename to src/Spectre.Console/Extensions/DayOfWeekExtensions.cs diff --git a/src/Spectre.Console/Internal/Extensions/DictionaryExtensions.cs b/src/Spectre.Console/Extensions/DictionaryExtensions.cs similarity index 100% rename from src/Spectre.Console/Internal/Extensions/DictionaryExtensions.cs rename to src/Spectre.Console/Extensions/DictionaryExtensions.cs diff --git a/src/Spectre.Console/Internal/Extensions/EnumerableExtensions.cs b/src/Spectre.Console/Extensions/EnumerableExtensions.cs similarity index 99% rename from src/Spectre.Console/Internal/Extensions/EnumerableExtensions.cs rename to src/Spectre.Console/Extensions/EnumerableExtensions.cs index c1028a8..3172af7 100644 --- a/src/Spectre.Console/Internal/Extensions/EnumerableExtensions.cs +++ b/src/Spectre.Console/Extensions/EnumerableExtensions.cs @@ -69,11 +69,13 @@ namespace Spectre.Console.Internal return source.Select((value, index) => func(value, index)); } +#if !NET5_0 public static IEnumerable<(TFirst First, TSecond Second)> Zip( this IEnumerable source, IEnumerable first) { return source.Zip(first, (first, second) => (first, second)); } +#endif public static IEnumerable<(TFirst First, TSecond Second, TThird Third)> Zip( this IEnumerable first, IEnumerable second, IEnumerable third) diff --git a/src/Spectre.Console/Extensions/StringExtensions.cs b/src/Spectre.Console/Extensions/StringExtensions.cs index 99567b3..e17649a 100644 --- a/src/Spectre.Console/Extensions/StringExtensions.cs +++ b/src/Spectre.Console/Extensions/StringExtensions.cs @@ -1,3 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using Spectre.Console.Internal; +using Spectre.Console.Rendering; + namespace Spectre.Console { /// @@ -5,6 +13,11 @@ namespace Spectre.Console /// public static class StringExtensions { + // Cache whether or not internally normalized line endings + // already are normalized. No reason to do yet another replace if it is. + private static readonly bool _alreadyNormalized + = Environment.NewLine.Equals("\n", StringComparison.OrdinalIgnoreCase); + /// /// Escapes text so that it won’t be interpreted as markup. /// @@ -18,8 +31,137 @@ namespace Spectre.Console } return text - .Replace("[", "[[") - .Replace("]", "]]"); + .ReplaceExact("[", "[[") + .ReplaceExact("]", "]]"); + } + + internal static int CellLength(this string text, RenderContext context) + { + if (context is null) + { + throw new ArgumentNullException(nameof(context)); + } + + return Cell.GetCellLength(context, text); + } + + internal static string Capitalize(this string text, CultureInfo? culture = null) + { + if (text == null) + { + return string.Empty; + } + + culture ??= CultureInfo.InvariantCulture; + + if (text.Length > 0 && char.IsLower(text[0])) + { + text = string.Format(culture, "{0}{1}", char.ToUpper(text[0], culture), text.Substring(1)); + } + + return text; + } + + internal static string NormalizeLineEndings(this string? text, bool native = false) + { + text = text?.ReplaceExact("\r\n", "\n"); + text = text?.ReplaceExact("\r", string.Empty); + text ??= string.Empty; + + if (native && !_alreadyNormalized) + { + text = text.ReplaceExact("\n", Environment.NewLine); + } + + return text; + } + + internal static string[] SplitLines(this string text) + { + var result = text?.NormalizeLineEndings()?.Split(new[] { '\n' }, StringSplitOptions.None); + return result ?? Array.Empty(); + } + + internal static string[] SplitWords(this string word, StringSplitOptions options = StringSplitOptions.None) + { + var result = new List(); + + static string Read(StringBuffer reader, Func criteria) + { + var buffer = new StringBuilder(); + while (!reader.Eof) + { + var current = reader.Peek(); + if (!criteria(current)) + { + break; + } + + buffer.Append(reader.Read()); + } + + return buffer.ToString(); + } + + using (var reader = new StringBuffer(word)) + { + while (!reader.Eof) + { + var current = reader.Peek(); + if (char.IsWhiteSpace(current)) + { + var x = Read(reader, c => char.IsWhiteSpace(c)); + if (options != StringSplitOptions.RemoveEmptyEntries) + { + result.Add(x); + } + } + else + { + result.Add(Read(reader, c => !char.IsWhiteSpace(c))); + } + } + } + + return result.ToArray(); + } + + internal static string Repeat(this string text, int count) + { + if (text is null) + { + throw new ArgumentNullException(nameof(text)); + } + + if (count <= 0) + { + return string.Empty; + } + + if (count == 1) + { + return text; + } + + return string.Concat(Enumerable.Repeat(text, count)); + } + + internal static string ReplaceExact(this string text, string oldValue, string? newValue) + { +#if NET5_0 + return text.Replace(oldValue, newValue, StringComparison.Ordinal); +#else + return text.Replace(oldValue, newValue); +#endif + } + + internal static bool ContainsExact(this string text, string value) + { +#if NET5_0 + return text.Contains(value, StringComparison.Ordinal); +#else + return text.Contains(value); +#endif } } } diff --git a/src/Spectre.Console/Extensions/StyleExtensions.cs b/src/Spectre.Console/Extensions/StyleExtensions.cs index 99b8c57..b61ffca 100644 --- a/src/Spectre.Console/Extensions/StyleExtensions.cs +++ b/src/Spectre.Console/Extensions/StyleExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace Spectre.Console { @@ -87,5 +88,26 @@ namespace Spectre.Console decoration: style.Decoration, link: link); } + + internal static Style Combine(this Style style, IEnumerable