mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-29 17:28:01 +01:00
* Replace all 342 `== null` with `is null`
* Replace 354 `!= null` with `is { }`
* Wrap these in conditionals since they break tests against Release configuration
The members they depend on do not exist in Release configuration
* Split these up and dispose properly
This test needs to be revisited for several reasons at some point.
* Fix release configuration tests
* Declare interface these already support
* Annotate constructor properly and use throw helper
* Move class to its own file
* Rename these files so they nest in the solution explorer
* Make this a record type and remove now-redundant/illegal members
* Reference passing to avoid some struct copies
* Simplify this
* Carry reference passing through as appropriate
* Turn this into a record struct
* Remove unused internal constructor and its test
It was only used by that test.
* Simplify this constructor
* This should be a property
* Simplify constructor
* Simplify GetHashCode
* Mark this ignored just in case
* Missed a couple of opportunities for reference passing
* record struct already does this by value
* Remove unused class
* Simplify the type initializer and Reset method
* Implement INotifyCollectionChanged and IDictionary by delegating to ColorSchemes
* Fix for reflection-based configuration
* Make CI build happy by disambiguiating this attribute
148 lines
6.6 KiB
C#
148 lines
6.6 KiB
C#
#nullable enable
|
|
using System.Buffers;
|
|
|
|
namespace Terminal.Gui;
|
|
|
|
/// <summary>Extensions to <see cref="string"/> to support TUI text manipulation.</summary>
|
|
public static class StringExtensions
|
|
{
|
|
/// <summary>Unpacks the last UTF-8 encoding in the string.</summary>
|
|
/// <remarks>This is a Terminal.Gui extension method to <see cref="string"/> to support TUI text manipulation.</remarks>
|
|
/// <param name="str">The string to decode.</param>
|
|
/// <param name="end">Index in string to stop at; if -1, use the buffer length.</param>
|
|
/// <returns></returns>
|
|
public static (Rune rune, int size) DecodeLastRune (this string str, int end = -1)
|
|
{
|
|
Rune rune = str.EnumerateRunes ().ToArray () [end == -1 ? ^1 : end];
|
|
byte [] bytes = Encoding.UTF8.GetBytes (rune.ToString ());
|
|
OperationStatus operationStatus = Rune.DecodeFromUtf8 (bytes, out rune, out int bytesConsumed);
|
|
|
|
if (operationStatus == OperationStatus.Done)
|
|
{
|
|
return (rune, bytesConsumed);
|
|
}
|
|
|
|
return (Rune.ReplacementChar, 1);
|
|
}
|
|
|
|
/// <summary>Unpacks the first UTF-8 encoding in the string and returns the rune and its width in bytes.</summary>
|
|
/// <remarks>This is a Terminal.Gui extension method to <see cref="string"/> to support TUI text manipulation.</remarks>
|
|
/// <param name="str">The string to decode.</param>
|
|
/// <param name="start">Starting offset.</param>
|
|
/// <param name="count">Number of bytes in the buffer, or -1 to make it the length of the buffer.</param>
|
|
/// <returns></returns>
|
|
public static (Rune Rune, int Size) DecodeRune (this string str, int start = 0, int count = -1)
|
|
{
|
|
Rune rune = str.EnumerateRunes ().ToArray () [start];
|
|
byte [] bytes = Encoding.UTF8.GetBytes (rune.ToString ());
|
|
|
|
if (count == -1)
|
|
{
|
|
count = bytes.Length;
|
|
}
|
|
|
|
OperationStatus operationStatus = Rune.DecodeFromUtf8 (bytes, out rune, out int bytesConsumed);
|
|
|
|
if (operationStatus == OperationStatus.Done && bytesConsumed >= count)
|
|
{
|
|
return (rune, bytesConsumed);
|
|
}
|
|
|
|
return (Rune.ReplacementChar, 1);
|
|
}
|
|
|
|
/// <summary>Gets the number of columns the string occupies in the terminal.</summary>
|
|
/// <remarks>This is a Terminal.Gui extension method to <see cref="string"/> to support TUI text manipulation.</remarks>
|
|
/// <param name="str">The string to measure.</param>
|
|
/// <returns></returns>
|
|
public static int GetColumns (this string str) { return str is null ? 0 : str.EnumerateRunes ().Sum (r => Math.Max (r.GetColumns (), 0)); }
|
|
|
|
/// <summary>Gets the number of runes in the string.</summary>
|
|
/// <remarks>This is a Terminal.Gui extension method to <see cref="string"/> to support TUI text manipulation.</remarks>
|
|
/// <param name="str">The string to count.</param>
|
|
/// <returns></returns>
|
|
public static int GetRuneCount (this string str) { return str.EnumerateRunes ().Count (); }
|
|
|
|
/// <summary>
|
|
/// Determines if this <see cref="ReadOnlySpan{T}"/> of <see langword="char"/> is composed entirely of ASCII
|
|
/// digits.
|
|
/// </summary>
|
|
/// <param name="stringSpan">A <see cref="ReadOnlySpan{T}"/> of <see langword="char"/> to check.</param>
|
|
/// <returns>
|
|
/// A <see langword="bool"/> indicating if all elements of the <see cref="ReadOnlySpan{T}"/> are ASCII digits (
|
|
/// <see langword="true"/>) or not (<see langword="false"/>
|
|
/// </returns>
|
|
public static bool IsAllAsciiDigits (this ReadOnlySpan<char> stringSpan) { return stringSpan.ToString ().All (char.IsAsciiDigit); }
|
|
|
|
/// <summary>
|
|
/// Determines if this <see cref="ReadOnlySpan{T}"/> of <see langword="char"/> is composed entirely of ASCII
|
|
/// digits.
|
|
/// </summary>
|
|
/// <param name="stringSpan">A <see cref="ReadOnlySpan{T}"/> of <see langword="char"/> to check.</param>
|
|
/// <returns>
|
|
/// A <see langword="bool"/> indicating if all elements of the <see cref="ReadOnlySpan{T}"/> are ASCII digits (
|
|
/// <see langword="true"/>) or not (<see langword="false"/>
|
|
/// </returns>
|
|
public static bool IsAllAsciiHexDigits (this ReadOnlySpan<char> stringSpan) { return stringSpan.ToString ().All (char.IsAsciiHexDigit); }
|
|
|
|
/// <summary>Repeats the string <paramref name="n"/> times.</summary>
|
|
/// <remarks>This is a Terminal.Gui extension method to <see cref="string"/> to support TUI text manipulation.</remarks>
|
|
/// <param name="str">The text to repeat.</param>
|
|
/// <param name="n">Number of times to repeat the text.</param>
|
|
/// <returns>The text repeated if <paramref name="n"/> is greater than zero, otherwise <see langword="null"/>.</returns>
|
|
public static string? Repeat (this string str, int n)
|
|
{
|
|
if (n <= 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (string.IsNullOrEmpty (str) || n == 1)
|
|
{
|
|
return str;
|
|
}
|
|
|
|
return new StringBuilder (str.Length * n)
|
|
.Insert (0, str, n)
|
|
.ToString ();
|
|
}
|
|
|
|
/// <summary>Converts the string into a <see cref="List{Rune}"/>.</summary>
|
|
/// <remarks>This is a Terminal.Gui extension method to <see cref="string"/> to support TUI text manipulation.</remarks>
|
|
/// <param name="str">The string to convert.</param>
|
|
/// <returns></returns>
|
|
public static List<Rune> ToRuneList (this string str) { return str.EnumerateRunes ().ToList (); }
|
|
|
|
/// <summary>Converts the string into a <see cref="Rune"/> array.</summary>
|
|
/// <remarks>This is a Terminal.Gui extension method to <see cref="string"/> to support TUI text manipulation.</remarks>
|
|
/// <param name="str">The string to convert.</param>
|
|
/// <returns></returns>
|
|
public static Rune [] ToRunes (this string str) { return str.EnumerateRunes ().ToArray (); }
|
|
|
|
/// <summary>Converts a <see cref="Rune"/> generic collection into a string.</summary>
|
|
/// <param name="runes">The enumerable rune to convert.</param>
|
|
/// <returns></returns>
|
|
public static string ToString (IEnumerable<Rune> runes)
|
|
{
|
|
var str = string.Empty;
|
|
|
|
foreach (Rune rune in runes)
|
|
{
|
|
str += rune.ToString ();
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
/// <summary>Converts a byte generic collection into a string in the provided encoding (default is UTF8)</summary>
|
|
/// <param name="bytes">The enumerable byte to convert.</param>
|
|
/// <param name="encoding">The encoding to be used.</param>
|
|
/// <returns></returns>
|
|
public static string ToString (IEnumerable<byte> bytes, Encoding? encoding = null)
|
|
{
|
|
encoding ??= Encoding.UTF8;
|
|
|
|
return encoding.GetString (bytes.ToArray ());
|
|
}
|
|
}
|