Possibly a new way of drawing boxes in the terminal
willmcgugan.com
willmcgugan.com
U+2581 LOWER ONE EIGHTH BLOCK
U+2594 UPPER ONE EIGHTH BLOCK
U+258E LEFT ONE QUARTER BLOCK
U+1FB87 RIGHT ONE QUARTER BLOCK
(Sorry, no actual glyphs, HN is gobbling them.)Notice anything different about the last one? It was added in Unicode 13 in a new block. This means very much reduced font support, and if absent, it generally means the use of a fallback font, which is very likely to mean a wider glyph, which means that the right edge of your box is displaced and probably the wrong thickness, and in some environments (though no proper terminals) anything following it will be offset too.
I use Triplicate as my monospace, and yeah, it lacks U+1FB87 RIGHT ONE QUARTER BLOCK, so this technique looks awful.
It gets a little worse when you consider line-heights. Some fonts design these things to fit line-height 1, others their default line-height, I think. The concepts are a bit fuzzy and implementations inconsistent and I don’t actually know the full details of what I’m talking about. Still worse, in browsers I don’t think the font’s proper preferred line-height (if that’s a thing?) is actually exposed, so you can’t actually get the correct result (the closest you’ll get is hard-coding the font metrics and hoping that font gets used, but that’s never guaranteed). But the end result is that you might get your box not neatly lining up in a terminal and probably won’t get it lining up in a browser, either squished more than it should be or with gaps, and in either case it’s going to be visually unbalanced in quite a disconcerting way, whereas the regular box-drawing characters are more likely to line up due to more care and even if they don’t the gaps (or maybe-visible-with-the-wrong-sort-of-antialiasing overlaps) will be balanced.
Sample (remote since HN is gobbling all these Block Elements characters): https://temp.chrismorgan.info/2022-10-16-hn-comment-33217918..., also try copying it to your terminal to see if it differs from the web layout technique.
Conclusion: stop trying to be fancy, block element support isn’t good enough and the technique’s failure modes are quite bad; just stick with box drawing characters and no clever backgrounds, because that will work much more consistently, and wastes less space too.
You can just use U+258A LEFT THREE QUARTERS BLOCK and inverse colour settings. I use U+258B (LEFT FIVE EIGHTS BLOCK) in my editor that way (inverse of what you'd "expect", to get 3/8th's instead of 5/8ths)
Certainly do this rather than using U+1FB87. SGR 7 to reverse colours and SGR 27 to cancel reverse, hopefully it’s pretty universally supported by now. I definitely expect it to be better supported than U+1FB87 in the chosen font.
EDIT: of course you meant why some are there and some not, yeah, no idea...
Mind that there are also
U+258F LEFT ONE EIGHTH BLOCK
U+2595 RIGHT ONE EIGHTH BLOCK
So it can be all done in the U+2580 – U+259F "Block Elements" range.Conclusion: Demand more from your terminal emulator, including direct support for more of the Unicode drawing characters.
Turn in your hacker card.
/* segment:offset -> linear = (segment << 4) + offset */
volatile void *text_base = (volatile void *)(0xb8000) /* B800:0000 to BFFF:000F is 32 KiB */
/* In VGA, bg bit 3 is a blink bit by default depending on Attribute Mode Control Register bit 3 */
/* In VGA, fg bit 3 is a secondary character code plane if font A and font B pointers are different */
void put_char(int ch, int fg, int bg, int x /* 0..79 */, int y /* 0..24 */, int video_page /* 0..7 */ ) {
size_t offset = video_page*4096 + (y*80 + x)*2;
uint8_t* p = (uint8_t*)(text_base) + offset;
/* Modern compilers should turn this into a 16-bit memory access without worrying about endianness. */
*p++ = (uint8_t)(ch & 0xff);
*p = (uint8_t)((bg & 0xf)*16 + (fg & 0xf)));
}I've actually reused this code a few months ago for a prank (UEFI network booted Linux containing DosBox running fullscreen in the framebuffer, to display a fake OS installer).
We create some fairly complex and feature rich forms for managing transfers in this appliance, but ncurses isn’t always the friendliest beast - we’ve managed to make it simpler to use with a lot (a lot!) of component-like functions to get to the level of abstraction we need, but one wonders about the grass over yonder fence.
At a former "disaster recovery" startup I had written a little ncurses tool for handling data transfers from pools of external USB drives customers would ship us to seed their off-site backups. This was something like 8 years ago now, and it was already a situation where literally nobody else in the company, new or existing hires, wanted anything to do with maintaining what was really a small ~1000-line C+ncurses application. I was on the systems/platform/backend/OS team and it was just a weekend hack to get us going with something ops could interface with via putty.
I can't imagine how much more difficult it is to find anyone with ncurses familiarity today, and few people seem interested in wasting time learning such antiquated tech. In hindsight I feel like I never should have written that tool in the first place, instead letting one of the front-end devs just make a REST API and web doodad for the whole thing. At least then it would have been familiar territory for practically every engineer they hired.
As I noted in another comment, using a TUI starts us off with a smaller attack surface and fewer dependencies, which makes it easier to scrub things down even further with relative ease (relative). It may make tooling and programming tougher, but it simplifies the overall job of achieving a target level of security.
> Unicode contains one eighth vertical and horizontal blocks which are fantastic for displaying terminal progress bars with apparently higher "resolution" that a single character.
https://fliptomato.wordpress.com/2007/03/19/medical-research...
I would find it remarkable if all these accomplished scientific experimenters and scholars first encountered it here
Not impossible but I think Occam's razor would suggest there might be domain specific nuances to the implementation that makes it special.
On the other hand I've certainly encountered a ton of stupidly obvious techniques in my 30 years of programming which I thought were unremarkable only to discover people have developed a special language and narrative history of attribution to it.
You swim through the jargon presuming it's profound and enlightening but then ultimately get disappointed. It's an emotionally impactful experience so I tend to remember it.
There's some interesting discussion on stackexchange at [1], the comment I link to reports on some investigation they did. Apparently, the Tai of Tai's Model misinterpreted other people's use of the trapezoid rule, found that misinterpreted version to be faulty, re-invented it, and named it after herself. One assumes that it was an honest mistake, but it's a damned shame that it didn't get caught in review.
E.g. here's "PETSCII" [1], the Commodore character set, and as you can see there's a number of characters that provides different thickness "borders" on the left/right/top/bottom.
Here's a page with a number of "PETSCII" images using the same method to have borders in images with the other colour firmly on one side of the line [2]
As for modern usage, here's a tiny image from my personal terminal text editor, which uses the same method with unicode to get a shaded transition between the line numbers and the main display area [3].
[1] https://www.petscii.de/images/PETSCII_MODE_02.png
[2] https://oldmachinery.blogspot.com/2020/09/petscii-petscii-pe...
____________
| |
| Like this. |
|____________|A related trick was to adjust the colors so that, for example, the background for one character looks like foreground of an adjacent character. I used this to draw thick boxes in one program without wasting a couple extra rows of display. (Though the trick was revealed if you did a B&W screenshot printout. There was no text selection©&paste in MS-DOS at the time.)
Of course for my dovetailing project, I had to make a little frame with spiral dovetails, to show that it could be done.
So a dovetail joint has two pieces that slide together at the corner. Because of how the wood is cut, one side of the corner has a fancy zig-zag showing on the outside (tails) and the other just has boring parallel lines (pins). [0] You have to slide the piece with pins into the piece with tails.
So typically if you're making a dovetail box, each side of the box would either have pins on both ends or tails on both ends. This is so that the last piece has both joints pointed the same direction so both ends can slide in to the rest of the box.
You end up with two sides of the box showing the zig-zag tails and two sides showing the boring pins. [1]
But I figured out how to assemble the box so that each side showed tails at one end and pins at the other.
[0] https://technologystudent.com/joints/dovejts.htm
[1] https://blendswap.com/static/blendImages/2021/7/31/Blend/286...
Edit: another way to describe it is that I made a square frame that had rotational symmetry instead of horizontal and vertical symmetry.
It is easier to code a relatively more secure constrained TUI login shell with ncurses than with a full GUI library.
I prefer polished UIs because they help sharpen my focus away from their flaws and into my work.
I prefer command line tools with polished UIs. I enjoy color highlighting. I run my editor in 256color mode.
I wish a restricted set of CSS was available through libncurses via ESC[ commands, with optional downgrade via term cap to Unicode characters like these one-eighth ones, so that we didn’t all have to suffer quite so much “UI is optional” default neglect from command line tool designs. (One that includes features for terminals newer than decades ago! Like tables, and borders :)
> it feels like a strange problem to solve.
Seen this way, why bother creating nicely-looking GUIs? It would be the same strange problem to solve.
Kids these days… Give them a chance and they will escape font-weight:200 saddlebrown-on-lavenderblush for tui “to look classy”.
Now, I'm not saying that my eyes hurt when I see boxes with color bleeding in a terminal. I've seen so many in years of TUI under DOS that I find them to be absolutely normal. But when I see a nicely done TUI, possibly in an unexpected or creative way, I find it more pleasing to use. It is the same as for a GUI: why not keep Windows 3.1 window decorations, if those details are not so important? The fact that it is in a terminal or not does not make any difference.
Aesthetics are medium-agnostic, they are valid both for TUIs and GUIs.
In theory, one could use a special protocol to support some gui library in it “natively” rather than at html-like level. If interested, take a look at gtk-server for example (not as a library example, it doesn’t fit here, but as an idea/inspiration).
More so than the editor, which I'm kinda treating as my config more than a finished app, I'm gradually splitting functionality into a bunch of gems so that the editor itself will feel even more like just configuration...
Here's another screenshot [2] showing part of the integration with Rouge for syntax-highlighting, and showing how it's rendering comments by recursing into Rouge's Markdown mode, which again recurses into Rouge's Ruby mode. The "LayeredLexer" class it shows is used to enable that.
EDIT: It's my main editor, by the way, and it persists open buffers, and shares them between the user interfaces using Drb. Currently I have 1969 buffers open...
Originally I did it as a quick way of ensuring I didn't lose data when I started using it, as Drb will forward exceptions as well, so the backend just won't crash, so as long as you don't do anything which corrupts the buffers you're good. Instead the frontend may crash (and throw me into a Pry repl, where I can query the backend and make sure I can recover the buffers), and I can just restart the frontend on the same buffer and keep working. (In practice it mostly crashes when I am using it to edit itself)
As an extra precaution I made it serialise all the open buffers to disk regularly. So I can just shut down my machine and next time I open all the buffers are still there (like Emacs etc. it'll warn me if the file has been edited since the buffer was opened).
Eventually this also gave me multi-frame support "for free" in that splitting the buffer vertically or horizontally just spawns a new instance of the editor and attaches to the same buffer (and then you can open whatever you want in it)
I realised too late that it's hard to see the border on imgur, here's one using a different theme which makes it a lot easier to see the transition:
Web UI in comparison is always sluggish, usually required extra login method (instead of just sshing into client, or having CLI client with credentials saved) and in modern days require hundreds of megabytes of deps to even make the JS to run it
Don’t get me wrong, I’m not fond of the modern web either, but setting up something like a chat-like shell in a browser-over-ssh sounds like a pretty straightforward and lightweight job.
Edit: correct args would be
ssh -L 2345:server:2345 user@server '/home/user/bin/my-web-shell -p 2345'I do wish terminal graphics support was a little better. A terminal (like iTerm 2 [0]) that supports inline graphics allows your terminal to display plot etc in a graphical form without having to exit it. In MGR [1] this was the _only_ way to display graphics, even interactive, and I think it had a lot of merit.
There are many flaws with such approach, webapps being often crappy being of course one of them. But the redeeming factor is that practically all the tech already exists, this would need just minimal glue to make it reality, while many other approaches are more of a pipe dream.
At this point, I am 95% convinced that the reason web UI's are oftentimes perceived as sluggish is the easy access to custom animation/transition on the web platform. As a result, developers tend to overdo animations, or set the transition too long, resulting in a subpar experience.
In the example, there's obligatory 1 character vertical margin and horizontal padding (or vice versa). If you want consistence, you have to add one character of vertical padding and horizontal margin, or if you allow "rounded" (missing) corners, I suppose you could have margin in all directions and no padding.
Actually, Unicode "Symbols for Legacy Computing", U+1FB7C – U+1FB7F ('LEFT AND LOWER ONE EIGHTH BLOCK', 'LEFT AND UPPER ONE EIGHTH BLOCK', 'RIGHT AND UPPER ONE EIGHTH BLOCK', 'RIGHT AND LOWER ONE EIGHTH BLOCK'). But support may vary, as this is a relatively recent addition (based on a proposal from 2019 [1]).
That said, there is more to this approach, as it actually solves two problems at once: corners and the surrounding white space required for boxes with a background fill. And there are no compatibility requirements (as compared to using the new Unicode range.)
[1] http://www.unicode.org/L2/L2019/19025-terminals-prop.pdf
It's a clever trick actually, though it doesn't compose the way the traditional box-drawing characters do. Good for one (1) box, where you want to be able to set the background without bleed.
A 1-dimensional, 1-sided horizontal example would be if you have abcdef in the background partially covered by ABCDEF in the foreground. With a vertical bar in the middle, it looks like
abc|ABCDEF
However, with this new technique it looks more like: abc |ABCDEF
(approximation, notice the space; also this example assumes a different stacking as used in the article, which brings the problem in the x-direction which is convenient in this example)It can be done with GUIs, of course. You can also have bad TUIs. But "out of the box", the TUI tends towards better keyboard navigability than GUIs, so are more likely to get something usable "for free".
I find it very easy to get "trapped" in GUIs where your keyboard falls in to a focus pit that it can't get out of.
For example, the calculator. If you use the mouse to press a button while entering a calculation (for a trigonometric function say) then when you press enter to get the result it just presses that button again. This is contrary to the Windows design guidelines and, more importantly, it isn't useful.
It's like the apps have been redeveloped by people who never use a keyboard.
I know remote desktop stuff exists for GUIs (from RDP to VNC to X tunnelling), but ssh (or mosh) with TUI apps can provide a great balance of functionality and reliability that I've never found with any of the remote GUI solutions.
Oh, so this is something unimpressive being used to disguise an advertisement.
I've designed such interfaces, and drawing boxen is superfluous to the point I realized it's not worthwhile. Regardless, this solution seems obvious for anyone who actually had this issue, and I'm doubtful there were many.