And here some photos of the crazy kitchen we had at our glamping trip. Of course, it was waaaaaaaaaaaaay oversize. Itâs typically used to feed several hundred people, not just only 70ish. Although it was really fun to work in, cleaning the whole thing took an entire day. We completely underestimated this.
https://lyse.isobeef.org/2026-09-07-willy-brandt-zeltlagerplatz-kueche1/
Something felt definitely wrong, I got up much earlier during the camp than when I have to work. Typically, I woke up beween 6 and 7 because I really had to go to the loo. There was almost always somebody already awake from the kitchen teammates or leaders. So, I always decided to not return to bed. When I was the very first one, I turned on the coffee machine and water kettle to the delight of the others and five minutes later, another person arrived at the kitchen. As a bonus, we sometimes got to enjoy the sunrises, like this one: https://lyse.isobeef.org/2026-09-07-morgensonne/
@itsericwoodward@itsericwoodward.com Then by all means, follow the instructions at https://git.mills.io/prologic/parley and setup your own instance on your own domain. Itâs partly inspired by Twtxt/Yarn.social and Salty.im â in at least the way teh DNS discovery and WKID works. Once your instance is up and running and youâve gone through the /setup and created yourself an account (or seti it up with an appropraite ODIC IDP) try something like /msg james@mills.io Hey! at which point you should automatically start peering with my instance. You should then be able to /join #lobby1 (a globally federated channel already across 2 instances so far). đ€
I have (finally) built a fully e2e working purely decentralised and federated IRC-compatible chat server. It is currently a PoC, but itâs already working quite well. Itâs inspired partly by the work we did with Salty Chat in terms of Discovery and Federation. Some screenshots of a normal IRC client irssi showing off how it works in a local e2e setup:

git, curl and a web server of some kind.
For the curious, this is fully documented with roleplay Alice/Bob. I was going to test this with @david@daiwei.me but we both got busy, but now Iâm on holidays from work for a month so đ€·ââïž đ€Ł
âIf you only pay attention to how things work, youâll be screwed when they failâ â Cory Doctorow
Um relato dos meus sentimentos muito misturados a respeito do #Manjaro e minha simultĂąnea incompetĂȘncia e competĂȘncia:
Nas Ășltimas semanas tava tendo que âbootar de um snapshotâ no meu micro do dia a dia, hoje finalmente quebrou tudo e nĂŁo conseguia mais bootar. AĂ, tome de bootar de um pendrive, e acessar umas anotaçÔes que eu tenho pra fazer o chroot⊠acho tudo muito difĂcil pq tenho que decriptar o hd, e montar partiçÔes diversas, nĂŁo manjo exatamente o que estou fazendo, sigo a receita anotada, muitos passos.
Em seguida, reinstalar kernels com pamac -S linuxXX e mhwd-kernel, reinstalar o grub, e usar o mkinitcpio -P pra recriar as âimagensâ dos kernels usadas no boot. NĂŁo sei o que resolveu exatamente o problema (tinha tentado esse mkinitcpio -P faz algumas semanas, sem ser bootando do pendrive, e nĂŁo tinha funcionado)
De um lado sou grato por ter conseguido fazer as coisas funcionarem, grato pelo esforço de muitas pessoas voluntĂĄrias fazendo o Manjaro ser teoricamente âmais fĂĄcilâ pra algumas pessoas, por outro lado acho tudo muito difĂcil e nĂŁo consigo imaginar outras pessoas do meu convĂvio fazendo essas coisas, nem eu consigo entender o que estou fazendo!
SerĂĄ que nĂŁo teria como ser mais fĂĄcil?
âIf you only pay attention to how things work, youâll be screwed when they failâ â Cory Doctorow
Um relato dos meus sentimentos misturados a respeito do #Manjaro e minha simultĂąnea incompetĂȘncia e competĂȘncia:
Nas Ășltimas semanas andei âbootando de um snapshotâ no meu micro do dia a dia, e hoje finalmente quebrou tudo e bootava mais. AĂ, tome de bootar de um pendrive, e acessar anotaçÔes que eu tenho pra fazer o chroot⊠acho tudo muito difĂcil pq tenho que decriptar o hd, e montar partiçÔes diversas, nĂŁo manjo exatamente o que estou fazendo, sigo a receita anotada, muitos passos.
Em seguida, reinstalei kernels com pamac -S linuxXX e mhwd-kernel, reinstalar o grub, e usei o mkinitcpio -P pra recriar as âimagensâ dos kernels pro boot. NĂŁo sei o que resolveu exatamente o problema (tinha tentado esse mkinitcpio -P faz algumas semanas, sem ser bootando do pendrive, e nĂŁo tinha funcionado)
De um lado sou grato por ter conseguido fazer as coisas funcionarem, grato pelo esforço de muitas pessoas voluntĂĄrias fazendo o Manjaro ser teoricamente âmais fĂĄcilâ pra algumas pessoas, por outro lado acho tudo muito difĂcil e nĂŁo consigo imaginar outras pessoas do meu convĂvio fazendo essas coisas, nem eu consigo entender o que estou fazendo!
SerĂĄ que nĂŁo teria como ser mais fĂĄcil? SerĂĄ que um dia vou achar fĂĄcil?
âIf you only pay attention to how things work, youâll be screwed when they failâ â Cory Doctorow
Um relato dos meus sentimentos misturados a respeito do #Manjaro e minha simultĂąnea incompetĂȘncia e competĂȘncia:
Nas Ășltimas semanas andei âbootando de um snapshotâ no meu micro do dia a dia, e hoje finalmente quebrou tudo e nĂŁo bootava mais. AĂ, tome de bootar de um pendrive, e acessar anotaçÔes que eu tenho pra fazer o chroot⊠acho tudo muito difĂcil pq tenho que decriptar o hd, e montar partiçÔes diversas, nĂŁo manjo exatamente o que estou fazendo, sigo a receita anotada, muitos passos.
Em seguida, reinstalei kernels com pamac -S linuxXX e mhwd-kernel, reinstalar o grub, e usei o mkinitcpio -P pra recriar as âimagensâ dos kernels pro boot. NĂŁo sei o que resolveu exatamente o problema (tinha tentado esse mkinitcpio -P faz algumas semanas, sem ser bootando do pendrive, e nĂŁo tinha funcionado)
De um lado sou grato por ter conseguido fazer as coisas funcionarem, grato pelo esforço de muitas pessoas voluntĂĄrias fazendo o Manjaro ser teoricamente âmais fĂĄcilâ pra algumas pessoas, por outro lado acho tudo muito difĂcil e nĂŁo consigo imaginar outras pessoas do meu convĂvio fazendo essas coisas, nem eu consigo entender o que estou fazendo!
SerĂĄ que nĂŁo teria como ser mais fĂĄcil? SerĂĄ que um dia vou achar fĂĄcil?
@movq@www.uninformativ.de Ahh, no you can. Much like what weâve built here with Twtxt / Yarn. Iâm building a spec, clients can implement the spec, or you can ya know, just curl and git your way through. Iâll link the spec soonâą, just need to keep refining and testing and make sure this actually works properly đ
@movq@www.uninformativ.de So the way this works in my design/prototype is this. You fork my repo in the app, it clones it to your own forge, follows my instance and itâs repo for updates and ping my instance to indicate âyouâve forked meâ. Then when you publish changes, I can see them by pulling your instanceâs feed. It all works on the same plain text principles of Tstxt itself. The feeds are âpullâ-based with push-based âpingsâ on things like âsomeone forked your repoâ, âa new issue has been raised against your repoâ, etc.
Literally just a day after Elon came out with his legal threats towards all of Nitter and people like me complained about it, Open AI decides to no longer work with Cursor (acquired by Space X), explicitly saying itâs because Elon wouldnât stop breaking their signed contracts and scraping (distilling) their models, behind their back.
https://openai.com/index/our-decision-on-cursor-following-its-acquisition-by-spacex/
This is not even the only instance of this happening, many mentioned having similar problems with Elon in the past. Not too long ago Kylie Robison shared a rumor xAI engineers were banned from using Anthropic models through Cursor, because of their scraping, though they seem to have later patched things over with Elon, when they had to start renting his data centers.

