Closed byorgey closed 3 years ago
On its face this doesn't seem like a crazy thing to add to the library, but I do worry about feature creep only because I know how far this rabbit hole goes. (Have you looked at par
? 😊)
This request makes me think about other things people could reasonably want, like "just indent the first line" or "indent all lines at the same level as any existing first-line indentation." I don't know of an API that would make those possible as well, and maybe we don't need to worry about those cases, but I am just trying to think ahead about how adding this feature might suggest that those others are missing.
I'm open to a PR if you would like to hack on this. It does occur to me that if WrapSettings
is going to get a new field along these lines, it might be useful to generalize this "indentation strategy" notion a bit beyond just an Int
or Maybe Int
for this specific case, and instead add a field whose value is of a new type that has a few constructors (or maybe one, for now) to capture these different indentation behaviors.
What do you think?
(Also, another thought I just had: in Emacs-land this is called "filling", as I recall, which goes a bit beyond just wrapping long lines. So maybe it would be conventional to use the term "fill" somewhere in the name of a new settings field.)
Hah, indeed, I know exactly what you mean about feature creep. I hope we can find a solution that is reasonably general but doesn't just open a floodgate of crazy features.
I hadn't made the connection to filling in emacs but that's a very fruitful connection. We definitely shouldn't add an "auto fill" mode like emacs has, I don't even want to think about how much convoluted code that must be. But I think your idea of adding a "fill strategy" field sounds good. How about this for a first cut?
data FillStrategy
= NoFill -- ^ Don't do any filling (default)
| FillIndent Int -- ^ Indent every line after the first by this many spaces
| FillPrefix T.Text -- ^ Prepend this text to every line after the first
I could also imagine a flag specifying whether the fill strategy should also be applied to the first line or not? But maybe it's simpler to just say that if you want that, you can just add the fill to the beginning manually before passing it to the text wrapping function.
It seems to me that this feature could have settings on two axes: which line(s) to affect, and how to affect them. I could read FillIndent
to mean other things than "all lines after the first", and that same "all lines after the first" is implied in the FillPrefix
constructor. But a user could reasonably want to affect all lines instead. That leads me to think that we could have two types: your type (which would configure the second axis I mentioned) and another type,
data FillScope = FillNone | FillFirst | FillAfterFirst
Then the combination of those two values (both new fields in WrapSettings
) would govern which lines are impacted, and how.
(I now see above that you had the same thought.)
I have made some good progress but I am now a little uncertain how filling should interact with the preserveIndentation
feature. Currently I'm thinking that any indentation generated by preserveIndentation
should come at the beginning of each line, followed by any additional indentation or prefix generated by the FillStrategy
.
I would really like a wrapping mode where every line after the first line is indented, e.g. something like
Would you be open to a PR implementing this functionality? What do you think would be the best way to go about it? Perhaps adding a field to the
WrapSettings
of typeMaybe Int
(or justInt
)? I'm happy to take a crack at implementing it but wanted to make sure we agree on the best approach first.