LineWrapRange

An InputRange that wraps a piece of text into seperate lines, based on the given options.

Constructors

this
this(StringT input, LineWrapOptions options)
Undocumented in source.

Members

Functions

empty
bool empty()
Undocumented in source. Be warned that the author may not have intended to support it.
front
StringT front()
Undocumented in source. Be warned that the author may not have intended to support it.
popFront
void popFront()
Undocumented in source. Be warned that the author may not have intended to support it.

Throws

Exception if the char limit is too small to show any text.

Notes: Other than the constructor, this range is entirely @nogc nothrow.

Currently, this performs character-wrapping instead of word-wrapping, so words can be split between multiple lines. There is no technical reason for this outside of I'm lazy. The option between character and word wrapping will become a toggle inside of LineWrapOptions, so don't fear about this range magically breaking in the future.

For every line created from the given text, the starting and ending spaces (not all whitespace, just spaces) are stripped off. This is so the user doesn't have to worry about random leading/trailling spaces, making it easier to format for the general case (though specific cases might find this undesirable, I'm sorry). This does not apply to prefixes and suffixes.

I may expand LineWrapOptions so that the user can specify an array of characters to be stripped off, instead of it being hard coded to spaces.

Output: For every line that needs to be wrapped by this range, it will return values in the following pattern.

Prefix (LineWrapOptions.prefix) -> Text (from input) -> Suffix (LineWrapOptions.suffix) -> New line character (if this isn't the last line).

Prefixes and suffixes are only outputted if they are not null.

Please refer to the example unittest for this struct, as it will show you this pattern more clearly.

Peformance: This range performs no allocations other than if the ctor throws an exception.

For character-based wrapping, the part of the code that handles getting the next range of characters from the user-provided input, totals to O(l+s), where "l" is the amount of lines that this range will produce (input.length / lineWrapOptions.charsPerLine(1)), and "s" is the amount of leading spaces that the range needs to skip over. In general, "l" will be the main speed factor.

For character-based wrapping, once leading spaces have been skipped over, it is able to calculate the start and end for the range of user-provided characters to return. In other words, it doesn't need to iterate over every single character (unless every single character is a space >:D), making it very fast.

Examples

import std.algorithm : equal;
import std.format    : format;

auto options = LineWrapOptions(8, "\t", "-");
assert(options.charsPerLine(1) == 5);

// This is the only line that's *not* @nogc nothrow, as it can throw an exception.
auto range = "Hello world".asLineWrapped(options);

assert(range.equal([
    "\t", "Hello", "-", "\n",
    "\t", "world", "-"        // Leading spaces were trimmed. No ending newline.
]), "%s".format(range));

// If the suffix/prefix are null, then they don't get outputted
options.linePrefix = null;
options.lineCharLimit--;
range = "Hello world".asLineWrapped(options);

assert(range.equal([
    "Hello", "-", "\n",
    "world", "-"
]));

Meta