@movq@www.uninformativ.de Humidity was through the sky. We had two thunderstorms pass by. One at 06:00 and and another one this arvo.
Somebody hooked this presumably plastic moon on the tree bark. Not sure why or what the reason is. Letâs just call it art. It looked weird and so I thought that it might poke other peopleâs interests as well. Worked out great. Got another question about it, too. ;-)
Started doing âFraktur Freitagâ last week on Mastodon, and why not post it here as well. (âBlackletter Fridayâ? Doesnât work in English. đ€Ș)
I want to make this a weekly thing, but I obviously cannot guarantee it. đ
Awful 33°C today. But I had to move, no matter what. So, I went outside. At first, the sun was out a bit. It was brutal. Later it vanished behind the clouds. But the humidity was still through the roof.
I watched the corn harvest I came across. Dusty as hell, but it was great fun observe the machineries work.
Going up my backyard mountain, there werenât many people around. I was pleasantly surprised. However, the smaller hill below was rather crowded. Many people with picnic mats, enjoying their dinner, painting A3 love letters, claiming all available benches, taking wedding photos, walking their dogs, etc.
The public barbecue site at the summit is still closed due to the ongoing fire hazard. I found it rather funny to see a fire extinguisher ready to go next to it. The bread and cake smell disclosed that the Mountain Baking Boys were active. The large oven right next to the BBQ was still going strong.
Similar here đ„ł 9 days then iâm off for 3 weeks. but really 20 working days!
Had no clue @prologic@twtxt.net has his own computer mouse brand now, straight up giving them away, for under $3 a piece.
I got one and well pleasantly surprised, especially for the price. It fits perfectly in the hand, decent rubber, weighs nothing, clicks very silently. The scroll wheel is where you can feel some of the cost cutting, itâs pretty wonky, but good enough.
Classic cheap thin long cable, you better like 1600 DPI, cause thereâs no button to change that. Sensor is the usual red light, but works on all surfaces, bedsheets included. Gliders are small and not around the sensor, but at this weight, that makes next to no difference.
Decent 8/10 option

Had no clue @prologic@twtxt.net has his own computer mouse brand now, straight up giving them away, for under $3 a piece.
I got one and well pleasantly surprised, especially for the price. It fits perfectly in my hand, decent rubber, weighs nothing, clicks very silently. The scroll wheel is where you can feel some of the cost cutting, itâs pretty wonky, but good enough.
Classic cheap thin long cable, you better like 1600 DPI, cause thereâs no button to change that. Sensor is the usual red light, but works on all surfaces, bedsheets included. Gliders are small and not around the sensor, but at this weight, that makes next to no difference.
Decent 8/10 option

