Inanity 1: Elpher and text/gemini --------------------------------- The next few posts are kind of a mishmash of project update announcements mixed with stream-of-consciousness waffle. Apologies in advance for the incoming inanity! * * * As I threatened in the last post, I've spent some time improving Elpher's handling of the text/gemini document type. This was helpfully pushed along by several people who pushed their own patches along these lines to the repository. Thank you! Even though I didn't wind up merging all of the patches, they were certainly all helpful in pushing this update forward. As of version 2.7, elpher properly handles text/gemini in accordance with the spec. Prior to this update, the situation was pretty dire. The text/gemini (t/g from now on) format is wonderfully minimal, but it is definitely not the case that one can just treat it as plain text and expect documents to be pleasant to read. Before you read any further, I want to make clear that I'm absolutely a fan of the current t/g spec and think it's made the right decisions. I'm just trying to lay out some of the interesting (transient) side effects of these decisions. The reason that one can't treat t/g as plain text is that, unless a line is in a pre-formatted section of the document, the client is expected to automatically wrap this line in the instance that it is "too long" as defined by the client. Furthermore, each source line must be treated independently from every other line (with the single exception of the pre-fromatted mode toggle). This means that it's against the rules to reflow a paragraph of source text containing newlines, and has the consequence hard-wrapped source text winds up looking horrible - unless you're lucky enough to have a device that can display a whole line of the length chosen by the author. By way of illustration, consider the following hard-wrapped t/g source: -- snip -- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Pharetra magna ac placerat vestibulum lectus mauris. Suspendisse interdum consectetur libero id faucibus nisl tincidunt. Semper auctor neque vitae tempus quam pellentesque. Sagittis eu volutpat odio facilisis mauris. Sem integer vitae justo eget magna fermentum iaculis. -- snip -- Now look at what happens when it's displayed using the t/g rendering rules on a client having only 50 columns to play with: -- snip -- --------------------------------------------------| Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Pharetra magna ac placerat vestibulum lectus mauris. Suspendisse interdum consectetur libero id faucibus nisl tincidunt. Semper auctor neque vitae tempus quam pellentesque. Sagittis eu volutpat odio facilisis mauris. Sem integer vitae justo eget magna fermentum iaculis. -- snip -- Pretty ugly! This is why the t/g spec advises against hard wrapping. Instead, the ideal approach is to place the whole paragraph on a single line of the source, which allows clients to wrap it properly. Of course, this then means that, without special handling, source t/g documents which are paying attention to the spec are increasingly tend to look like this: -- snip -- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Pharetra magna ac placerat vestibulum lectus mauris. Suspendisse interdum consectetur libero id faucibus nisl tincidunt. Semper auctor neque vitae tempus quam pellentesque. Sagittis eu volutpat odio facilisis mauris. Sem integer vitae justo eget magna fermentum iaculis. -- snip -- How does this relate to elpher? Well, until v2.7, elpher used the same set of functions for rendering both gopher directory files and t/g documents. Of course the parsing code differed, but the rendering code was the same. This seemed nice and elegant when I originally wrote it; I even gushed about it [1] on my phlog. But this meant that text lines in t/g were rendered in the same way as info lines in gopher directories, and these - at least the way the street uses these things - don't come with any expectation of wrapping. Of course, emacs wraps all lines by default, but unless specifically told to it does this without any reference to word boundaries. Furthermore it does this at the edge of the window. And I am a very firm believer in the principle that text lines should be no more than ~70 characters wide. Thus modern t/g documents started to look like shit in elpher. So, I bit the bullet and implemented an entirely new rendering function for t/g. This was easy, and cleaned up a few other things along the way. (This always seems to be the way when implementing gemini-related stuff!) This function uses emacs auto-fill mode to wrap text lines appropriately. This is the mechanism that magically wraps long lines when an emacs user presses enter when editing a text document. It also automatically indents the next line when the previous line starts with what looks to be a bullet (e.g. a *). This had the nice side effect that bulleted t/g lists were formatted nicely essentially for free. (In the end I had to replace this "for free" mechanism with one more tailored, because the "for free" algorithm actually looks several lines back and assumes that, if the last two lines begin with "*", you're actually editing a block comment and will thus automatically prefix the wrapped portion of the line with a new "*" - which obviously nobody wants!) One final gripe: I've had to set the default maximum wrapping width to 80. (The actual width depends on the window size.) While I would definitely have preferred to set it to 70, unfortunately (but understandably) there are still some t/g documents around that are hard-wrapped. Using 80 means that those continue to display okay provided the window is sufficiently wide. Hopefully the prevalence of hard-wrapped t/g documents will diminish over time, allowing us to set wrapping widths without having to deal with this trade-off. Besides the wrapping stuff, treating t/g documents as distinct from gopher directories meant I could easily get rid of the 6 column left margin that elpher uses to report selector types in gopher dirs. Also, we now have distinct (configurable) faces for the different header types. Phew. If you managed to stick with me through all of that, I'm both baffled and humbled! Thank you, dear reader. If you're into Emacs and Gemini, please give the new Elpher a whirl [2] and let me know what you think! --- [1]: gopher://thelambdalab.xyz:70/0/phlog/2019-09-11-Elpher-now-supports-Gemini.txt [2]: gopher://thelambdalab.xyz:70/1/projects/elpher/