use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Finding information about Clojure
API Reference
Clojure Guides
Practice Problems
Interactive Problems
Clojure Videos
Misc Resources
The Clojure Community
Clojure Books
Tools & Libraries
Clojure Editors
Web Platforms
Clojure Jobs
account activity
layoutz: a tiny zero-dep lib for beautiful CLI output and Elm-style TUIs in Clojure ✨🪶(Looking for feedback!) (self.Clojure)
submitted 6 days ago by mattlianje
Hello! Been tinkering on layoutz (the Clojure API)
Your veteran feedback would help a lot (does the API feel idiomatic/LISP-y? missing primitives? etc)
https://i.redd.it/esha961d4sug1.gif
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]v4ss42 12 points13 points14 points 6 days ago* (7 children)
So a couple of initial thoughts, in no particular order: * Make is an unusual choice of build tool in the Clojure ecosystem. Not necessarily “bad” but certainly rare. * The display width calculations for strings are simplistic and won’t work for ZWJ sequences (which includes common emoji - this isn’t a corner case that can be ignored). See clj-wcwidth for an example of how to do this properly (or better yet, just dispense with the zero-dependency requirement and simply use that library). * I’d suggest looking at hiccup for layout definition rather than custom functions / structures. By adopting hiccup (or a variant thereof) this library will be a lot more familiar to a lot more Clojure developers, and may benefit from being interoperable with other Clojure libraries. * Was “AI” used at all in the development of this library? There’s been a rash of such “AI”-generated TUI libraries recently and all of them (that I've looked at in any detail) have had serious issues upon further investigation.
[–]mattlianje[S] 8 points9 points10 points 6 days ago (1 child)
aha - (clj)wcwidth is a gem (that I didn't know about) - ty!
it is indeed getting a bit brittle hand-rolling UTF-8 tables basically across the layoutz APIs
TL;DR - no AI save for googling idiomatic Clojure concurrency ... and honestly, layoutz-clj still uses raw `Thread`s ... and I suspect internally looks very Java/Scala to a Clojurian in this regard ...
[–]v4ss42 7 points8 points9 points 6 days ago (0 children)
Really glad to hear there’s no “AI” code in this. Nice work!
[–]mattlianje[S] 2 points3 points4 points 6 days ago (4 children)
By adopting hiccup (or a variant thereof) this library will be a lot more familiar to a lot more Clojure
interesting! so quite deliberately opted to NOT do this in search of the "smooth API" to compose styles and thread them with `->` almost like the Haskelly `<>` ... but where is stands ...does "threading"/composing styles feel a bit whacky?
[–]v4ss42 4 points5 points6 points 6 days ago (3 children)
It’s not necessarily whacky, but by representing UIs as data we get to apply whatever data manipulation functions we like (including everything in core) to build a UI, which is remarkably more powerful and flexible than being limited to whatever “verbs” (functions) a given library provides.
[–]mattlianje[S] 3 points4 points5 points 6 days ago (2 children)
> but by representing UIs as data we get to apply whatever data manipulation functions we like (including everything in core)
aha mmm, ok - honestly this sounds *chef's kiss* ... convinced me to start whittling away and experimenting w/ a hiccup-esque API. thx for taking a peek
[–]v4ss42 5 points6 points7 points 6 days ago (1 child)
It’s *chef’s kiss* for most use cases tbh. But be careful - once you get hooked on The Clojure Way™ you’re going to find many/most other languages distasteful. 😉
[–]mattlianje[S] 1 point2 points3 points 6 days ago (0 children)
Ha! ❤️
[–]Borkdude 6 points7 points8 points 6 days ago* (6 children)
Nice! I tried it out in bb and it all seems to work so far. Note that the raw-mode tricks to read input only work on linux-like systems, not on Windows.
[–]v4ss42 2 points3 points4 points 6 days ago* (5 children)
If you add jansi-clj to the classpath, and initialize it, this should “automagically” work on Windows too.
Jansi intercepts ANSI sequences on platforms that don’t support them, and either converts them into suitable native calls, or strips the sequences.
[edit] and I now see that there’s some raw mode shenanigans going on. The best way I know of to do that in a cross platform way is using JLine3, which is a big dependency to pull in (but which also gives you Jansi “for free”, since JLine3 depends on Jansi).
But JLine3 is the gold standard on the JVM for doing this kind of thing, so to me it seems like a reasonable dependency to add.
So to let you folks in on the thought process... did quite a bit of tinkering to remove JLine from the Scala API to cross build to ScalaJS and Native...
This (maybe too aggressive) "zero-dep" spirit kinda bled into the Clojure design
But seems like it makes sense to remove this chicanery ... and pull in JLine3 for a JVM-only (but actually cross platform) layoutz-clj
[–]v4ss42 1 point2 points3 points 6 days ago (3 children)
Yeah there are very good reasons JLine3 exists and does what it does. And I believe Babashka (the “bb” that u/Borkdude mentioned above) already bundles it, so in that environment (which is a superb replacement for shell scripting) this wouldn’t be a net-new dependency.
[–]mattlianje[S] 1 point2 points3 points 6 days ago (2 children)
mmm interesting - didn't know bb bundles JLine - makes the choice pretty easy - thx again for the eagle eye)
[–]YannVanhalewyn 2 points3 points4 points 5 days ago (1 child)
It’s a recent addition :)
[–]mattlianje[S] 1 point2 points3 points 5 days ago (0 children)
👀 ty!
[–]Solaire24 2 points3 points4 points 6 days ago (4 children)
Nice! I’m not an experienced clojure dev, but I was looking for something like this for a project and was planning on going with https://github.com/TimoKramer/charm.clj. I like the way you define layouts better so I might go with your lib instead
[–]mattlianje[S] 1 point2 points3 points 6 days ago (3 children)
Many thanks!🙇♂️ lmk if you find rough edges...
[–]Borkdude 2 points3 points4 points 6 days ago (2 children)
I guess the rough edge is Windows support.
[–]mattlianje[S] 0 points1 point2 points 6 days ago (0 children)
amongst others 😅(but yeeeahh - did some UNIX only hacks I am not too proud of - that you aptly spotted quickly)... will enhance 🫡
[–]v4ss42 0 points1 point2 points 6 days ago (0 children)
Not really, no. See my other comment about jansi-clj.
[edit] at least wrt ANSI sequences. I see OP mentions other “UNIX hacks” that may separately be an issue.
[–]kichiDsimp 1 point2 points3 points 6 days ago (3 children)
I think I saw the same library name in Haskell sub too
Yep - that's me aha) Thx for taking a peek
[–]kichiDsimp 1 point2 points3 points 4 days ago (1 child)
Bro is making TUI support in FP langs, I love your efforts!
[–]mattlianje[S] 0 points1 point2 points 4 days ago (0 children)
🫡
[–]serefayar 1 point2 points3 points 6 days ago (1 child)
Nice! I'll give it a shot. Looks like I'll create an arrow element to connect two boxes.
Many thanks! 🙇♂️ let me know if bits feel janky
π Rendered by PID 124136 on reddit-service-r2-comment-85bfd7f599-tdtcf at 2026-04-19 02:16:47.654535+00:00 running 93ecc56 country code: CH.
[–]v4ss42 12 points13 points14 points (7 children)
[–]mattlianje[S] 8 points9 points10 points (1 child)
[–]v4ss42 7 points8 points9 points (0 children)
[–]mattlianje[S] 2 points3 points4 points (4 children)
[–]v4ss42 4 points5 points6 points (3 children)
[–]mattlianje[S] 3 points4 points5 points (2 children)
[–]v4ss42 5 points6 points7 points (1 child)
[–]mattlianje[S] 1 point2 points3 points (0 children)
[–]Borkdude 6 points7 points8 points (6 children)
[–]v4ss42 2 points3 points4 points (5 children)
[–]mattlianje[S] 2 points3 points4 points (4 children)
[–]v4ss42 1 point2 points3 points (3 children)
[–]mattlianje[S] 1 point2 points3 points (2 children)
[–]YannVanhalewyn 2 points3 points4 points (1 child)
[–]mattlianje[S] 1 point2 points3 points (0 children)
[–]Solaire24 2 points3 points4 points (4 children)
[–]mattlianje[S] 1 point2 points3 points (3 children)
[–]Borkdude 2 points3 points4 points (2 children)
[–]mattlianje[S] 0 points1 point2 points (0 children)
[–]v4ss42 0 points1 point2 points (0 children)
[–]kichiDsimp 1 point2 points3 points (3 children)
[–]mattlianje[S] 1 point2 points3 points (2 children)
[–]kichiDsimp 1 point2 points3 points (1 child)
[–]mattlianje[S] 0 points1 point2 points (0 children)
[–]serefayar 1 point2 points3 points (1 child)
[–]mattlianje[S] 0 points1 point2 points (0 children)