mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-31 10:17:55 +01:00
Add XML Document and move the Rune folder into the Text folder.
This commit is contained in:
@@ -1,110 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Terminal.Gui {
|
||||
public static class RuneExtensions {
|
||||
public static Rune MaxRune = new Rune (0x10FFFF);
|
||||
|
||||
public static int ColumnWidth (this Rune rune)
|
||||
{
|
||||
return RuneUtilities.ColumnWidth (rune);
|
||||
}
|
||||
|
||||
public static bool IsNonSpacingChar (this Rune rune)
|
||||
{
|
||||
return RuneUtilities.IsNonSpacingChar (rune.Value);
|
||||
}
|
||||
|
||||
public static bool IsWideChar (this Rune rune)
|
||||
{
|
||||
return RuneUtilities.IsWideChar (rune.Value);
|
||||
}
|
||||
|
||||
public static int RuneUnicodeLength (this Rune rune, Encoding encoding = null)
|
||||
{
|
||||
if (encoding == null) {
|
||||
encoding = Encoding.UTF8;
|
||||
}
|
||||
var bytes = encoding.GetBytes (rune.ToString ().ToCharArray ());
|
||||
var offset = 0;
|
||||
if (bytes [bytes.Length - 1] == 0) {
|
||||
offset++;
|
||||
}
|
||||
return bytes.Length - offset;
|
||||
}
|
||||
|
||||
public static int EncodeRune (this Rune rune, byte [] dest, int start = 0, int nbytes = -1)
|
||||
{
|
||||
var bytes = Encoding.UTF8.GetBytes (rune.ToString ());
|
||||
int length = 0;
|
||||
for (int i = 0; i < (nbytes == -1 ? bytes.Length : nbytes); i++) {
|
||||
if (bytes [i] == 0) {
|
||||
break;
|
||||
}
|
||||
dest [start + i] = bytes [i];
|
||||
length++;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
public static (Rune Rune, int Size) DecodeRune (byte [] buffer, int start = 0, int nbytes = -1)
|
||||
{
|
||||
var operationStatus = Rune.DecodeFromUtf8 (buffer, out Rune rune, out int bytesConsumed);
|
||||
return (rune, bytesConsumed);
|
||||
}
|
||||
|
||||
public static (Rune Rune, int Size) DecodeLastRune (byte [] buffer, int end = -1)
|
||||
{
|
||||
var operationStatus = Rune.DecodeLastFromUtf8 (buffer, out Rune rune, out int bytesConsumed);
|
||||
if (operationStatus == System.Buffers.OperationStatus.Done) {
|
||||
return (rune, bytesConsumed);
|
||||
} else {
|
||||
return (default, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool DecodeSurrogatePair (this Rune rune, out char [] spair)
|
||||
{
|
||||
if (rune.IsSurrogatePair ()) {
|
||||
spair = rune.ToString ().ToCharArray ();
|
||||
return true;
|
||||
}
|
||||
spair = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool EncodeSurrogatePair (char highsurrogate, char lowSurrogate, out Rune result)
|
||||
{
|
||||
result = default;
|
||||
if (char.IsSurrogatePair (highsurrogate, lowSurrogate)) {
|
||||
result = (Rune)char.ConvertToUtf32 (highsurrogate, lowSurrogate);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsSurrogatePair (this Rune rune)
|
||||
{
|
||||
return char.IsSurrogatePair (rune.ToString (), 0);
|
||||
}
|
||||
|
||||
public static bool IsValid (byte [] buffer)
|
||||
{
|
||||
var str = Encoding.Unicode.GetString (buffer);
|
||||
foreach (var rune in str.EnumerateRunes ()) {
|
||||
if (rune == Rune.ReplacementChar) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool IsValid (this Rune rune)
|
||||
{
|
||||
return Rune.IsValid (rune.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,37 +32,93 @@ namespace Terminal.Gui {
|
||||
.ToString ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of columns used by the string on console applications.
|
||||
/// It's never return less than 0, like the <see cref="RuneExtensions.ColumnWidth(Rune)"/>.
|
||||
/// </summary>
|
||||
/// <param name="instr">The string to measure.</param>
|
||||
/// <returns></returns>
|
||||
public static int ConsoleWidth (this string instr)
|
||||
{
|
||||
return instr.EnumerateRunes ().Sum (r => Math.Max (r.ColumnWidth (), 0));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of runes in a string.
|
||||
/// </summary>
|
||||
/// <param name="instr">The string to count.</param>
|
||||
/// <returns></returns>
|
||||
public static int RuneCount (this string instr)
|
||||
{
|
||||
return instr.EnumerateRunes ().Count ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string into a <see cref="Rune"/> array.
|
||||
/// </summary>
|
||||
/// <param name="instr">The string to convert.</param>
|
||||
/// <returns></returns>
|
||||
public static Rune [] ToRunes (this string instr)
|
||||
{
|
||||
return instr.EnumerateRunes ().ToArray ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string into a List of runes.
|
||||
/// </summary>
|
||||
/// <param name="instr">The string to convert.</param>
|
||||
/// <returns></returns>
|
||||
public static List<Rune> ToRuneList (this string instr)
|
||||
{
|
||||
return instr.EnumerateRunes ().ToList ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DecodeRune unpacks the first UTF-8 encoding in the string returns the rune and its width in bytes.
|
||||
/// </summary>
|
||||
/// <param name="instr">The string to decode.</param>
|
||||
/// <param name="start">Starting offset to look into.</param>
|
||||
/// <param name="nbytes">Number of bytes valid 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 instr, int start = 0, int nbytes = -1)
|
||||
{
|
||||
return RuneExtensions.DecodeRune (Encoding.UTF8.GetBytes (instr), start, nbytes);
|
||||
var rune = instr.EnumerateRunes ().ToArray () [start];
|
||||
var bytes = Encoding.UTF8.GetBytes (rune.ToString ());
|
||||
if (nbytes == -1) {
|
||||
nbytes = bytes.Length;
|
||||
}
|
||||
var operationStatus = Rune.DecodeFromUtf8 (bytes, out rune, out int bytesConsumed);
|
||||
if (operationStatus == System.Buffers.OperationStatus.Done && bytesConsumed >= nbytes) {
|
||||
return (rune, bytesConsumed);
|
||||
} else {
|
||||
return (Rune.ReplacementChar, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DecodeLastRune unpacks the last UTF-8 encoding in the string.
|
||||
/// </summary>
|
||||
/// <param name="instr">The string to decode.</param>
|
||||
/// <param name="end">Scan up to that point, if the value is -1, it sets the value to the length of the buffer.</param>
|
||||
/// <returns></returns>
|
||||
public static (Rune rune, int size) DecodeLastRune (this string instr, int end = -1)
|
||||
{
|
||||
var bytes = Encoding.UTF8.GetBytes (instr);
|
||||
return RuneExtensions.DecodeLastRune (bytes, end);
|
||||
var rune = instr.EnumerateRunes ().ToArray () [end == -1 ? ^1 : end];
|
||||
var bytes = Encoding.UTF8.GetBytes (rune.ToString ());
|
||||
var operationStatus = Rune.DecodeFromUtf8 (bytes, out rune, out int bytesConsumed);
|
||||
if (operationStatus == System.Buffers.OperationStatus.Done) {
|
||||
return (rune, bytesConsumed);
|
||||
} else {
|
||||
return (Rune.ReplacementChar, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reports whether this <see cref="Rune"/> is a valid surrogate pair and can be decoded from UTF-16.
|
||||
/// </summary>
|
||||
/// <param name="instr">The string to decode.</param>
|
||||
/// <param name="chars">The chars if is valid. Null otherwise.</param>
|
||||
/// <returns></returns>
|
||||
public static bool DecodeSurrogatePair (this string instr, out char [] chars)
|
||||
{
|
||||
chars = null;
|
||||
@@ -76,11 +132,22 @@ namespace Terminal.Gui {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a version of the string as a byte array, it might allocate or return
|
||||
/// the internal byte buffer, depending on the backing implementation.
|
||||
/// </summary>
|
||||
/// <param name="instr">The string to convert.</param>
|
||||
/// <returns></returns>
|
||||
public static byte [] ToByteArray (this string instr)
|
||||
{
|
||||
return Encoding.Unicode.GetBytes (instr.ToCharArray ());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="Rune"/> array into a string.
|
||||
/// </summary>
|
||||
/// <param name="runes">The rune array to convert.</param>
|
||||
/// <returns></returns>
|
||||
public static string Make (Rune [] runes)
|
||||
{
|
||||
var str = string.Empty;
|
||||
@@ -92,6 +159,11 @@ namespace Terminal.Gui {
|
||||
return str;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a List of runes into a string.
|
||||
/// </summary>
|
||||
/// <param name="runes">The List of runes to convert.</param>
|
||||
/// <returns></returns>
|
||||
public static string Make (List<Rune> runes)
|
||||
{
|
||||
var str = string.Empty;
|
||||
@@ -101,16 +173,32 @@ namespace Terminal.Gui {
|
||||
return str;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a rune into a string.
|
||||
/// </summary>
|
||||
/// <param name="rune">The rune to convert.</param>
|
||||
/// <returns></returns>
|
||||
public static string Make (Rune rune)
|
||||
{
|
||||
return rune.ToString ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a numeric value of a rune into a string.
|
||||
/// </summary>
|
||||
/// <param name="rune">The rune to convert.</param>
|
||||
/// <returns></returns>
|
||||
public static string Make (uint rune)
|
||||
{
|
||||
return ((Rune)rune).ToString ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a byte array into a string in te provided encoding (default is UTF8)
|
||||
/// </summary>
|
||||
/// <param name="bytes">The byte array to convert.</param>
|
||||
/// <param name="encoding">The encoding to be used.</param>
|
||||
/// <returns></returns>
|
||||
public static string Make (byte [] bytes, Encoding encoding = null)
|
||||
{
|
||||
if (encoding == null) {
|
||||
@@ -119,6 +207,11 @@ namespace Terminal.Gui {
|
||||
return encoding.GetString (bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a array of characters into a string.
|
||||
/// </summary>
|
||||
/// <param name="chars">The array of characters to convert.</param>
|
||||
/// <returns></returns>
|
||||
public static string Make (params char [] chars)
|
||||
{
|
||||
var c = new char [chars.Length];
|
||||
|
||||
194
Terminal.Gui/Text/Rune/RuneExtensions.cs
Normal file
194
Terminal.Gui/Text/Rune/RuneExtensions.cs
Normal file
@@ -0,0 +1,194 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Terminal.Gui {
|
||||
/// <summary>
|
||||
/// Extension helper of <see cref="System.Text.Rune"/> to work with specific text manipulation./>
|
||||
/// </summary>
|
||||
public static class RuneExtensions {
|
||||
/// <summary>
|
||||
/// Maximum valid Unicode code point.
|
||||
/// </summary>
|
||||
public static Rune MaxRune = new Rune (0x10FFFF);
|
||||
|
||||
/// <summary>
|
||||
/// Number of column positions of a wide-character code.
|
||||
/// This is used to measure runes as displayed by text-based terminals.
|
||||
/// </summary>
|
||||
/// <param name="rune">The rune to measure.</param>
|
||||
/// <returns>
|
||||
/// The width in columns, 0 if the argument is the null character,
|
||||
/// -1 if the value is not printable,
|
||||
/// otherwise the number of columns that the rune occupies.
|
||||
/// </returns>
|
||||
public static int ColumnWidth (this Rune rune)
|
||||
{
|
||||
return RuneUtilities.ColumnWidth (rune);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the rune is a non-spacing character.
|
||||
/// </summary>
|
||||
/// <param name="rune">The rune to inspect.</param>
|
||||
/// <returns>True if is a non-spacing character, false otherwise.</returns>
|
||||
public static bool IsNonSpacingChar (this Rune rune)
|
||||
{
|
||||
return RuneUtilities.IsNonSpacingChar (rune.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the rune is a wide character.
|
||||
/// </summary>
|
||||
/// <param name="rune">The rune to inspect.</param>
|
||||
/// <returns>True if is a wide character, false otherwise.</returns>
|
||||
public static bool IsWideChar (this Rune rune)
|
||||
{
|
||||
return RuneUtilities.IsWideChar (rune.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get number of bytes required to encode the rune, based on the provided encoding.
|
||||
/// </summary>
|
||||
/// <param name="rune">The rune to probe.</param>
|
||||
/// <param name="encoding">The encoding used, default is UTF8.</param>
|
||||
/// <returns></returns>
|
||||
public static int RuneUnicodeLength (this Rune rune, Encoding encoding = null)
|
||||
{
|
||||
if (encoding == null) {
|
||||
encoding = Encoding.UTF8;
|
||||
}
|
||||
var bytes = encoding.GetBytes (rune.ToString ().ToCharArray ());
|
||||
var offset = 0;
|
||||
if (bytes [bytes.Length - 1] == 0) {
|
||||
offset++;
|
||||
}
|
||||
return bytes.Length - offset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes into the destination buffer starting at offset the UTF8 encoded version of the rune.
|
||||
/// </summary>
|
||||
/// <param name="rune">The rune to encode.</param>
|
||||
/// <param name="dest">The destination buffer.</param>
|
||||
/// <param name="start">Starting offset to look into.</param>
|
||||
/// <param name="nbytes">Number of bytes valid in the buffer, or -1 to make it the length of the buffer.</param>
|
||||
/// <returns>he number of bytes written into the destination buffer.</returns>
|
||||
public static int EncodeRune (this Rune rune, byte [] dest, int start = 0, int nbytes = -1)
|
||||
{
|
||||
var bytes = Encoding.UTF8.GetBytes (rune.ToString ());
|
||||
int length = 0;
|
||||
for (int i = 0; i < (nbytes == -1 ? bytes.Length : nbytes); i++) {
|
||||
if (bytes [i] == 0) {
|
||||
break;
|
||||
}
|
||||
dest [start + i] = bytes [i];
|
||||
length++;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DecodeRune unpacks the first UTF-8 encoding in the string returns the rune and its width in bytes.
|
||||
/// </summary>
|
||||
/// <param name="rune">The rune to encode.</param>
|
||||
/// <param name="buffer">The byte array to look into.</param>
|
||||
/// <param name="start">Starting offset to look into.</param>
|
||||
/// <param name="nbytes">Number of bytes valid in the buffer, or -1 to make it the length of the buffer.</param>
|
||||
/// <returns></returns>
|
||||
public static (Rune Rune, int Size) DecodeRune (this Rune rune, byte [] buffer, int start = 0, int nbytes = -1)
|
||||
{
|
||||
var operationStatus = Rune.DecodeFromUtf8 (buffer, out Rune nrune, out int bytesConsumed);
|
||||
if (operationStatus == System.Buffers.OperationStatus.Done) {
|
||||
return (nrune, bytesConsumed);
|
||||
} else {
|
||||
return (Rune.ReplacementChar, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DecodeLastRune unpacks the last UTF-8 encoding in the byte array.
|
||||
/// </summary>
|
||||
/// <param name="buffer">Buffer to decode rune from.</param>
|
||||
/// <param name="end">Scan up to that point, if the value is -1, it sets the value to the length of the buffer.</param>
|
||||
/// <returns></returns>
|
||||
public static (Rune Rune, int Size) DecodeLastRune (byte [] buffer, int end = -1)
|
||||
{
|
||||
var operationStatus = Rune.DecodeLastFromUtf8 (buffer, out Rune rune, out int bytesConsumed);
|
||||
if (operationStatus == System.Buffers.OperationStatus.Done) {
|
||||
return (rune, bytesConsumed);
|
||||
} else {
|
||||
return (Rune.ReplacementChar, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reports whether this <see cref="Rune"/> is a valid surrogate pair and can be decoded from UTF-16.
|
||||
/// </summary>
|
||||
/// <param name="rune">The rune to decode.</param>
|
||||
/// <param name="chars">The chars if is valid. Null otherwise.</param>
|
||||
/// <returns><c>true</c>If is a valid surrogate pair, <c>false</c>otherwise.</returns>
|
||||
public static bool DecodeSurrogatePair (this Rune rune, out char [] chars)
|
||||
{
|
||||
if (rune.IsSurrogatePair ()) {
|
||||
chars = rune.ToString ().ToCharArray ();
|
||||
return true;
|
||||
}
|
||||
chars = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this <see cref="Rune"/> can be
|
||||
/// encoded as UTF-16 from a surrogate pair or zero otherwise.
|
||||
/// </summary>
|
||||
/// <param name="highsurrogate">The high surrogate code point.</param>
|
||||
/// <param name="lowSurrogate">The low surrogate code point.</param>
|
||||
/// <param name="result">The returning rune.</param>
|
||||
/// <returns><c>True</c>if the returning rune is greater than 0 <c>False</c>otherwise.</returns>
|
||||
public static bool EncodeSurrogatePair (char highsurrogate, char lowSurrogate, out Rune result)
|
||||
{
|
||||
result = default;
|
||||
if (char.IsSurrogatePair (highsurrogate, lowSurrogate)) {
|
||||
result = (Rune)char.ConvertToUtf32 (highsurrogate, lowSurrogate);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reports whether a rune is a surrogate code point.
|
||||
/// </summary>
|
||||
/// <param name="rune">The rune to probe.</param>
|
||||
/// <returns><c>true</c>If is a surrogate code point, <c>false</c>otherwise.</returns>
|
||||
public static bool IsSurrogatePair (this Rune rune)
|
||||
{
|
||||
return char.IsSurrogatePair (rune.ToString (), 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this <see cref="Rune"/> can be encoded as UTF-8.
|
||||
/// </summary>
|
||||
/// <param name="buffer">The byte array to probe.</param>
|
||||
/// <value><c>true</c> if is valid; otherwise, <c>false</c>.</value>
|
||||
public static bool IsValid (byte [] buffer)
|
||||
{
|
||||
var str = Encoding.Unicode.GetString (buffer);
|
||||
foreach (var rune in str.EnumerateRunes ()) {
|
||||
if (rune == Rune.ReplacementChar) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this <see cref="Rune"/> is valid.
|
||||
/// </summary>
|
||||
/// <param name="rune">The rune to probe.</param>
|
||||
/// <returns></returns>
|
||||
public static bool IsValid (this Rune rune)
|
||||
{
|
||||
return Rune.IsValid (rune.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -91,7 +91,7 @@ namespace Terminal.Gui {
|
||||
{ 0xff01, 0xff60 }, { 0xffe0, 0xffe6 },
|
||||
{ 0x16fe0, 0x16fe4 }, { 0x16ff0, 0x16ff1 }, { 0x17000, 0x187f7 },
|
||||
{ 0x18800, 0x18cd5 }, { 0x18d00, 0x18d08 }, { 0x1aff0, 0x1affc },
|
||||
{ 0x1b000, 0x1b122 }, { 0x1b150, 0x1b152 }, { 0x1b164, 0x1b167 }, { 0x1b170, 0x1b2fb }, {0x1d539, 0x1d539},
|
||||
{ 0x1b000, 0x1b122 }, { 0x1b150, 0x1b152 }, { 0x1b164, 0x1b167 }, { 0x1b170, 0x1b2fb }, {0x1d538, 0x1d550},
|
||||
{ 0x1f004, 0x1f004 }, { 0x1f0cf, 0x1f0cf }, /*{ 0x1f100, 0x1f10a },*/
|
||||
//{ 0x1f110, 0x1f12d }, { 0x1f130, 0x1f169 }, { 0x1f170, 0x1f1ac },
|
||||
{ 0x1f18f, 0x1f199 },
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Text;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Xunit;
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace Terminal.Gui.TextTests {
|
||||
Assert.Equal (0, e.ColumnWidth ());
|
||||
string join = "\u1104\u1161";
|
||||
Assert.Equal ("따", join);
|
||||
Assert.Equal (2, join.EnumerateRunes().Sum (x => x.ColumnWidth ()));
|
||||
Assert.Equal (2, join.EnumerateRunes ().Sum (x => x.ColumnWidth ()));
|
||||
Assert.Equal (OperationStatus.Done, Rune.DecodeFromUtf16 (join.ToCharArray (), out Rune result, out int charsConsumed));
|
||||
Assert.False (join.DecodeSurrogatePair (out char [] spair));
|
||||
Assert.Equal (2, join.RuneCount ());
|
||||
@@ -62,7 +62,7 @@ namespace Terminal.Gui.TextTests {
|
||||
Assert.Equal (3, e.Utf8SequenceLength);
|
||||
string joinNormalize = join.Normalize ();
|
||||
Assert.Equal ("따", joinNormalize);
|
||||
Assert.Equal (2, joinNormalize.EnumerateRunes().Sum (x => x.ColumnWidth ()));
|
||||
Assert.Equal (2, joinNormalize.EnumerateRunes ().Sum (x => x.ColumnWidth ()));
|
||||
Assert.Equal (OperationStatus.Done, Rune.DecodeFromUtf16 (joinNormalize.ToCharArray (), out result, out charsConsumed));
|
||||
Assert.False (joinNormalize.DecodeSurrogatePair (out spair));
|
||||
Assert.Equal (1, joinNormalize.RuneCount ());
|
||||
@@ -196,37 +196,37 @@ namespace Terminal.Gui.TextTests {
|
||||
Assert.Equal ('\u1100', (uint)rune.Value);
|
||||
string str = "\u2615";
|
||||
Assert.Equal ("☕", str);
|
||||
Assert.Equal (2, str.EnumerateRunes().Sum(x => x.ColumnWidth()));
|
||||
Assert.Equal (2, str.EnumerateRunes ().Sum (x => x.ColumnWidth ()));
|
||||
Assert.Equal (2, str.ConsoleWidth ());
|
||||
Assert.Equal (1, str.RuneCount ());
|
||||
Assert.Equal (1, str.Length);
|
||||
str = "\u2615\ufe0f"; // Identical but \ufe0f forces it to be rendered as a colorful image as compared to a monochrome text variant.
|
||||
Assert.Equal ("☕️", str);
|
||||
Assert.Equal (2, str.EnumerateRunes().Sum(x => x.ColumnWidth()));
|
||||
Assert.Equal (2, str.EnumerateRunes ().Sum (x => x.ColumnWidth ()));
|
||||
Assert.Equal (2, str.ConsoleWidth ());
|
||||
Assert.Equal (2, str.RuneCount ());
|
||||
Assert.Equal (2, str.Length);
|
||||
str = "\u231a";
|
||||
Assert.Equal ("⌚", str);
|
||||
Assert.Equal (2, str.EnumerateRunes().Sum(x => x.ColumnWidth()));
|
||||
Assert.Equal (2, str.EnumerateRunes ().Sum (x => x.ColumnWidth ()));
|
||||
Assert.Equal (2, str.ConsoleWidth ());
|
||||
Assert.Equal (1, str.RuneCount ());
|
||||
Assert.Equal (1, str.Length);
|
||||
str = "\u231b";
|
||||
Assert.Equal ("⌛", str);
|
||||
Assert.Equal (2, str.EnumerateRunes().Sum(x => x.ColumnWidth()));
|
||||
Assert.Equal (2, str.EnumerateRunes ().Sum (x => x.ColumnWidth ()));
|
||||
Assert.Equal (2, str.ConsoleWidth ());
|
||||
Assert.Equal (1, str.RuneCount ());
|
||||
Assert.Equal (1, str.Length);
|
||||
str = "\u231c";
|
||||
Assert.Equal ("⌜", str);
|
||||
Assert.Equal (1, str.EnumerateRunes().Sum(x => x.ColumnWidth()));
|
||||
Assert.Equal (1, str.EnumerateRunes ().Sum (x => x.ColumnWidth ()));
|
||||
Assert.Equal (1, str.ConsoleWidth ());
|
||||
Assert.Equal (1, str.RuneCount ());
|
||||
Assert.Equal (1, str.Length);
|
||||
str = "\u1dc0";
|
||||
Assert.Equal ("᷀", str);
|
||||
Assert.Equal (0, str.EnumerateRunes().Sum(x => x.ColumnWidth()));
|
||||
Assert.Equal (0, str.EnumerateRunes ().Sum (x => x.ColumnWidth ()));
|
||||
Assert.Equal (0, str.ConsoleWidth ());
|
||||
Assert.Equal (1, str.RuneCount ());
|
||||
Assert.Equal (1, str.Length);
|
||||
@@ -530,7 +530,7 @@ namespace Terminal.Gui.TextTests {
|
||||
Assert.Equal ("ô", f);
|
||||
Assert.Equal (f, s);
|
||||
Assert.Equal (1, f.ConsoleWidth ());
|
||||
Assert.Equal (1, s.EnumerateRunes().Sum (c => c.ColumnWidth ()));
|
||||
Assert.Equal (1, s.EnumerateRunes ().Sum (c => c.ColumnWidth ()));
|
||||
Assert.Equal (2, s.Length);
|
||||
(var rune, var size) = f.DecodeRune ();
|
||||
Assert.Equal (rune, l);
|
||||
@@ -548,7 +548,7 @@ namespace Terminal.Gui.TextTests {
|
||||
Assert.Equal ("A̅", f);
|
||||
Assert.Equal (f, s);
|
||||
Assert.Equal (1, f.ConsoleWidth ());
|
||||
Assert.Equal (1, s.EnumerateRunes().Sum(c => c.ColumnWidth()));
|
||||
Assert.Equal (1, s.EnumerateRunes ().Sum (c => c.ColumnWidth ()));
|
||||
Assert.Equal (2, s.Length);
|
||||
(rune, size) = f.DecodeRune ();
|
||||
Assert.Equal (rune, l);
|
||||
@@ -566,7 +566,7 @@ namespace Terminal.Gui.TextTests {
|
||||
Assert.Equal ("ä", f);
|
||||
Assert.Equal (f, s);
|
||||
Assert.Equal (1, f.ConsoleWidth ());
|
||||
Assert.Equal (1, s.EnumerateRunes().Sum(c => c.ColumnWidth()));
|
||||
Assert.Equal (1, s.EnumerateRunes ().Sum (c => c.ColumnWidth ()));
|
||||
Assert.Equal (2, s.Length);
|
||||
(rune, size) = f.DecodeRune ();
|
||||
Assert.Equal (rune, l);
|
||||
@@ -584,7 +584,7 @@ namespace Terminal.Gui.TextTests {
|
||||
Assert.Equal ("伀〪", f); // Occupies 4 columns.
|
||||
Assert.Equal (f, s);
|
||||
Assert.Equal (4, f.ConsoleWidth ());
|
||||
Assert.Equal (4, s.EnumerateRunes().Sum(c => c.ColumnWidth()));
|
||||
Assert.Equal (4, s.EnumerateRunes ().Sum (c => c.ColumnWidth ()));
|
||||
Assert.Equal (2, s.Length);
|
||||
(rune, size) = f.DecodeRune ();
|
||||
Assert.Equal (rune, l);
|
||||
@@ -627,10 +627,10 @@ namespace Terminal.Gui.TextTests {
|
||||
Assert.Equal (us, s);
|
||||
if (r.ColumnWidth () < 0) {
|
||||
Assert.NotEqual (r.ColumnWidth (), us.ConsoleWidth ());
|
||||
Assert.NotEqual (s.EnumerateRunes().Sum (c => c.ColumnWidth ()), us.ConsoleWidth ());
|
||||
Assert.NotEqual (s.EnumerateRunes ().Sum (c => c.ColumnWidth ()), us.ConsoleWidth ());
|
||||
} else {
|
||||
Assert.Equal (r.ColumnWidth (), us.ConsoleWidth ());
|
||||
Assert.Equal (s.EnumerateRunes().Sum (c => c.ColumnWidth ()), us.ConsoleWidth ());
|
||||
Assert.Equal (s.EnumerateRunes ().Sum (c => c.ColumnWidth ()), us.ConsoleWidth ());
|
||||
}
|
||||
Assert.Equal (us.RuneCount (), s.Length);
|
||||
} else {
|
||||
@@ -767,13 +767,31 @@ namespace Terminal.Gui.TextTests {
|
||||
List<Rune> runes = new List<Rune> ();
|
||||
int tSize = 0;
|
||||
for (int i = 0; i < us.RuneCount (); i++) {
|
||||
(Rune rune, int size) = us.Substring (i, 1).DecodeRune ();
|
||||
(Rune rune, int size) = us.DecodeRune (i);
|
||||
runes.Add (rune);
|
||||
tSize += size;
|
||||
}
|
||||
string result = StringExtensions.Make (runes);
|
||||
Assert.Equal ("Hello, 世界", result);
|
||||
Assert.Equal (13, tSize);
|
||||
Assert.Equal (11, result.ConsoleWidth ());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Test_DecodeRune_With_Surrogate_Pairs ()
|
||||
{
|
||||
string us = "Hello, 𝔹𝕆𝔹";
|
||||
List<Rune> runes = new List<Rune> ();
|
||||
int tSize = 0;
|
||||
for (int i = 0; i < us.RuneCount (); i++) {
|
||||
(Rune rune, int size) = us.DecodeRune (i);
|
||||
runes.Add (rune);
|
||||
tSize += size;
|
||||
}
|
||||
string result = StringExtensions.Make (runes);
|
||||
Assert.Equal ("Hello, 𝔹𝕆𝔹", result);
|
||||
Assert.Equal (19, tSize);
|
||||
Assert.Equal (13, result.ConsoleWidth ());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -783,13 +801,31 @@ namespace Terminal.Gui.TextTests {
|
||||
List<Rune> runes = new List<Rune> ();
|
||||
int tSize = 0;
|
||||
for (int i = us.RuneCount () - 1; i >= 0; i--) {
|
||||
(Rune rune, int size) = us.Substring (i, 1).DecodeLastRune ();
|
||||
(Rune rune, int size) = us.DecodeLastRune (i);
|
||||
runes.Add (rune);
|
||||
tSize += size;
|
||||
}
|
||||
string result = StringExtensions.Make (runes);
|
||||
Assert.Equal ("界世 ,olleH", result);
|
||||
Assert.Equal (13, tSize);
|
||||
Assert.Equal (11, result.ConsoleWidth ());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Test_DecodeLastRune_With_Surrogate_Pairs ()
|
||||
{
|
||||
string us = "Hello, 𝔹𝕆𝔹";
|
||||
List<Rune> runes = new List<Rune> ();
|
||||
int tSize = 0;
|
||||
for (int i = us.RuneCount () - 1; i >= 0; i--) {
|
||||
(Rune rune, int size) = us.DecodeLastRune (i);
|
||||
runes.Add (rune);
|
||||
tSize += size;
|
||||
}
|
||||
string result = StringExtensions.Make (runes);
|
||||
Assert.Equal ("𝔹𝕆𝔹 ,olleH", result);
|
||||
Assert.Equal (19, tSize);
|
||||
Assert.Equal (13, result.ConsoleWidth ());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -863,14 +899,14 @@ namespace Terminal.Gui.TextTests {
|
||||
Assert.Equal (200, us.Length);
|
||||
Assert.Equal (200, us.RuneCount ());
|
||||
Assert.Equal (200, us.ConsoleWidth ());
|
||||
int sumRuneWidth = us.EnumerateRunes().Sum (x => x.ColumnWidth ());
|
||||
int sumRuneWidth = us.EnumerateRunes ().Sum (x => x.ColumnWidth ());
|
||||
Assert.Equal (200, sumRuneWidth);
|
||||
|
||||
us = "01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\n";
|
||||
Assert.Equal (201, us.Length);
|
||||
Assert.Equal (201, us.RuneCount ());
|
||||
Assert.Equal (200, us.ConsoleWidth ());
|
||||
sumRuneWidth = us.EnumerateRunes().Sum(x => x.ColumnWidth());
|
||||
sumRuneWidth = us.EnumerateRunes ().Sum (x => x.ColumnWidth ());
|
||||
Assert.Equal (199, sumRuneWidth);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user