gyscos / cursive

A Text User Interface library for the Rust programming language
MIT License
4.24k stars 240 forks source link

Allow TextView formatting #162

Open hellow554 opened 6 years ago

hellow554 commented 6 years ago

I'd like to see some bold, italic, underline in my Textview, but currently it is not possible afaik. I guess all the underlying backends support this, so this can be implemented, right?

gyscos commented 6 years ago

Yes, styled views is something I'd like to include but is currently missing from Cursive. There are two parts to this:

There was some thoughts on the second point in https://github.com/gyscos/Cursive/pull/106, but I realize the first point may not even be ready yet, so I'll start looking into that.

gyscos commented 6 years ago

Just pushed 2d7f8295cf91724a4fd7aa22f1e97dccac6ea63c, which brings the Bold, Italic and Underline effects, so it's now at least possible to print such text.

The next step will be to update TextView to apply an Effect to its content (edit: aa9db30a51fb81802c833ae02b30213cdd6a5cdd); and the step after that (which will likely take a bit more work) will be to parse marked-up text, and apply various effects to only segments of the text.

hellow554 commented 6 years ago

Hurray! 😊 I really like the idea to use marked-up text, let's use markdown? ;) Here I see two possibilities

A. Use a simple regex to parse *italic*, **bold** or ***bolditalic*** text B. Use a library (e.g. pulldown ) which might be a bit overkill for just those three cases

gyscos commented 6 years ago

The first step is to define an intermediate representation (a list of "styled' spans of text), and adapt the current line-breaking algorithm to work on that. I'll probably look into xi-unicode's for that.

Then, we'll add various parsers from &str to this representation, and markdown sounds like a prime choice. Pulldown, looks interesting, with a reasonable API and few dependencies.

The parsing itself may be behind a feature or even in a separate crate, as it's quite independent from the rest of the code.

gyscos commented 6 years ago

I started playing with pulldown-cmark. Note that it only supports vanilla markdown (without inline HTML) and therefore does not support underlining text.

It also generates a lot of markup that we won't support (for now or ever), like tables, horizontal rules, etc... without giving access to the source string for those, so we'll need to manually replace them with strings (eg: every time the parser returns the beginning/end of a code block, insert ```).

One problem with this solution is that multiple source strings can result in the same Markdown tags (titles can have a # prefix or be followed by a ===== line), but we cannot know which was used, we only know that a title was found. So we have to guess, and always output this as # Title. This is weird because it modifies parts of the text that we can't really render. I don't know if this is acceptable.

Still, I'd very much prefer not having to write a simplified parser myself, as there are a few corner-cases (with word separation, etc...) that I'd rather avoid.