https://clojurians.slack.com/archives/C06JZ4X334N/p1741312782861049 @smith.adriane Did you ever get a flash of insight or make any progress on the issue discussed in this thread? I'm working on a similar system to membrane, but only for the terminal, and, like membrane, you don't get anything for free and you have to implement everything (focus, hover, etc). Replicant's model is really elegant, but it leans entirely on the dom/css for those sorts of concerns. I've been noodling around with different ideas. Currently I'm leaning towards the Elm MVU architecture.
Membrane's state management can and does work in the terminal, https://github.com/phronmophobic/terminal-todo-mvc. Membrane's state management is optional and you can use the membrane data model without using the state management (eg. membrane.component). I've been interested in integrating other state management options from outside membrane, but I haven't found any that have been up to the task.
If you're just trying to get up and running quickly, you try some libraries from the js world: https://clojurians.slack.com/archives/CQT1NFF4L/p1646244559963309?thread_ts=1646233781.943679&cid=CQT1NFF4L.
Is there a reason you're targeting the terminal rather than a desktop app? In my experience, there are few instances where you really need the app to run inside the terminal (eg. you're using the UI via ssh).
Sorry I didn't ask my question very clearly. I am curious if you've had any thoughts or insights specifically on this topic of "other" state management patterns for membrane. It sounds like the answer is: "not yet"? What conclusion did you come to about a data driven top down render flow ala replicant? --- As to your questions: I'm aware of membrane's lanterna support, I toyed around with it, and it is a real testament to membrane's design that it works as well as it does! Props on that. However for various NIH non-reasons I wanted to develop a from scratch clojure-first terminal manipulation (low level) and rendering library (higher level, with a data driven ui). The fact that FFI/FFM is now supported in graalvm native image in JDK 25 makes such a library that can produce standalone fast-starting binaries actually feasible with "no dependencies" (read: java libs, JNI, nodejs etc). Your membrane docs on public/private and essential/incidental state are very interesting. I find myself returning to read it as I go through different stages of development on this project.
Generally, I find the state management that membrane offers acceptable. If there is another state management solution that's functional, I would be interested in checking it out, but I haven't found one yet. I'm not interested in extending someone else's state management solution to make it work outside of the browser.
Replicant's state management has lots of similarities with membrane's. I do think memoization/caching of component renders would essentially be a free win for replicant, https://clojurians.slack.com/archives/C06JZ4X334N/p1750178260431799?thread_ts=1750163389.619449&cid=C06JZ4X334N. I do think it could solve some of the performance issues you would have with handling stuff like mouse-move events.
https://replicant.fun/top-down/#reusability > This approach optimizes for the system as a whole instead of for its building blocks. In my experience, this is more effective at keeping code bases manageable over time. In fact, strong centralized machinery allows you to earn compounding interest on your investments over time – instead of drowning in ever increasing technical debt. I disagree that there's a tradeoff here. I think having reusable components is important and that you don't have to give up optimizing for the system as a whole. As you may be learning, no one wants to write their own text input.
> Your membrane docs on public/private and essential/incidental state are very interesting. I find myself returning to read it as I go through different stages of development on this project. I think there's some areas where I can improve the explanations. I do intend to revisit these ideas at some point and try to do a better job explaining things. Let me know if you have any questions or suggestions.
As far as implementing text inputs, you may find clobber useful. It's a design goal for clobber that you can do a lot of text editing as data only without any coupling to a specific UI library, https://github.com/phronmophobic/clobber/blob/main/src/com/phronemophobic/clobber/modes/text.clj. See https://youtu.be/kRd4JYIiWb0?t=1225 for more info.
The fact that FFI/FFM is now supported in graalvm native image in JDK 25 makes such a library that can produce standalone fast-starting binaries actually feasible with "no dependencies" (read: java libs, JNI, nodejs etc).Fwiw, graalvm already had support for JNA. The https://github.com/phronmophobic/terminal-todo-mvc example has instructions for compiling using graalvm. Totally understand if you still want to do your own thing though. I will be interested to see if you come up with another state management option that is functional. I think there are lots of opportunities and unexplored design space for new techniques.
Top down rendering is probably fine for terminal since input events tend to come in at a pretty slow rate.
any luck in getting icu4j to work with native-image?
No, but I haven't tried. Do you have a particular use case in mind?
I've now removed it from my library: https://clojurians.slack.com/archives/C06MAR553/p1769432464453419. I am not sure but I think using the jvm internal breakiterator in the latest jvm releases should be good enough. will have to investigate a bit more.
Yea, I was going to suggest the breakiterator that ships in the java standard library. One thing to watch out for is that in the versions I tested, using the breakiterator would segment the full string which may be a problem if you are segmenting lots of different, long strings.
ok interesting behaviour. but i guess terminal interaction can be tricky. will test some things.
> As far as implementing text inputs, you may find clobber useful. This is amazing! Thanks for sharing your video. How is the headless support in clobber currently? Its a design goal, but is it also a reality at the moment?
The headless support currently works. Thinking about it a bit, I'm not sure if icu4j is native image compatible. I only use one class, com.ibm.icu.text.BreakIterator, which is a drop in replacement for java.text.BreakIterator . I think if icu4j isn't native image compatible, it would be easy to add a flag to use java.text.BreakIterator instead, which should hopefully already be native image compatible. I use BreakIterator for counting grapheme clusters, but I could make it possible to just use code points for platforms that don't have a library available for counting grapheme clusters.
I have some projects where I want to use clobber with native image. I think counting grapheme clusters is the only issue where I'm not sure how easy/hard it will be to use with native image.
clobber is really cool 🙂 I already have a few TUI input fields working that are powered by it
feel free to ping me or file an issue if you have any problems
I suppose if icu4j doesn't work with native image one could use the ICU c library right? I suppose that depends on what platform support you need and your distribution mechanism. I also wonder how straightforward it is to bundle a shared lib in the native image and extract it at runtime.
Potentially. The icu libraries also have a bunch of data files and I'm not sure how hard they are to package with native image. I assume it's possible, but just not sure what the right steps are. I would first check to see if java.text.BreakIterator suits your needs and is native image compatible as it is probably the easiest option long term.
> I also wonder how straightforward it is to bundle a shared lib in the native image and extract it at runtime.
It's definitely possible, but it's uncommon since you would typically build the library statically and then just link it directly into the resulting executable.
icu4c doesn't seem too bad, https://unicode-org.github.io/icu/userguide/icu4c/packaging.html#link-to-icu-statically (although I still think using java.text.BreakIterator is probably more straightforward).