Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
StringUtil.cs274 linesDownload Raw Back to utils
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections.Generic;5using System.Globalization;6using System.Management.Automation.Host;7using System.Text;8using System.Text.RegularExpressions;9using System.Threading;10 11using Dbg = System.Management.Automation.Diagnostics;12 13namespace System.Management.Automation.Internal14{15    internal static class StringUtil16    {17        internal static string Format(string format, object arg0)18            => string.Format(CultureInfo.CurrentCulture, format, arg0);19 20        internal static string Format(string format, object arg0, object arg1)21            => string.Format(CultureInfo.CurrentCulture, format, arg0, arg1);22 23        internal static string Format(string format, object arg0, object arg1, object arg2)24            => string.Format(CultureInfo.CurrentCulture, format, arg0, arg1, arg2);25 26        internal static string Format(string format, params object[] args)27            => string.Format(CultureInfo.CurrentCulture, format, args);28 29        internal static string TruncateToBufferCellWidth(PSHostRawUserInterface rawUI, string toTruncate, int maxWidthInBufferCells)30        {31            Dbg.Assert(rawUI != null, "need a reference");32            Dbg.Assert(maxWidthInBufferCells >= 0, "maxWidthInBufferCells must be positive");33 34            string result;35            int i = Math.Min(toTruncate.Length, maxWidthInBufferCells);36 37            while (true)38            {39                result = toTruncate.Substring(0, i);40                int cellCount = rawUI.LengthInBufferCells(result);41                if (cellCount <= maxWidthInBufferCells)42                {43                    // the segment from start..i fits44 45                    break;46                }47                else48                {49                    // The segment does not fit, back off a tad until it does50                    // We need to back off 1 by 1 because there could theoretically51                    // be characters taking more 2 buffer cells52                    --i;53                }54            }55 56            return result;57        }58 59        // Typical padding is at most a screen's width, any more than that and we won't bother caching.60        private const int IndentCacheMax = 120;61 62        private static readonly string[] s_indentCache = new string[IndentCacheMax];63 64        internal static string Padding(int countOfSpaces)65        {66            if (countOfSpaces >= IndentCacheMax)67                return new string(' ', countOfSpaces);68 69            var result = s_indentCache[countOfSpaces];70 71            if (result == null)72            {73                Interlocked.CompareExchange(ref s_indentCache[countOfSpaces], new string(' ', countOfSpaces), null);74                result = s_indentCache[countOfSpaces];75            }76 77            return result;78        }79 80        private const int DashCacheMax = 120;81 82        private static readonly string[] s_dashCache = new string[DashCacheMax];83 84        internal static string DashPadding(int count)85        {86            if (count >= DashCacheMax)87                return new string('-', count);88 89            var result = s_dashCache[count];90 91            if (result == null)92            {93                Interlocked.CompareExchange(ref s_dashCache[count], new string('-', count), null);94                result = s_dashCache[count];95            }96 97            return result;98        }99 100        /// <summary>101        /// Substring implementation that takes into account the VT escape sequences.102        /// </summary>103        /// <param name="str">String that may contain VT escape sequences.</param>104        /// <param name="startOffset">105        /// When the string doesn't contain VT sequences, it's the starting index.106        /// When the string contains VT sequences, it means starting from the 'n-th' char that doesn't belong to a escape sequence.107        /// </param>108        /// <returns>The requested substring.</returns>109        internal static string VtSubstring(this string str, int startOffset)110        {111            return VtSubstring(str, startOffset, int.MaxValue, prependStr: null, appendStr: null);112        }113 114        /// <summary>115        /// Substring implementation that takes into account the VT escape sequences.116        /// </summary>117        /// <param name="str">String that may contain VT escape sequences.</param>118        /// <param name="startOffset">119        /// When the string doesn't contain VT sequences, it's the starting index.120        /// When the string contains VT sequences, it means starting from the 'n-th' char that doesn't belong to a escape sequence.</param>121        /// <param name="length">Number of non-escape-sequence characters to be included in the substring.</param>122        /// <returns>The requested substring.</returns>123        internal static string VtSubstring(this string str, int startOffset, int length)124        {125            return VtSubstring(str, startOffset, length, prependStr: null, appendStr: null);126        }127 128        /// <summary>129        /// Substring implementation that takes into account the VT escape sequences.130        /// </summary>131        /// <param name="str">String that may contain VT escape sequences.</param>132        /// <param name="startOffset">133        /// When the string doesn't contain VT sequences, it's the starting index.134        /// When the string contains VT sequences, it means starting from the 'n-th' char that doesn't belong to a escape sequence.</param>135        /// <param name="prependStr">The string to be prepended to the substring.</param>136        /// <param name="appendStr">The string to be appended to the substring.</param>137        /// <returns>The requested substring.</returns>138        internal static string VtSubstring(this string str, int startOffset, string prependStr, string appendStr)139        {140            return VtSubstring(str, startOffset, int.MaxValue, prependStr, appendStr);141        }142 143        /// <summary>144        /// Substring implementation that takes into account the VT escape sequences.145        /// </summary>146        /// <param name="str">String that may contain VT escape sequences.</param>147        /// <param name="startOffset">148        /// When the string doesn't contain VT sequences, it's the starting index.149        /// When the string contains VT sequences, it means starting from the 'n-th' char that doesn't belong to a escape sequence.</param>150        /// <param name="length">Number of non-escape-sequence characters to be included in the substring.</param>151        /// <param name="prependStr">The string to be prepended to the substring.</param>152        /// <param name="appendStr">The string to be appended to the substring.</param>153        /// <returns>The requested substring.</returns>154        internal static string VtSubstring(this string str, int startOffset, int length, string prependStr, string appendStr)155        {156            var valueStrDec = new ValueStringDecorated(str);157            if (valueStrDec.IsDecorated)158            {159                // Handle strings with VT sequences.160                bool copyStarted = startOffset == 0;161                bool hasEscSeqs = false;162                bool firstNonEscChar = true;163                StringBuilder sb = new(capacity: str.Length);164                Dictionary<int, int> vtRanges = valueStrDec.EscapeSequenceRanges;165 166                for (int i = 0, offset = 0; i < str.Length; i++)167                {168                    // Keep all leading ANSI escape sequences.169                    if (vtRanges.TryGetValue(i, out int len))170                    {171                        hasEscSeqs = true;172                        sb.Append(str.AsSpan(i, len));173 174                        i += len - 1;175                        continue;176                    }177 178                    // OK, now we get a non-escape-sequence character.179                    if (copyStarted)180                    {181                        if (firstNonEscChar)182                        {183                            // Prepend the string before we copy the first non-escape-sequence character.184                            sb.Append(prependStr);185                            firstNonEscChar = false;186                        }187 188                        // Copy this character if we've started the copy.189                        sb.Append(str[i]);190 191                        // Increment 'offset' to keep track of number of non-escape-sequence characters we've copied.192                        offset++;193                    }194                    else if (++offset == startOffset)195                    {196                        // We've skipped enough non-escape-sequence characters, and will be copying the next one.197                        copyStarted = true;198 199                        // Reset 'offset' and from now on use it to track the number of copied non-escape-sequence characters.200                        offset = 0;201                        continue;202                    }203 204                    // If the number of copied non-escape-sequence characters has reached the specified length, done copying.205                    if (copyStarted && offset == length)206                    {207                        break;208                    }209                }210 211                if (hasEscSeqs)212                {213                    string resetStr = PSStyle.Instance.Reset;214                    bool endsWithReset = sb.EndsWith(resetStr);215                    if (endsWithReset)216                    {217                        // Append the given string before the reset VT sequence.218                        sb.Insert(sb.Length - resetStr.Length, appendStr);219                    }220                    else221                    {222                        // Append the given string and add the reset VT sequence.223                        sb.Append(appendStr).Append(resetStr);224                    }225                }226                else227                {228                    sb.Append(appendStr);229                }230 231                return sb.ToString();232            }233 234            // Handle strings without VT sequences.235            if (length == int.MaxValue)236            {237                length = str.Length - startOffset;238            }239 240            if (prependStr is null && appendStr is null)241            {242                return str.Substring(startOffset, length);243            }244            else245            {246                int capacity = length + prependStr?.Length ?? 0 + appendStr?.Length ?? 0;247                return new StringBuilder(prependStr, capacity)248                    .Append(str, startOffset, length)249                    .Append(appendStr)250                    .ToString();251            }252        }253 254        internal static bool EndsWith(this StringBuilder sb, string value)255        {256            if (sb.Length < value.Length)257            {258                return false;259            }260 261            int offset = sb.Length - value.Length;262            for (int i = 0; i < value.Length; i++)263            {264                if (sb[offset + i] != value[i])265                {266                    return false;267                }268            }269 270            return true;271        }272    }273}274