StringExtensions.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. namespace Terminal.Gui;
  6. /// <summary>
  7. /// Extensions to <see cref="string"/> to support TUI text manipulation.
  8. /// </summary>
  9. public static class StringExtensions {
  10. /// <summary>
  11. /// Repeats the string <paramref name="n"/> times.
  12. /// </summary>
  13. /// <remarks>
  14. /// This is a Terminal.Gui extension method to <see cref="string"/> to support TUI text manipulation.
  15. /// </remarks>
  16. /// <param name="str">The text to repeat.</param>
  17. /// <param name="n">Number of times to repeat the text.</param>
  18. /// <returns>
  19. /// The text repeated if <paramref name="n"/> is greater than zero,
  20. /// otherwise <see langword="null"/>.
  21. /// </returns>
  22. public static string Repeat (this string str, int n)
  23. {
  24. if (n <= 0) {
  25. return null;
  26. }
  27. if (string.IsNullOrEmpty (str) || n == 1) {
  28. return str;
  29. }
  30. return new StringBuilder (str.Length * n)
  31. .Insert (0, str, n)
  32. .ToString ();
  33. }
  34. /// <summary>
  35. /// Gets the number of columns the string occupies in the terminal.
  36. /// </summary>
  37. /// <remarks>
  38. /// This is a Terminal.Gui extension method to <see cref="string"/> to support TUI text manipulation.
  39. /// </remarks>
  40. /// <param name="str">The string to measure.</param>
  41. /// <returns></returns>
  42. public static int GetColumns (this string str)
  43. {
  44. return str == null ? 0 : str.EnumerateRunes ().Sum (r => Math.Max (r.GetColumns (), 0));
  45. }
  46. /// <summary>
  47. /// Gets the number of runes in the string.
  48. /// </summary>
  49. /// <remarks>
  50. /// This is a Terminal.Gui extension method to <see cref="string"/> to support TUI text manipulation.
  51. /// </remarks>
  52. /// <param name="str">The string to count.</param>
  53. /// <returns></returns>
  54. public static int GetRuneCount (this string str) => str.EnumerateRunes ().Count ();
  55. /// <summary>
  56. /// Converts the string into a <see cref="Rune"/> array.
  57. /// </summary>
  58. /// <remarks>
  59. /// This is a Terminal.Gui extension method to <see cref="string"/> to support TUI text manipulation.
  60. /// </remarks>
  61. /// <param name="str">The string to convert.</param>
  62. /// <returns></returns>
  63. public static Rune [] ToRunes (this string str) => str.EnumerateRunes ().ToArray ();
  64. /// <summary>
  65. /// Converts the string into a <see cref="List{Rune}"/>.
  66. /// </summary>
  67. /// <remarks>
  68. /// This is a Terminal.Gui extension method to <see cref="string"/> to support TUI text manipulation.
  69. /// </remarks>
  70. /// <param name="str">The string to convert.</param>
  71. /// <returns></returns>
  72. public static List<Rune> ToRuneList (this string str) => str.EnumerateRunes ().ToList ();
  73. /// <summary>
  74. /// Unpacks the first UTF-8 encoding in the string and returns the rune and its width in bytes.
  75. /// </summary>
  76. /// <remarks>
  77. /// This is a Terminal.Gui extension method to <see cref="string"/> to support TUI text manipulation.
  78. /// </remarks>
  79. /// <param name="str">The string to decode.</param>
  80. /// <param name="start">Starting offset.</param>
  81. /// <param name="count">Number of bytes in the buffer, or -1 to make it the length of the buffer.</param>
  82. /// <returns></returns>
  83. public static (Rune Rune, int Size) DecodeRune (this string str, int start = 0, int count = -1)
  84. {
  85. var rune = str.EnumerateRunes ().ToArray () [start];
  86. var bytes = Encoding.UTF8.GetBytes (rune.ToString ());
  87. if (count == -1) {
  88. count = bytes.Length;
  89. }
  90. var operationStatus = Rune.DecodeFromUtf8 (bytes, out rune, out int bytesConsumed);
  91. if (operationStatus == System.Buffers.OperationStatus.Done && bytesConsumed >= count) {
  92. return (rune, bytesConsumed);
  93. }
  94. return (Rune.ReplacementChar, 1);
  95. }
  96. /// <summary>
  97. /// Unpacks the last UTF-8 encoding in the string.
  98. /// </summary>
  99. /// <remarks>
  100. /// This is a Terminal.Gui extension method to <see cref="string"/> to support TUI text manipulation.
  101. /// </remarks>
  102. /// <param name="str">The string to decode.</param>
  103. /// <param name="end">Index in string to stop at; if -1, use the buffer length.</param>
  104. /// <returns></returns>
  105. public static (Rune rune, int size) DecodeLastRune (this string str, int end = -1)
  106. {
  107. var rune = str.EnumerateRunes ().ToArray () [end == -1 ? ^1 : end];
  108. var bytes = Encoding.UTF8.GetBytes (rune.ToString ());
  109. var operationStatus = Rune.DecodeFromUtf8 (bytes, out rune, out int bytesConsumed);
  110. if (operationStatus == System.Buffers.OperationStatus.Done) {
  111. return (rune, bytesConsumed);
  112. }
  113. return (Rune.ReplacementChar, 1);
  114. }
  115. /// <summary>
  116. /// Converts a <see cref="Rune"/> generic collection into a string.
  117. /// </summary>
  118. /// <param name="runes">The enumerable rune to convert.</param>
  119. /// <returns></returns>
  120. public static string ToString (IEnumerable<Rune> runes)
  121. {
  122. var str = string.Empty;
  123. foreach (var rune in runes) {
  124. str += rune.ToString ();
  125. }
  126. return str;
  127. }
  128. /// <summary>
  129. /// Converts a byte generic collection into a string in the provided encoding (default is UTF8)
  130. /// </summary>
  131. /// <param name="bytes">The enumerable byte to convert.</param>
  132. /// <param name="encoding">The encoding to be used.</param>
  133. /// <returns></returns>
  134. public static string ToString (IEnumerable<byte> bytes, Encoding encoding = null)
  135. {
  136. if (encoding == null) {
  137. encoding = Encoding.UTF8;
  138. }
  139. return encoding.GetString (bytes.ToArray ());
  140. }
  141. }