@movq@www.uninformativ.de I usually donât listen to metal where the singers scream. There are only very, very few bands where I find that actually pleasing.
Two decades ago or so, we young supervisors compiled ourselves a cassette for our forest recreation week. One of us had an old ruggedly built radio with a cassette deck powered by a bunch of large Baby (?) batteries. One side had âworking musicâ which we played back while working in the evenings and night, e.g. gathering firewood in a handtruck for the campfire and things like that.
I used something by either Finntroll or Turmion KĂ€tilöt for the âwakeup musicâ side in the morning. The kids slept at home, but there were always some supervisors sleeping at the camp. The SĂT, the Standard-Ăbernachtungsteam, consisted of mostly young folks, about sixteen to early twenties. It was completed by wiser people in their fourties. Each morning, metal blasted through the dining tent that we converted into a sleeping tent. :-) Good times!
@movq@www.uninformativ.de I actually didnât know that and just listened to it. There are a few nice songs, but in general, itâs too boring to me. Iâm missing the rock and metal elements for sure. Some of the calm songs might work to relax in a sauna or so. But I find the âwind noiseâ rather annoying.
@smmbear@twtpub.com Hey đ Welcome to Yarn.social / Twtxt đ Just in case you are not ware a) spam is not really tolerated by this community and b) doesnât work anyway, youâll just be ignored, and there are exactly zero ways to promote spam or advertise on this social system â on purpose.
@murad@twtxt.net Yes things do work đ€Ł
Whatâs interesting here⊠Which is the interesting thing about Mu is the dual runtime. So the above solution for Euler Problem 9 finds the solution in ~429ms with the Go VM and ~327ms natively compiled to darwin/arm64. Not bad for a language I havenât really done any optimization work on yet (correctness first obviously).
It is such a nice feeling that Mu is such a capable little language đ And I decided to write code code in Mu by hand đ€ haha đ€Ł and start solving Project Euler problems, like Problem 8 which works out to be a nice elegant solution in Mu:
#!/usr/bin/env mu
// Largest Product in a Series
import "fp"
import "sys"
fn usage() {
print("Usage: cat |", args()[0], "<n>")
}
fn products(xs) {
return fp.reduce(xs, 1, fn(x, y) {
if y == nil {
return x
}
return x * y
})
}
fn main() {
if len(args()) < 2 {
usage()
exit(1)
}
s := must(sys.read_all(0))
if len(s) == 0 {
usage()
exit(1)
}
n := must(int(args()[1]))
r := fp.max(fp.map(fp.sliding(fp.map(s, int), n), products))
print(r)
}
main()
I am a bit split on this, donât think thereâs any real use for AI in things like art, at absolute most getting a reference to compare with multiple non-AI ones, or possibly some animation in between frames, if it ever gets better at making those. Would not rely on it for any of my personal projects, more than maybe a quick search that would have previously been done on Stack Overflow, but if I work somewhere and they demand it be used similarly to how it is described on this site, considering the current IT job market, Iâd probably take the slop bullet, over being unemployed.
Obviously even in that case, Iâd only do this to generate code I can understand, improve and review. Iâm definitely not advacating people just put their feet up on the table and let some random combination of âAI agentsâ, vibecode their entire codebase.
I hate having my website offline, so I tried to bring it back in a honey-potted version: âAIâ agents get served article versions with inverted meaning, like âdoâ replaced with âdonâtâ and so on.
It didnât work. Claude noticed it and âfixedâ it back to the original version. When I asked it, âwait, nowhere on the page does it say $string, check againâ, it said:
This is the creepiest shit ever. Silently âfixingâ stuff behind my back is the epitome of untrustworthiness.
Open the bay doors, HAL.
I donât like using Instagram and I was happy that maybe I could automate posting my daily sketches there using a #python script with the #instagrapi library.
I tried posting a single image as a test yesterday and it worked great in the first attempt, yay! :)
Today my account was blocked as Meta figured my account might have been invaded! :(
So there goes my excitement about automated posting on InstagramâŠ
I really do find it difficult to follow anyone that basically posts to a wall, or doesnât follow back. Itâs utterly pointless not being able to have a conversation, like basically, at all. Maybe itâs not even anyoneâs fault? Maybe just a sucky client that doesnât understand how User-Agent works in Twtxt Discovery? đĄ
I kind of feel that I finally found a way to visualize and maybe explain to myself and others how a #numpy #meshgrid works⊠Letâs see how long this feeling lasts đ
(⊠I should draw some diagrams from this insightâŠ) #python #education
@david@daiwei.me Sorry, I canât do this anymore. A large part of my work (text, code, thoughts, âŠ) of the last 20-25 years has been stolen and is now being sold at rampant prices to idiots who then complain about me being a backwards bitch (I get to hear this every single day). Everything I say and do in public is being abused.
Fuck that, Iâm out.
@david@daiwei.me Thanks, mate! I just finished my two full version marking gauges. And Iâm rather pleased with them, I think they turned out great if I say so myself.
https://lyse.isobeef.org/tmp/streichmass-mit-messerrad/
The beech fences (80 and 100mm long) were part of a former table frame that I cut down. I plugged the dowel holes with, well, dowels. The horrific looking one was the stuck original one, though. Luckily, itâs a hell lot worse on camera than in person. If you take a close look, youâll also be able to see the large but slight chamfers one one side each that I just left alone.
I really like beech wood. It looks beautiful, is rather heavy (at least in comparison to spruce which I typically use) and thus rock solid, is also a blast to plane and the list goes on. I sanded it with 180 grit and itâs smooth as a babyâs bottom.
The 25mm beech round stocks that house the brass knurled nuts are now roughly 4cm long. Thatâs one thing I wanted to change right after my first experience. If they were rounded or chamfered more, it would probably be even nicer for the fingers when using the marking gauge. Theyâre sunken in roughly 3mm in the fences. A forstner bit made quick work. This simplified alignment during glue-up a lot. Will definitely do that again if I happen to build more. I could fully concentrate on the grain orientation and it didnât shift around.
Just like in the prototype, I used 8mm aluminium solid round bar again for one of the marking gauges. Itâs also about 15cm in length. I figure thatâs enough. The bought marking gauge has a twenty-something and some change steel rod. So far, all my markings didnât even exceed probably 50mm.
I found the 8mm brass pipe laying around on the workshop. Didnât know anymore I had it for ages. Unfortunately, the wall thickness is below a millimeter, so my 6mm wooden dowels are sliding in there. Thus, I put 8mm dowels in my drill chuck and reduced the diameter with a rasp. I went a tiny bit too far, the press fit is on the loose side. When drilling with a 2mm drill (I did that on purpose to hopefully cause the dowel to expand a bit more in the pipe, typically the tap hole for M3 is 2.5mm) and tapping M3, the downsized and glued in dowel slipped down the pipe. Should have used construction adhesive or something along those lines. Anyway, I might replace it with a solid one. I consider this a half-successful experiment. I fear that an unfavorable grain direction might pull out the cutting wheel during use. Letâs see.
The finish of all three is boiled linseed oil. It looks nice, but oh by, this smell. I really dislike it. My hands stink even after washing them several times. I still got several liters left, so I have the dubious joy to use it on many, many other projects to come.
Oh, one last thing. Didnât manage to drill the tiny holes for my M3x16 bolts perfectly in center like for the prototype. Theyâre a tiny bit off. Also, on the longer fenced marking gauge, the hole for the knurled nut is a little to the side and at an angle. No idea how I messed this up. Luckily, itâs just a look thing but doesnât impair use.
Bwahahaha, these security folks have a great sense of humor! :-D Got a phishing test e-mail disguised as an overdue anti-phishing training e-mail:
We receive these test phishing e-mails every now and then at work. When you follow the links and log in at the fake login, you probably get assigned another (real) training.
When I got this e-mail, I immediately thought of such a test. Since I actually do have some stupid training deadlines coming up soon, I wasnât 100% sure, but still doubted that this was one of them. To make the timing even better, in the team meeting last week, our bosses reminded us to complete outstanding trainings before the deadlines. Ideally well in advance. Notifications about deadlines coming closer are sometimes not only sent to the individuals but also to the bosses and their bosses. And then things can get out of hands when somebody doesnât read the e-mails properly and mistakes them for deadline exceeded reports.
Anyway, the URL also looked kinda legit. It really doesnât help a single bit that domain names change all the fucking time. So, still with the test program in mind, I thought, I just give it a quick shot out of curiosity. Since I just had logged in before, the empty SSO username field was totally obvious then. Looking at the e-mail headers confirmed that this was indeed one of securityâs field checks. :-)
@bender@twtxt.net probably just too busy with real life and work to interact with us plebs đ€Ł
So #flameshot stopped working for me on #manjaro #xfce, any suggestions?
@GabesArcade@gabesarcade.com Probably. How do you want this to work? An âExportâ button to export all your settings in some form?
Dunno if anyone will find this interesting⊠But some ~6 months or so ago I experimented briefly with creating a whole bootloader + kernel + userland â Basically an entire OS in the Mu programming language (which as you know I also designed and created) â 6 months later Iâve worked on it some more after spending the last week working on improvements to Mu itself, which is now able to compile itself with its own Mu implemented compiler and now have an os/arch backend called muos/amd64 that boots into a running shell, with a tiny little vfs, UNIX-like semantics, syscalls, read/write, etc. It works pretty nicely, and aside from a small Assembly ânucleusâ, most of the Kernel and Userspace is written in Mu.
@prologic@twtxt.net Seems to work? đ§
@klaxzy@klaxzy.net Hey, sounds exactly like the company I work(ed) for.
@movq@www.uninformativ.de Similar to my Go IDE at work. GoLand hangs so often in this giant code base. :-D (But it could also be one or the other snake oil thatâs forcefully installed and fucks with me every day.)
@david@daiwei.me Hahaha! The thing is, it doesnât taste as good in summer as in winter for some unknown reason. Two or three decades ago I asked my grandma to bake some of her amazing gingerbread in summer. But she always refused, claiming that this only really works in winter. Of course, I didnât believe that. Finally, after years of begging and pleading, she finally made a tray. And to my surprise, she was right. It wasnât bad, no, no, not at all. It was really yummy. But the gingerbread in winter was just better. :-/
Maybe I should give it a shot myself. Perhaps she slightly changed the recipe on purpose. So that I will never break the tradition of seasonal food again. :-P It worked, at least I never asked her to bake gingerbread in summer again. :-D
@thecanine@twtxt.net Always love your work ! đ
jenny stuff aside, I received zero bug reports or code contributions since leaving GitHub in 2018.
@movq@www.uninformativ.de Finally, your software is just perfect and finished by now, no need to report non-existing bugs or send in code changes. :-) How many tickets and merge requests did you get before moving to your own server?
I have to admit that I use git format-patch so rarely, I always have to pull it up from my shell history. Havenât used git send-email even once. I definitely have to look into that soon. Wanted to do that for several years. I typically upload the patch to my server and send a link via IRC.
Maybe I was just very unlucky, but my experience is that you can perfectly ignore people and their work who only do it for the âfameâ. Itâs almost always been from inferior quality to say the least.
@movq@www.uninformativ.de Works good. I fully get and support your reasoning behind that change. Thereâs only one downside. Quickly looking at some code snippets in the browser helps me to quickly judge whether itâs worth to clone a repo or not. Oh well. :-) After all I know that movqware always is.
After many months of hardâą work, Iâve finally been able to get Mu (”) lang to a point where the duplication of machine code / assembly between the ARM64/AMD64 and Mach-O and ELF formats are not all eliminated. This now means that writing a new backend target os/arch for Mu is now relatively simple to do, or far less duplicated work/effort.
@david@daiwei.me @lyse@lyse.isobeef.org Oh, I wish it was for work. Iâd usually abstain from going if donât get to choose either the location, or the company. But, both? HEeeeeLL No!! đ
tt. I run into this bug almost daily for weeks now.
@prologic@twtxt.net A screenshot wonât help in this case, as you donât see anything. :-D It starts off just fine with a conversation tree like that:
Unknown conversation root
ââŽRead reply
ââŽRead subreply
Everything works. After reloading the feeds, a new message becomes part of the conversation, so the conversation e.g. looks:
Unknown conversation root
ââŽRead reply
ââŽRead subreply
ââŽUnread subreply
However, the bug is that the whole conversation is not shown at all. None of the three (or four with the root) messages appear in the message tree view. My recursive SQL determining the messages to display is clearly broken.
Posting the review and plan here for posterity as it is related to this thread: https://canvas.mills.io/a/6QVGjzRW
The PR(s) as-is will likely not go ahead Iâm afraid. More work to be done, but this is basically all about the âRecoveryâ story and how to anchor and notion of an âaccountâ without well umm an account đ€Ł
@aelaraji@aelaraji.com Thatâs totally fine if you work at the beach. :-)
@david@daiwei.me Not sure if you only mean the code segments or in general. In theory, a general darker text color for read messages would probably work. The thing is that regular white on black is quite standard. In Newsboat, new articles are red (I opted for yellow here) and read ones white. I found that useful and kinda copied it for tt.
In theory, itâs Gitea anyway. So it should work.
I trip over this in our code at work all the time.
Python has this concept of âpropertiesâ:
class Oink:
def __init__(self):
self._foo = 3
@property
def my_property(self):
return self._foo
a = Oink()
print(a.my_property)
my_property() is a method but it can be used as if it were a field.
This can also be used to define a setter:
class Oink:
def __init__(self):
self._foo = 3
@property
def my_property(self):
return self._foo
@my_property.setter
def my_property(self, value):
self._foo = 123 * value
Because, for some reason, Python people donât like getters and setters. Instead, they hide it behind a property.
The result is, when you read this:
a.my_property = 5
print(a.my_property)
You have no idea that this actually calls a method.
I really think I should go back to Java.
Writing programs in Python is so exhausting. I want a compiler and I want static typing. No, linters and type checkers and IDEs are not good enough. Compilers catch way more errors in advance.
Rust is also exhausting. Theyâre constantly adding language features and, at the same time, the runtime library remains tiny and you need 3rd party libraries for everything. Many of those are still at version 0.x (SemVer!) and you canât rely on anything. Often times, you need the latest Rust nightly compiler.
Go is ⊠I donât like it. And huge binaries.
I like C as a language, but itâs too fragile. I want to have a proper HashMap every now and then.
None of the above have good GUI libraries, at least not on Linux.
And then thereâs Java. This is my fractal renderer that I wrote over 17 years ago:
https://movq.de/v/fcd3c4e557/vid-1784121825.mp4
Itâs fast. It has a GUI with custom widgets and those werenât even hard to make. It still works without changing a single line of code. The source code files have timestamps from 2009 and I just noticed that the JAR file Iâm using in the video was compiled in 2010.
Java as a language is relatively easy to learn and to master. There are few surprises. The source code organization with packages is good. Java API docs are clear and well written.
The JVM ramp-up times have improved considerably:
https://movq.de/v/e7314e521e/vid-1784121998.mp4
This isnât like the Dark Ages anymore. Might even be usable for some CLI tools.
The only thing where Java really sucks is anything close-ish to the kernel. Try issuing an ioctl() ⊠I couldnât have made my TUI framework in Java, but then again, I wouldnât have needed to because Swing already exists and it just works.
Just depends, if I get overwhelmed and canât keep up with demand, Iâll insist on a Gitea Issue(s) so I can organise the work.
@david@daiwei.me I agree, the App (https://twtxt.app) really does work quite nicely đ
Hurray, I can now press gg instead of g to go to the top in tt. Much better! :-) Other multi-key combinations are also easily possible now.
I should probably write a real article about this at some point, but here we go. The only downside with my new key binding system is that it breaks tviewâs established pattern. Youâve got an InputHandler(), that is implemented using WrapInputHandler(âŠ). It typically then directly implements the switching logic depending on the key press. Something like this:
func (w *Widget) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
// WrapInputHandler allows for intercepting key events with SetInputCapture(âŠ)
// from the outside for customization. This handles the default key bindings.
return t.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
switch event.Key() {
case tcell.KeyRune:
if event.Modifiers() == tcell.ModNone {
switch event.Rune() {
case 'k':
w.scrollUp()
return // we already handled the event, stop processing
case 'j':
w.scrollDown()
return
}
}
}
// We didn't handle the key event. Maybe the parent
// widget knows what to do with it.
if handler := w.parent.InputHandler(); handler != nil {
handler(event, setFocus)
}
})
}
From the outside, you can intercept and either stop or continue the widgetâs original key handling with a potentially rewritten key event using SetInputCapture(âŠ):
w := NewWidget()
// customized or additional key bindings
w.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
case tcell.KeyUp:
// Rewrite the event, so the "cursor up" key is an alias
// for the vim key binding "k", that is handled by the
// wrapped input handler above. (I know, I know, this is a
// completely unrealistic example, why would anyone use
// cursor keys when there are vim key bindings available?!)
return tcell.NewEventKey(tcell.KeyRune, 'k', tcell.ModNone)
case tcell.KeyRune:
if event.Modifiers() == tcell.ModNone {
switch event.Rune() {
case 'q':
app.Stop()
// we already handled the event, do not pass it
// to the wrapped input handler above
return nil
case 'r':
toggleMessageReadStatus()
return nil
}
}
}
// we didn't handle the event, pass it to the wrapped
// input handler above
return event
}
Since they all expect a single key, Iâve noticed that using multiple dedicated KeyBindings of mine on these different levels kinda breaks multi-key handling with common prefixes. The outer-most KeyBinding captures the prefix, but it canât transfer it to the inner one if not handled by the outer one. At least not without some more (potentially ugly) changes. So, I now have to work with just a single KeyBindings object for the entire widget chain (if it consists of multiple other widgets or the regular input handler and input capture are in the game). The outside needs to register all its key bind customizations or extensions at the same level that the original widget handles its default ones. Doable by exposing the widgetâs KeyBindings instance, but not pretty. You always have to keep this in mind.
With the KeyBindings, it will look like that:
type Widget struct {
parent tview.Primitive
// make it available to children or the outside either by
// direct field access or by providing a getter method
KeyBindings *bind.KeyBindings
}
func NewWidget() *Widget {
w := &Widget{KeyBindings: &bind.KeyBindings{}}
w.KeyBindings. // default key bindings
Bind0(bind.KeySequence('k', w.scrollUp).
Bind0(bind.KeySequence('j', w.scrollDown)
return w
}
func (w *Widget) InputHandler() InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
return t.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
// also note the missing support for focus transfer at the moment
event = w.KeyBindings.Capture(event)
if event == nil {
return
}
if handler := w.parent.InputHandler(); handler != nil {
handler(event, setFocus)
}
}
}
And then from the outside, or in a child widget:
w := NewWidget()
w.KeyBindings. // additional or customized key bindings
Bind1(bind.KeySequence(tcell.KeyUp), func(*tcell.EventKey) *tcell.EventKey {
return tcell.NewEventKey(tcell.KeyRune, 'k', tcell.ModNone)
}).
Bind0(bind.KeySequence('q'), app.Stop).
Bind0(bind.KeySequence('r'), toggleMessageReadStatus)
When directly working with tview primitives that are not part of custom widget implementations, the following works well so far:
textView := tview.NewTextView().
SetWordWrap(true).
SetText("âŠ")
SetScrollable(true)
textView.SetInputCapture((&bind.KeyBindings{}).
Bind0(bind.KeySequence('q'), app.Stop).
Bind1(bind.KeySequence('g', 'g'), func(*tcell.EventKey) *tcell.EventKey {
return tcell.NewEventKey(tcell.KeyHome, 0, tcell.ModNone)
}).
Capture)
I need to sleep on this some more.
Also, writing very long messages like this one is really not all that fun in ttâs editor. I should absolutely provide a way to shell out to vim.
(Took me about one and a half hours to compose, holy crap. But not only because of not using vim. Although, that might have saved me a quarter hour or so for sure. Proof-reading this message also uncovered quite a few bugs in my real documentation. So, thatâs a big win!) Good night!
@david@daiwei.me The one with www is correct: https://www.uninformativ.de/twtxt.txt is the canonical URL used in the url = metadata field. (For historical reasons, it also works without www and even with http.)
@balloonfu-sen@yarn.girlonthemoon.xyz Such tilde(s), etc, could in theory just run a twtd instance per user, or if I was convinced enough to make twtd also multi-user capable (optionally) that would also work. But many ~tilde(s) barely implement the Twtxt specs we continue to build and improve (albiet slowly and carefully).
@balloonfu-sen@yarn.girlonthemoon.xyz That should work. LMK if you run into any issues!
@david@daiwei.me Ta, I continued my fun with studying the tcell and cbind code bases for key bindings. My plan is to eventually not only support custom key bindings in the tt configuration file, but also to enable multi-key sequences, such as gg to jump to the top of a list/tree. Or use other vim-like navigation movements like 7j or 25gg etc.
And it turns out there are only a hand full oft tcell/cbind version combinations that work together. Only if all stars align, thereâs chance of success. I will probably end up pulling cbind in to simplify my life. There are situations where tcell.EventKeyâs triple of key, modifiers and rune are not all that intuitive to me. Letâs see.
@bender@twtxt.net All the other ones worked but this broke? Whatâs different here? To which twt hash should this be a reply? đ€
Friday, my love, we meet again. I am going to take you to lunch, and pamper you. I will led you to believe you are the only one in my life, but then, as the working day sunsets, I shall leave you at the door, like a stood up girl by her prom date.
Weekend babies, here we come! đ
@movq@www.uninformativ.de tell me about it! I try to enjoy the time I have available, regardless of being working time, or not. I admit it is quite hard!
@aelaraji@aelaraji.com At least your feed works as well your avatar đ
@arne@uplegger.eu You have Matrix at work? No Teams, Google Chat, Slack, Discord, whatever, but Matrix? Really? Where do you work, is this Socialist Russia?!
@aelaraji@aelaraji.com At work we used to have XMPP/Jabber Chat-Clients but now they are obsolete, due to the introduction of Matrix.
@movq@www.uninformativ.de There is nothing like that on Linux, because you donât need it. Everything just works!
FYi đ Iâm aware of an optimist precomputed hashing bug on the new twtxt.app đ€Ż Trying to work with @bender@twtxt.net remotely on my vacation yo fix it đ€Ł
Okay, wow. Windows NT 4 wasnât part of my timeline back then, so this is the first time Iâm seeing it in action. And this thing came with IE 2, which Iâve also never seen before. (Thatâs interesting, because I remember using IE even on Win 3.x, but apparently that was already IE 3?)
It also makes me really happy to see my website work in these old browsers. Fullscreen images are âbrokenâ because those are PNG or WebP, but the rest works just fine. đ„ł
I am watching Zatoichi the blind swordsman today. I also have a mountain of clothes to fold. Then work comes tomorrow. đ
@david@raw.githubusercontent.com your fork worked, and this is a fork, of your fork. Letâs forkâem!
Hello everyone ! đ Behold I bring you (after many years) the launch of the Twtxt App đ â Ye, this is a Desktop and Mobile app built as a Progressive Web App (PWA) using a little framework (Swag) I put together iafter some experiments @xuu@txt.sour.is and I did in Go and HTMX and Service Workers.
The App is offline-first and supports installing to Desktop and Mobile (add to Home screen) and supports a number of publishing backends, including Yarn.socialâs yarnd Pod, Github, Codeberg/Gitea, and a little tiny twtd Twtxt server (See: https://git.mills.io/yarnsocial/twtd).
Please try it out, no need for any account(s) or such, works with your existing feed(s) (as long as the publishing backends work well enough for you!). Please give me feedback! đ
Also, did you know the Twtxt Search Engine is back? đ
@arne@uplegger.eu Well, it works, I think. đ
@arne@uplegger.eu Foo, bar, and baz! Does it work? Is the houseplant happy?
Test! It works now.
The mentioned go.{mod,sum} change is already part of tview 0.42.0. After implementing Set/GetDisabled(âŠ) and PasteHandler(), tt starts up fine and seems to work without issues.
@movq@www.uninformativ.de Lucky you! My damn work laptop heated up this room to 29°C. The hottest so far.
Other than the few Unicode issues I mentioned recently, vim-classic works just fine. I completely forgot that I switched to it.
The firefly season is ending. I only saw 200 of them or so. There was one female directly on the forest road. If only I brought my camera and tripod, that would have worked out I reckon. I had my torch with me and this looked really cool.
Dusk took forever today. It was really long light out there. Full moon is tomorrow.
On the way back, there was suddenly a load clatter and crashing sound 100 meters away from me. I didnât see anything, but a tree fell over in the forest out of the blue. Fuck me dead, that was scary as hell. Luckily, I was already on the main road, only meadows around me. Itâs the second time I witnessed a tree accidentally coming down. The first one was during the most expensive hail storm in our area so far in 2011 behind me when setting up a summer camp. The weather changed in less than 15 minutes.
Maybe not such a good idea to go out so late alone. :-? Any rustling in the forest immediately reminded me of the boar the other day. Luckily, always false alarm. Still a bit terrified from that event.
So I decided to change tact a bit with GoNIX and instead of trying to build apure Go browser from scratch (which I kinda of half succeeded, in at least it was able to render most static ssr sites), Iâve instead decided to write a new browsered using the Chromium Embedded Framework, otherwise known as CEF. So now I have a fully working browser in GoNIX đ â However since my goal is to keep GoNIX pretty lcean and mostly written in Go, I delegated the cef part(s) to an OCI container image and run that with GoNIXâs box (command-line container runtime). It works great đ
@movq@www.uninformativ.de Yes, thatâs what I was thinking, too. For a moment, I wanted to suggest to use <ol> instead of <ul> to fix that. However, thatâs only gonna work for the first level, but subsections then miss their parent level.
And it turns out that I was wrong. At least sort of. There are some CSS tricks to fix it: https://stackoverflow.com/a/26243681 Of course, with text or retro browsers, this is not gonna fly.
I also came across this interesting article. I just skimmed it and itâs about real tables of contents with page numbers, so not what you have in mind, but cool nevertheless: https://css-tricks.com/a-perfect-table-of-contents-with-html-css/
@movq@www.uninformativ.de Itâs working fine. I can still read your messages. :-)
So Iâve been working on GoNIX the last few days⊠Which is derived from ”Linux â At least itâs entire build process. GoNIX however has a 100% Go userland, including the init process, package and service management.
Now⊠As an experiment, because I was able to make much process on enhancing the build tools and package management, I decided to see if I could build a âDesktopâ Gui of sortsâŠ
I still wanted it to be fairly minimal and lightweight. So I went with wayland (of course) and labwc and yambar. So far Iâm liking the result đ 42 packages in the wayland-desktop meta port. Not too bad. Not sure if I can slim that down anymore⊠But trying to avoid Mesa/GL as that drags in far too much âcruftâ.
@movq@www.uninformativ.de Haha, thanks! :-D Some deliberately crude GIMP work.
@movq@www.uninformativ.de Yeah, the damn message to urge me into updating for no reason. It still works fine, why update then!? Leave me alone. If downloading fails, thereâs already a hint that updating might fix it. The introduction of this banner in https://github.com/yt-dlp/yt-dlp/pull/13937 doesnât give any reason for that change either.
Whatâs your motivation for running this, btw? đ€
Basically, two things a) feeling generous for folks that either canât afford or find it hard to have a little place to call home (webpage, feed, whatever) and b) a real opportunity to test some of the components that make it possible sshbox, which I know works well as it fronts my Gitea instanceâs Git+SSH service and box, a container runtime I wrote a while ago, recently improved, hardened and polished.
@movq@www.uninformativ.de Thatâs right, way harder than centrally managed. They even didnât reach concensus over the main folder: âAlle Programme, âAlle Programme (x86)â, âAll Programsâ, âAll Programmesâ, etc. Anyway.
For class 11 (or maybe already in 10, I donât remember exactly) we could choose either between traditional maths class with a graphical calculator or âMathe mit CASâ. There were two teachers in my entire school who were able to teach the latter. It was also fairly new at the time I believe. Certainly unheard of for a âallgemeinbildendes Gymnasiumâ, maybe the technical ones were already offering it for some time, not sure. It was clear to me that I would take the maths with CAS class.
Each kid had to buy their own Cassiopeia A-Something. I donât know how much that thing was (definitely more expensive than a graphical calculator) and whether the school subsidized that in any form. But it was slow and underpowered as hell. We rarely used it in class nor for homework (most if not all had already a desktop at home). Typically, when we worked with the CAS, we sat down on the desktop computers. Our class took place in one of the two computer rooms. The desktops were placed on the three sides (left, right, back, facing the walls or windows) and the regular school desks were in the middle. Since there were more pupils than desktops, we always shared. Nowadays, we call it pair programming. ;-)
For the exams we had the âmandatory partâ (Pflichtteil) without any tools. Once we finished that and handed the papers to our teacher, we were then allowed to boot up our Cassiopeias and work with them for the second part. Before the exam started, everyone had to show the teacher that they reset their small computer to factory settings. This second part was called âWahlteilâ. But you had to do it in order to pass. So, I never understood the choice of this term. Maybe itâs because the first part is the exact same for everyone (graphical calculator and CAS class), but the second part was definitely different for the two classes. Each suited to their tools.
After one or two exams, it became clear that the Cassiopeia was far from ideal. So, we took the second part at the desktop computers from then on. Our teacher unplugged the network cables himself to avoid cheating. Each computer had an âHDD Sheriffâ running that reset the disk at startup. There was also an issue that the personal user accounts were affected by that. Sometimes all your data were lost. If you were lucky, they were still there. So, we saved our Maple project to local disk (if the computer didnât crash in between, that was no problem) and at least eventually before leaving the classroom, we then also saved it on the server. For that, the teacher quickly plugged in the cable, we saved, and then the cable was unplugged again immediately. Oh, and everybody used their USB sticks, too.
All in all, this Cassiopeia A-* was quite a useless purchase. :-D Iâm not sure if I still have it. At least I thought several times about giving it to the flea market. Donât know if I did or not.
@lyse@lyse.isobeef.org Ah, you mean the categorization. Yeah, that would never work in Windows, at least not without having a centralized package manager (so thereâs one authoritative source of which program belongs into which category).
Oh wow, those Cassiopeias look pretty cool. Did you have one of those or one for each kid?
@lyse@lyse.isobeef.org That, uh ⊠yeah, that would work as well. đ đ€Šââïž
@lyse@lyse.isobeef.org Interesting approach. đ€
The master branch should never be in a broken state (apart from bugs I donât know about). Any intermediate state during the development of a larger feature will happen in a different branch.
I mean, yeah, but ⊠I donât know, I like having âtraditional releasesâ as a second safety net when I write programs. I like to let things mature for a while and then I cut a new release. So itâs, like, âwe have a bunch of new features and fixes here, and to the best of my knowledge this works fine nowâ. But maybe Iâm just paranoid. đ€
In Venezuela, a 91-Year-Old Weaver Sticks to Traditions
Though electric machines are now standard, the Venezuelan weaver Margarita Mora has clung to a mix of ancestral Indigenous and Spanish practices to create surprisingly modern work. â Read more
tt. But then, in the message tree, I spot another missed typo. My process is then to go to my twtxt.txt and fix it by hand. However, I still have to clean up tt's cache. This is rather tidious:
@movq@www.uninformativ.de Thank you very much! So, the concept is very similar. The root widget gets the input and can pass it to whatever child has the focus and so on.
My two main issues are the API design, that the input handler sometimes get an additional callback to notify the application about which element is focused, but sometimes not. And that focus switching sometimes just does not work as expected. Anyway.
As for rendering the selected button, I was also thinking about indicating it with some kind of border around it, square brackets seem to be a wonderful choice. :-)
In Venezuela, a 91-Year-Old Weaver Sticks to Traditions
Though electric machines are now standard, the Venezuelan weaver Margarita Mora has clung to a mix of ancestral Indigenous and Spanish practices to create surprisingly modern work. â Read more
Drone ban lifted at Coogee Beach after woman mauled by shark
The government will work with the Civil Aviation Safety Authority and Surf Life Saving NSW to make the exemption permanent. â Read more
âSports guyâ Trump works to project strength with UFC bout as political woes mount
Trump will celebrate becoming an octogenarian as he hosts an extravagant UFC showcase on the White House South Lawn on Sunday night. â Read more
Drone ban lifted at Coogee Beach after woman mauled by shark
The government will work with the Civil Aviation Safety Authority and Surf Lifesaving NSW to make the exemption permanent. â Read more
@itsericwoodward@itsericwoodward.com Why hear? Iâll just put it up at https://twtxt.app now shall I? Itâs good enough IMO that itâs already working quite well. The challenging parts now is to figure out a good set of default publishing connectors to support? đ€
tt. But then, in the message tree, I spot another missed typo. My process is then to go to my twtxt.txt and fix it by hand. However, I still have to clean up tt's cache. This is rather tidious:
With multicolored TUIs, I find it usually hard to immediately tell which button is selected if there are just two.
Indeed, I wouldnât be able to tell in that example, either. movwin works around that by (mostly) assuming that there is no support for colors at all, so there should always be a way to tell which widget has focus, even without colors. Thatâs why it puts brackets around a buttonâs label when focused:
The fewer colors you use, the better, I guess. đ€
tt. But then, in the message tree, I spot another missed typo. My process is then to go to my twtxt.txt and fix it by hand. However, I still have to clean up tt's cache. This is rather tidious:
Now Iâm curious how movwin deals with that. ;-)
Focus handling? I hardly remember, lol. đ Did that 6 months ago and havenât touched it since. Letâs see.
The core main loop gets keyboard/mouse events from curses. At this level, the main loop only knows about exactly one widget, so it passes the event to that widget (whatever that is, doesnât matter â they all inherit from the Widget base class, it could be a Window, a WindowManager, or an Edit box directly).
The outermost widget is usually a WindowManager. It implements a few hotkeys of its own, like switching to another window. If none of those hotkeys match, it passes the event to the currently focused window.
Same story here: Window implements some hotkeys (like opening the menu bar). If none of those match, then ⊠the magic happens.
Each Window acts as a focus manager. It can descend into its child widget hierarchy and collect all child widgets in a depth-first search. They are collected into a flat list. Each Window then has an attribute _focus_position, which is an index into that list. Pressing Tab or Shift+Tab increases or decreases that index and that allows you to select the next/previous focusable widget in the current window.
Eventually, Window passes the input event to the currently focused widget.
Usually on initialization, the application can ask a Window object to focus a certain widget. The file selection dialog does that, for example, because the ânaturalâ focus order would be to focus the Edit box at the top of the window first â but thatâs not what the user wants, the Table showing the list of files should be focused.
If no widget ever feels responsible for handling a certain input event, then thereâs a global unhandled_input callback that the application can provide (same as in urwid).
I think thatâs it.
Hm, thatâs more complicated than I remembered, but apparently it works fine, because I completely forgot about this. đ
All I did in the last few months was make new classes that inherit from Widget, like the new Table class or Edit or HexEdit or whatever, and if they want to get input events, then they must implement the methods input_key() or input_mouse().
Does this answer your question? đ (I admit that I didnât exactly understand your scenario, so I just went ahead and rambled about my implementation. đ )
tt. But then, in the message tree, I spot another missed typo. My process is then to go to my twtxt.txt and fix it by hand. However, I still have to clean up tt's cache. This is rather tidious:
Getting the vim key bindings to work for focus switching in this modal dialog took me forever. Only cursors and (Shift+)Tab are supported out of the box. I absolutely understand that, itâs fine. I installed an input handler on the dialog, but the focus always stayed the same.
After two wasted hours, I was in despair to copy the tview.Modal into my own code base. Of course, I had to fix all the private tview field accesses first. But even installing the input handler directly on the buttons themselves did not work. Even though, the handler was definitely executed, the focus did not shift. Forcing redraws as a last resort also did not work.
Looking through all the messy chained input handling, I eventually stumbled across another place in the tview.Form, which is internally used by tview.Modal. This messed around with app focus receptions and input handlers. This gave me the idea to make the tview.Application refocus my modal dialog after I told the modal dialog which button to select. And would you look at that, this did the trick! I havenât completely figured out what is going on exactly, but I could get rid of my Modal clone again.
I always go through hell with focus handling in tview. Each and every time. It just does not feel natural to me. Complete brainfuck to wrap my head around. The Urwid API felt sooo much more refined, it never was an issue. It just works. In fact, I cannot think of any other TUI library that has remotely the same pain level when it comes to focusing widgets as tview.
Now Iâm curious how movwin deals with that. ;-)
@movq@www.uninformativ.de Right, at work, nobody gives a fuck. At all. There are so many universes between my definition of quality and everybody elseâs.
Letâs stop here and enjoy the weekend or vacation. :-)
@movq@www.uninformativ.de Just working on swag đ AndâŠ.. Building an Offline-first Yarn/twtxt client that has no server requirements (_other than you need to publish your feed somewhereâŠ)