Happy New Year (2026) 🥳
Hurray, I finally fixed another rendering bug in tt that was bugging me for a long time. Previously, when there were empty lines in a markdown multiline code block, the background color of the code block had not been used for the empty lines. So, this then looked as if there were actually several code blocks instead of a single one.
https://lyse.isobeef.org/tmp/tt-bugfix-empty-lines-in-multiline-code-blocks.png
@movq@www.uninformativ.de Because they’re just boxes. :-D
Why have these Unicode smilies never caught on, I wonder? 🤪
@movq@www.uninformativ.de Yeah, I see. Just crudely checked on my computer, with around 0.013 seconds, Python 2.7 seems a tad faster than Python 3.14’s 0.023 seconds in this little program.
The lazy imports sound not too bad, but I just skimmed over them. There are surprisingly many exceptions, but yeah, no way around them. :-)
mu (µ) now has builtin code formatting and linting tools, making µ far more useful and useable as a general purpose programming language. Mu now includes:
- An interpreter for quick “scriptinog”
- A native code compiler for building native executables (Darwin / macOS only for now)
- A builtin set of developer tools, currently: fmt (-fmt), check (-check) and test (-test).
@movq@www.uninformativ.de Mu (µ)’s startup latency appears to be ~10ms on my machine:
$ time ./bin/mu ./foo.mu
real 0m0.011s
user 0m0.004s
sys 0m0.006s
The baseline here is about 55 ms for nothing, btw. Python ain’t fast to start up.
$ time python -c 'exit(0)'
real 0m0.055s
user 0m0.046s
sys 0m0.007s
I assume you made the thing load quickly, didn’t you?
That’s the problem with Python. If you have a couple of files to import, it will take time.
I want this to be reasonably fast on my old Intel NUC from 2016 (Celeron N3050 @ 1.60GHz) and I already notice that the program startup takes about 95 ms (or 125 ms when there are no .pyc files yet). That’s still fine, but it shows that I’ll have to be careful and keep this thing very small …
Python 3.14 will bring lazy imports, maybe that can help in some cases.
@movq@www.uninformativ.de That’s cool! I also like the name of your library. :-) I assume you made the thing load quickly, didn’t you?
@prologic@twtxt.net No, that’s Python/curses on Linux. 😅
@movq@www.uninformativ.de Is this on yout little toy OS? 🤔
Well, you girls and guys are making cool things, and I have some progress to show as well. 😅
https://movq.de/v/c0408a80b1/movwin.mp4
Scrolling widgets appears to work now. This is (mostly) Unicode-aware: Note how emojis like “😅” are double-width “characters” and the widget system knows this. It doesn’t try to place a “😅” in a location where there’s only one cell available.
Same goes for that weird “ä” thingie, which is actually “a” followed by U+0308 (a combining diacritic). Python itself thinks of this as two “characters”, but they only occupy one cell on the screen. (Assuming your terminal supports this …)
This library does the heavy Unicode lifting: https://github.com/jquast/wcwidth (Take a look at its implementation to learn how horrible Unicode and human languages are.)
The program itself looks like this, it’s a proper widget hierarchy:
https://movq.de/v/1d155106e2/s.png
(There is no input handling yet, hence some things are hardwired for the moment.)
I just fixed another bug in tt where the language hint in multiline markdown code blocks had not been stripped before rendering. It just looked like it was part of the actual code, which was ugly. I now throw it away. Actually, it’s already extracted into the data model for possible future syntax highlighting.
Phew, it was just a one-time thing. Ta! :-)
Btw, @shinyoukai@neko.laidback.moe, that’s a super cool logo on your yarnd. I like it a lot!
It just doesn’t look aligned properly: https://lyse.isobeef.org/tmp/misalignment.png Could be a yarnd issue, though, it might not expect a logo this large. Just wildguessing, no idea.
git add everything!? Is it not enough for the file(s) to be already checked in from the get go?
@shinyoukai@neko.laidback.moe Because you might not want to commit all changed files in a single commit. I very often make use of this and create several commits. In fact, I like to git add --patch to interactively select which parts of a file go in the next commit. This happens most likely when refactoring during a feature implementation or bug fix. I couldn’t live without that anymore. :-)
If you have a much more organized way of working where this does not come up, you can just git commit --all to include all changed files in the next commit without git adding them first. But new files still have to be git added manually once.
@shinyoukai@neko.laidback.moe Do we now need ad filters in twtxt clients, too? O_o I hope not! Personally, I cannot stand the “Sent with my crappy $phone/$app” e-mail footers.
But congrats on your client. :-)
Why the hell do I have to git add everything!? Is it not enough for the file(s) to be already checked in from the get go?
Git = G(od damn)it
os.UserConfigDir() up until a few seconds ago! I always implemented that myself.
@shinyoukai@neko.laidback.moe Yeah, they don’t truly support XDG. In fact, I looked in the Go stdlib source code to notice all the differences and shortcomings.
os.UserCacheDir(), it seems that the Go devs hasn't acknowledged the $XDG_DATA_DIR yet
@lyse@lyse.isobeef.org You could always take a peek at the Go source
Posted from mikuru/0.0.3 @ NetBSD amd64
os.UserConfigDir() up until a few seconds ago! I always implemented that myself.
@lyse@lyse.isobeef.org the funny thing about it? There’s os.UserCacheDir(), it seems that the Go devs hasn’t acknowledged the $XDG_DATA_DIR yet
$HOME is not specified it tries to resolve the user's home directory by user.Current().HomeDir. Maybe that's overkill, I have to check the XDG spec.
Ok, the standard library implementation is wonky at best, at least in regards to XDG, because it really doesn’t implement it properly. https://github.com/golang/go/issues/62382 I stick to my own code then. It doesn’t properly support anything else than Linux or Unixes that use XDG, but personally, I don’t care about them anyway. And the cross-platform situation is a giant mess. Unsurprisingly.
os.UserConfigDir() up until a few seconds ago! I always implemented that myself.
Hmm, mine also resolves a leading tilde in these variables. And if $HOME is not specified it tries to resolve the user’s home directory by user.Current().HomeDir. Maybe that’s overkill, I have to check the XDG spec.
But I’m definitely missing os.UserDataDir(). That’s a bummer.
@shinyoukai@neko.laidback.moe Cool, I didn’t know about os.UserConfigDir() up until a few seconds ago! I always implemented that myself.
@movq@www.uninformativ.de Thanks! I’ll have a look at SnipMate. Currently, I’m (mis)using the abbreviation mechanism to expand a code snippet inplace, e.g.
autocmd FileType go inoreab <buffer> testfunc func Test(t *testing.T) {<CR>}<ESC>k0wwi
or this monstrosity:
autocmd FileType go inoreab <buffer> tabletest for _, tt := range []struct {<CR> name string<CR><CR><BS>}{<CR> {<CR> name: "",<CR><BS>},<CR><BS>} {<CR> t.Run(tt.name, func(t *testing.T) {<CR><CR>})<CR><BS>}<ESC>9ki<TAB>
But this of course has the disadvantage that I still have to remove the last space or tab to trigger the expansion by hand again. It’s a bit annoying, but better than typing it out by hand.
Oh, suddenly Mother Hulda dumped a centimeter of snow tonight! https://lyse.isobeef.org/schnee-2025-12-30/01.jpg
Magpie from the day before yesterday: https://lyse.isobeef.org/elster-2025-12-28/
@lyse@lyse.isobeef.org Well, I used SnipMate years ago (until 2012). IIRC, it’s more than just “insert a bit of text here”, it can also jump to the correct next location(s) and stuff like that. Don’t remember why I stopped using it.
Then I used nothing for a long time. Just before Christmas, I made my own plugin (… of course …), which does everything I need at the moment (and nothing more).
It can insert simple templates and then jump to the next location:
https://movq.de/v/67cdf7c827/sisni%2Dpython.mp4
And replace a string after insertion:
https://movq.de/v/67cdf7c827/sisni%2Dheader.mp4
(It’s not public (yet?) and it also uses vim9script, so I guess it wouldn’t work on your system.)
Everything about the future is classified information
Question to my fellow Vimers: Which snippet insertion mechanism are you using or can you (not) recommend?
Pro tip: Don’t keep the christmas biscuits close to the bird fat balls. I nearly mixed up the bags. :-D
lldb or gdb 😂
@prologic@twtxt.net Debugging this stuff on bare metal hardware (without an underlying OS) is a nightmare. 🤣
@movq@www.uninformativ.de Yeah. I had that in my Python implementation and was really missing that.
@movq@www.uninformativ.de I see. Yeah, all the Unicode stuff certainly doesn’t help here, that’s for sure.
Maybe “speedcurses” could be a name. Or just select any Palatinate curse. ;-)
lldb or gdb 😂
@prologic@twtxt.net Oh yeah, I bet it is horrible to troubleshoot.
tt URLs View now automatically selects the first URL that I probably are going to open. In decreasing order, the URL types are:
@lyse@lyse.isobeef.org That sounds useful. 🤔
This was the scariest movie I’ve seen in a long time, jesus. 🤣 https://en.wikipedia.org/wiki/Fall_(2022_film)
@lyse@lyse.isobeef.org I’m toying with the idea of making a widget/window system on top of Python’s ncurses. I’ve never really been happy with the existing ones (like urwid, textual, pytermgui, …). I mean, they’re not horrible, it’s mostly the performance that’s bugging me – I don’t want to wait an entire second for a terminal program to start up.
Not sure if I’ll actually see it through, though. Unicode makes this kind of thing extremely hard. 🫤
pwgen --no-capitalize --no-numerals 5 and since that already showed up in DDG search results, I simply appended the last two, which yielded nothing on DDG and Google).
@lyse@lyse.isobeef.org Bwahaha. 🤣
@lyse@lyse.isobeef.org I can tell you this right now, writing assembly / machine code is fucking hard work™ 😓 I’m sure @movq@www.uninformativ.de can affirm 🤣 And when it all goes to shit™ (which it does often), man is debugging fucking hard as hell! Without debug symbols I can’t use the regular tools like lldb or gdb 😂
@prologic@twtxt.net Yeah, the parser part is what I typically enjoy. Haven’t really looked into code generation itself.
I’m currently looking at your µ commits from the last few days. Holy cow! :-)
println(1, 2) was bring printed as 1 2 in the bytecode VM and 1 nil when natively compiled to machine code on macOS. In the end it turned out the machine code being generated / emitted meant that the list pointers for the rest... of the variadic arguments was being slot into a register that was being clobbered by the mu_retain and mu_release calls and effectively getting freed up on first use by the RC (reference counting) garbage collector 🤦♂️
@lyse@lyse.isobeef.org Yeah I remember you said some days back that your interest in compilers was rekindled by my work on mu (µ) 😅
pwgen --no-capitalize --no-numerals 5 and since that already showed up in DDG search results, I simply appended the last two, which yielded nothing on DDG and Google).
Dang it, there’s a Swede by the username of Quongsi: https://www.flashback.org/u1404408 :-D
println(1, 2) was bring printed as 1 2 in the bytecode VM and 1 nil when natively compiled to machine code on macOS. In the end it turned out the machine code being generated / emitted meant that the list pointers for the rest... of the variadic arguments was being slot into a register that was being clobbered by the mu_retain and mu_release calls and effectively getting freed up on first use by the RC (reference counting) garbage collector 🤦♂️
@prologic@twtxt.net Tada, congratulations! I find that rather interesting, thanks for telling us. :-)
@movq@www.uninformativ.de How about “Quongsi”? I generated the first five letters with pwgen --no-capitalize --no-numerals 5 and since that already showed up in DDG search results, I simply appended the last two, which yielded nothing on DDG and Google).
What kind of project is it? Maybe we can help you find a name or nudge you in the right direction.
The tt URLs View now automatically selects the first URL that I probably are going to open. In decreasing order, the URL types are:
- markdown media URLs (images, videos, etc.)
- markdown or plaintext URLs
- subjects
- mentions
I might differentiate between mentions of subscribed and unsubscribed feeds in the future. The odds of opening a new feed over an already existing one are higher.
Whoo! I fixed one of the hardest bugs in mu (µ) I think I’ve had to figure out. Took me several days in fact to figure it out. The basic problem was, println(1, 2) was bring printed as 1 2 in the bytecode VM and 1 nil when natively compiled to machine code on macOS. In the end it turned out the machine code being generated / emitted meant that the list pointers for the rest... of the variadic arguments was being slot into a register that was being clobbered by the mu_retain and mu_release calls and effectively getting freed up on first use by the RC (reference counting) garbage collector 🤦♂️
@lyse@lyse.isobeef.org True !
@prologic@twtxt.net In my opinion, the integrity isn’t lost. The same input data always result in the same output hash, no matter when you calculate the hashes. It’s true that a corrupt database contents yields to corrupt hashes, but then you have a whole bigger problem than just receiving different hashes. :-D