Searching txt.sour.is

Twts matching #work
Sort by: Newest, Oldest, Most Relevant
In-reply-to » I've been away with the scouts in our district summer camp. The nearly two weeks were absolutely amazing, mentally a great vacation. On the other hand, physically not so much. But I've still got Monday to recover from my holiday. :-)

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/

​ Read More
In-reply-to » I've been away with the scouts in our district summer camp. The nearly two weeks were absolutely amazing, mentally a great vacation. On the other hand, physically not so much. But I've still got Monday to recover from my holiday. :-)

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/

​ Read More
In-reply-to » @itsericwoodward Not really no đŸ€Ł Did you want to join us and setup your own instance and join the growing aprty? It's turning out to be quie neat actually 😅

@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). đŸ€ž

​ Read More

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:

​ Read More
In-reply-to » Does anyone have time this weekend to manually test and validate and prove out this spec I'm calling Gitxt? A Twtxt-inspired purely decentralised Git federation/forge? đŸ€” Hit me up! You need only 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 đŸ€·â€â™‚ïž đŸ€Ł

​ Read More

“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?

​ Read More

“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?

​ Read More

“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?

​ Read More
In-reply-to » @prologic Hmm. đŸ€”

@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 😅

​ Read More
In-reply-to » @prologic Hmm. đŸ€”

@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.

​ Read More

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.

​ Read More
In-reply-to » 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.

@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. ;-)

​ Read More

Started doing “Fraktur Freitag” last week on Mastodon, and why not post it here as well. (“Blackletter Friday”? Doesn’t work in English. đŸ€Ș)

Image

Image

I want to make this a weekly thing, but I obviously cannot guarantee it. 😅

​ Read More

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.

https://lyse.isobeef.org/waldspaziergang-2026-08-27/

​ Read More

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

​ Read More

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

​ Read More
In-reply-to » @lyse Huh, didn’t expect that. :-D

@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!

​ Read More
In-reply-to » @lyse I take it you also know their acoustic album “Visor om Slutet”? I love that one. 😍

@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.

​ Read More

@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.

​ Read More
In-reply-to » 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:

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).

​ Read More

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()

​ Read More
In-reply-to » The author of the Xfce Wayland compositor on LLMs:

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.

​ Read More

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:

Image

This is the creepiest shit ever. Silently “fixing” stuff behind my back is the epitome of untrustworthiness.

Open the bay doors, HAL.

​ Read More

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


​ Read More

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? 💡

​ Read More

@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.

​ Read More
In-reply-to » I finally built a prototype of a marking gauge with a cutter wheel out of some scraps.

@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.

​ Read More

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:

Image

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. :-)

​ Read More

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.

https://git.mills.io/prologic/muos

​ Read More
In-reply-to » I’m seeing some slowdowns in Vim lately. Must have something to do with syntax highlighting or indentation rules or something: When I hit Enter to go to the next line, it sometimes freezes for like 100 ms. It’s pretty annoying.

@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.)

​ Read More

@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

​ Read More
In-reply-to » @prologic Hmmm, I have no idea how to solve that problem. 😅 Some 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.

​ Read More
In-reply-to » Okay, so, my website also includes my code / git repos, and those are made browsable by stagit. What I don’t like about this (these days) is that this includes all the diffs of my commits. In other words: All my code.

@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.

​ Read More

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.

​ Read More
In-reply-to » I should really fix this damn bug where new replies to read replies to unknown conversation roots are not showing up in 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.

​ Read More

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 đŸ€Ł

​ Read More

@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.

​ Read More

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.

​ Read More

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.

​ Read More

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.

​ Read More

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!

​ Read More

@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.

​ Read More

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! 😂

​ Read More
In-reply-to » Anyone using XMPP? I've been hearing a lot about how it is the OG messaging protocol. That G00gle Talk used to use it as a back-end, that FB messanger and w_hatsapp use some modified version of it or something; And that setting up a server (or even using a public one) would be a better alternative to the aforementioned apps, so I did. Now the question is: "Where the Fu__ are my video calls at!!? đŸ€Ł" ... The protocol supports videoconferencing and I'm yet to find a decent Desktop/Mobile client that implements it. I wish I knew enough Code-Fu to contribute/help implement some, somewhere.

@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?!

​ Read More
In-reply-to » Anyone using XMPP? I've been hearing a lot about how it is the OG messaging protocol. That G00gle Talk used to use it as a back-end, that FB messanger and w_hatsapp use some modified version of it or something; And that setting up a server (or even using a public one) would be a better alternative to the aforementioned apps, so I did. Now the question is: "Where the Fu__ are my video calls at!!? đŸ€Ł" ... The protocol supports videoconferencing and I'm yet to find a decent Desktop/Mobile client that implements it. I wish I knew enough Code-Fu to contribute/help implement some, somewhere.

@aelaraji@aelaraji.com At work we used to have XMPP/Jabber Chat-Clients but now they are obsolete, due to the introduction of Matrix.

​ Read More

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. đŸ„ł

https://movq.de/v/56243a3e54

​ Read More

I am watching Zatoichi the blind swordsman today. I also have a mountain of clothes to fold. Then work comes tomorrow. 😅

​ Read More

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? 🎉

​ Read More
In-reply-to » Fuck me! I tried to upgrade tview and the first thing I notice is a shitload of added dependency versions:

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.

​ Read More
In-reply-to » I went to check on the fireflies this season. But I didn't see any. Instead lots of moths. At first, I thought it might have been still too light, but it was already dark enough for me to miss and destroy a snail shell. Bummer. Maybe it was too wet tonight. Although, it's probably just another or two weeks until my glowing friends will finally show up.

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.

​ Read More

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 👍

​ Read More
In-reply-to » @lyse Besides, have a look at https://movq.de/v/cf0903ebc3/numb.png again: When it goes from item 9 to item 10, the indentation of the text (after the number) changes. Pretty ugly. In other words, a table of contents should be a table, not a list like it is at the moment. And that would require me to write my own extension for python-markdown 
 Probably not worth it.

@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/

​ Read More

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”.

​ Read More
In-reply-to » @lyse Okay, wait, what is the anti-feature here? The nag screen because it’s “old”? The inability to update when run from source? đŸ€”

@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.

​ Read More
In-reply-to » Behold, I bring you (reincarnated) mbox.blue -- A tiny shared linux server based on / around containers (my own implemtnation).

@movq@www.uninformativ.de

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.

​ Read More
In-reply-to » @lyse 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).

@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.

​ Read More
In-reply-to » @lyse In what way was KDE 3’s menu organized? KDE 1 is the only KDE version I ever used. 😅 We’re talking about this one, right?

@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?

​ Read More
In-reply-to » @lyse Is it this one? https://github.com/rivo/tview It’s almost 10 years old but hasn’t seen a 1.0.0 release yet? đŸ€”

@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. đŸ€”

​ Read More
In-reply-to » Every now and then, I think that I have carefully proof-read my message enough times and hit the "Add message" button in 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. :-)

​ Read More
In-reply-to » Every now and then, I think that I have carefully proof-read my message enough times and hit the "Add message" button in 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:

@lyse@lyse.isobeef.org

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. đŸ€”

​ Read More
In-reply-to » Every now and then, I think that I have carefully proof-read my message enough times and hit the "Add message" button in 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:

@lyse@lyse.isobeef.org

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. 😅)

​ Read More
In-reply-to » Every now and then, I think that I have carefully proof-read my message enough times and hit the "Add message" button in 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. ;-)

​ Read More