Example #1
0
        /// <summary>
        /// Forces the string to word wrap so that each line doesn't exceed the maxLineLength.
        /// </summary>
        /// <param name="str">The string to wrap.</param>
        /// <param name="options">The options used for wrapping a string.</param>
        /// <returns></returns>
        public static string Wrap(this string str, StringWrapOptions options)
        {
            var lines   = WrappedLines(str, options);
            var wrapped = string.Join(Environment.NewLine, lines);

            // Any of the line ending combos will be excluded if at the end of the line.
            if (str == null)
            {             /* Ignore */
            }
            else if (str.EndsWith("\r\n"))
            {
                wrapped += "\r\n";
            }
            else if (str.EndsWith("\n\r"))
            {
                wrapped += "\r\n";
            }
            else if (str.EndsWith("\r"))
            {
                wrapped += "\r";
            }
            else if (str.EndsWith("\n"))
            {
                wrapped += "\n";
            }

            return(wrapped);
        }
Example #2
0
        /// <summary>
        /// Forces the string to word wrap so that each line doesn't exceed the maxLineLength.
        /// </summary>
        /// <param name="str">The string to wrap.</param>
        /// <param name="options">The options used for wrapping a string.</param>
        /// <returns></returns>
        public static IEnumerable <string> WrappedLines(this string str, StringWrapOptions options)
        {
            if (string.IsNullOrEmpty(str))
            {
                return new string[] { }
            }
            ;
            if (options.MaxWidth <= 0)
            {
                return new string[] { str }
            }
            ;

            var prefix      = options.Prefix ?? "";        // Make sure we have something so we don't have to keep checking for null.
            var prefixWidth = MeasureWidth(prefix, options.TabWidth);

            if (prefixWidth >= options.MaxWidth)
            {
                throw new ArgumentException("The width of the prefix must be less than the max width of the line.", "options");
            }

            var lines = new List <string>();

            foreach (string line in str.Lines())
            {
                var lineWidth = 0;

                if (line.Trim() == "")
                {
                    // Empty line. Just use an empty string in case there is white space
                    // wider than the line. We don't want to wrap white spaces if that
                    // is all that there is on the line since the user won't see it.
                    lines.Add("");
                    continue;
                }

                // We want to keep any white space at the front of the line, but the
                // white space at the end could cause an extra line that appears empty.
                //var chars = line.TrimEnd();
                var chars = line;

                var sb = new StringBuilder();
                // Iterate through each character on the line so that we
                // can adjust for TABs and other odd characters.
                for (var i = 0; i < chars.Length; i++)
                {
                    var ch        = chars[i];
                    var charWidth = 1;

                    if (ch == '\t')
                    {
                        // Tabs have variable width based on the max width they allow.
                        // This allows text to have something that looks like columns
                        // It's not recommended to have embedded TABs in text for wrapped
                        // lines, but we need to support it.

                        charWidth = CalcTabWidth(lineWidth, options.TabWidth);
                    }
                    else if (char.IsControl(ch))
                    {
                        // TAB is considered a control character, but it can be printed, so put this check in the else.

                        // Ignore control characters. They aren't printed, and don't add to the length of the string.
                        continue;
                    }

                    // Check to see if adding this char will push the width of the line past the max.
                    if (lineWidth + charWidth <= options.MaxWidth)
                    {
                        sb.Append(ch);
                        lineWidth += charWidth;
                    }
                    else if (char.IsWhiteSpace(ch))
                    {
                        // If this is a white space, then we know we are at the end of a word.
                        lines.Add(sb.ToString());
                        sb.Clear();
                        sb.Append(prefix);

                        // Ignore white space at beginning of new wrapped line.
                        // It would make the left column of text appear jagged.
                        lineWidth = prefixWidth;
                    }
                    else
                    {
                        // Need to find the beginning of the current word and remove it from
                        // the line that we are building. We'll add it to the new line instead.
                        // The prefix is not included when finding a whitespace character.
                        var idx = -1;
                        for (var j = sb.Length - 1; j >= prefix.Length; j--)
                        {
                            if (char.IsWhiteSpace(sb[j]))
                            {
                                idx = j;
                                break;
                            }
                        }

                        // There weren't any white space characters or only the first char is a white space.
                        // Unable to break at word boundary, so break the word at the character.
                        if (idx <= 0)
                        {
                            lines.Add(sb.TrimEnd());                             // Don't want any TABs at the end of the line causing problems.
                            sb.Clear();
                            lineWidth = prefixWidth + charWidth;
                            sb.Append(prefix + ch);
                        }
                        else
                        {
                            lines.Add(sb.Substring(0, idx));
                            var end = sb.Substring(idx + 1);
                            sb.Clear();
                            sb.Append(prefix + end);                             // We know there are no TABs (white space) or control chars, so we can assume all chars have length of 1.
                            lineWidth = prefixWidth + end.Length + charWidth;
                            sb.Append(ch);
                        }
                    }
                }

                // Add the end of the line.
                if (sb.Trim() != "")
                {
                    lines.Add(sb.ToString());
                }
            }

            return(lines);
        }