Random Stuff

Reading An introduction to homological algebra (1994 book) by Charles A. Weibel.

Playing with the Jane Street ASIC Puzzle.

Playing 蒼の彼方のフォーリズム (2014 visual novel).

Reading 中日交流标准日本语 初级 上 (1988 book).

Watching 転校先の清楚可憐な美少女が、昔男子と思って一緒に遊んだ幼馴染だった件 and ぐらんぶる season 3 (2026 animes).

2026-08-24

I'm surprised I'm surprised streaming music on my phone from my laptop feels so nice. Guess it'd be even better with 9p over TLS (with a client certificate) over SCTP instead of regular HTTPS. Connecting with a (server address, port, certificate; client certificate) quadruple doesn't seem to be a thing in "regular" Web browsers...

2026-08-23

It'd be cool were libavformat called libavmudex.

A pirate website offers some JavaScript to download selected files of an item and save them as a ZIP. The speed meter and progress bars are flaky: despite continuous network traffic, most of the time no speed is shown and progress bars freeze, and sometimes the speeds shown are absurdly fast and progress bars jump wildly. I just looked into it and it's quite simple. Files of moderate size, up to about 400 MB, are cut into 16 equally-sized chunks and downloaded sequentially. When a chunk download is finished, the progress bar and a per-second counter for bytes received is updated. My network is somewhat slow so downloading, say, a 10 MB chunk can take multiple seconds, and the speed meter stays at zero until the download is finished and it goes to 10 MB/s for one second. Worse, larger files are not chunked, so a 600 MB file leads to a 600 MB/s spike in speed and its progress bar is totally useless, only ever being at 0% or 100%.

Another annoying thing is seemingly random CORS failures, which force me to restart these multi-GB downloads. Not enough so to make me write a shell script for it though. It just failed three times in a row so I did a quick Python script to feed URLs into curl — the listing is a JSON tree and I don't know how to make jq recurse with an extra argument (the current prefix).

2026-08-20

Watched Terminator Genisys (2015 film).

2026-08-19

TIL using curl's --parallel with --fail-early terminates partial downloads on errors, including those specified before the failing one. See also. The story: I needed to download some sequentially numbered files but didn't know how many, so I fed curl 100 URLs at a time and passed --fail so it treats a 404 as an error, hoping that once it gets a 404 it would stop sending requests, which it did, but it also canceled the other active downloads, which (I think) removed or truncated up to --parallel-max files. Now I must clean up this mess, and I cannot quite automate it because intermittent network conditions... Not fun.

2026-08-17

This is ridiculous.

# from traffic log
content-signature-2.cdn.mozilla.net
firefox-settings-attachments.cdn.mozilla.net
firefox.settings.services.mozilla.com
push.services.mozilla.com

Why the split between mozilla.com and mozilla.net? Just stick with one maybe? (I know I could disable them. Also, that page has less text than this one and requires JavaScript for some reason.)

2026-08-16

Watched The Internship (2013 film). Only realized that sqrt(17) isn't anywhere close to 4.23 when I went to get some water; guess I'll be like that when drunk too. Nice comedy if you can stand the bullshit, only not enough fighting in that dance club.

Also, the credits comes in some interesting font...

2026-08-12

Here's a way to lazy-load images by (not quite) abusing <details>:

<style>
._0812 {
    details { margin: 1em 0; }
    details[open] summary { display: none; }
    summary, img {
        display: block;
        margin: auto;
        width: min(80%, 80vh * var(--r));
        aspect-ratio: var(--r);

        background: #eee;
        text-align: center;
        align-content: center;
    }
}
</style>
<div class="_0812">
<details style="--r:1280/1073">
<summary>Load image (252K)</summary>
<img loading="lazy" src="hfvomutneputvmmwczla.jpg" alt="sample image">
</details>
</div>

Firefox doesn't currently support typed attr() in CSS so I have to define a CSS variable on <details>. I don't know how to get the largest size given a maximum width, a maximum height, and a fixed aspect ratio, thus the min().

Load image (252K) sample image

Without JavaScript, the image would still load eagerly, for privacy reasons. This construct is not too useful since most probably the user wants to see a scaled-down version first, in which case the "link to full-sized image" idiom is well-established.

Also, don't worry if you don't see the image; I didn't upload it. I don't want to link to another site and can't find a nice image with clear copyright status. Fuck DMCA. It's an Internet meme with SHA-1 9298f0c6f771... though.

2026-08-11

Finished the 鳥沢 みさき plotline, which occupied much of my time awake today. It's much more interesting. The plot is actually quite boring if I think about it, but it's relatable and feels nice for some reason.

Been eating instant Udon for a few nights. Nice alternative to regular instant noodles, but still very unhealthy. There're few if any food shops open this late, let alone affordable ones. I've been thinking "what for", but one has to get by; there's no "pristine state of human nature" to be disrupted by the socio-industrial complex anyway.

2026-08-07

Been playing 蒼の彼方のフォーリズム (2014 visual novel); just finished the 市ノ瀬 莉佳 plotline, despite having tried to enter that of 鳶沢 みさき.

2026-08-06

mailbox (the email service provider) shows a "Spam" and a "Trash" folder in the Web UI, but "Spam" is actually called "Junk": the name shows up in "Settings → Spam and trash → Spam Settings → Spam Emails → Route to". If I put an email in "Junk" in a local maildir and sync via IMAP, it goes in "Spam" in the Web UI; if I put it in "Spam" instead it goes in, well, another "Spam", in "My folders". I guess mailbox can't fix it anymore though.

Just pointing out that some blog post I just read loads about 15 KB of HTML, a 30 KB image, about three times that much CSS, and a 250 KB GitHub avatar that isn't even on the page but a <link rel="preload">. Must be really confident I'd visit the homepage to see that avatar.

2026-08-03

Watched みるタイツ (2019 anime).

My (crappy) PDF viewer depends on MuPDF to actually render PDFs, but it is complex, has lots of dependencies, and deals with images, fonts, and apparently the Internet, so it probably supports Remote Code Execution, so I better sandbox it. Since rendering PDFs is mostly "pure computation", SECCOMP_SET_MODE_STRICT works, but I have to avoid libc's malloc and stdout. (Why would printf call fstat?) fz_new_context reads /etc/localtime for some reason, so it has to go before the Seccomp call, which is weird but fine, since MuPDF's dependencies are initialized outside Seccomp anyway.

#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/seccomp.h>
#include <mupdf/fitz.h>

char data[1<<24], pool[1<<24], *top = pool;

void *mymalloc(void *_, size_t n) { void *t = top; n = (n + 15) & ~15; top += n; return t; }
void *myrealloc(void *_, void *p, size_t n) { void *t = mymalloc(_, n); if (p) memcpy(t, p, n); return t; }
void myfree(void *_, void *p) {}

int main(void) {
    fz_alloc_context actx = { 0, mymalloc, myrealloc, myfree };
    fz_buffer *buf;
    fz_context *ctx;
    fz_document *doc;
    fz_pixmap *pix;
    int size;
    char ihdr[100];

    ctx = fz_new_context(&actx, 0, FZ_STORE_UNLIMITED);
    syscall(SYS_seccomp, SECCOMP_SET_MODE_STRICT, 0, 0);
    fz_register_document_handlers(ctx);
    size = read(0, data, sizeof(data));
    buf = fz_new_buffer_from_shared_data(ctx, data, size);
    doc = fz_open_document_with_buffer(ctx, data, buf);
    pix = fz_new_pixmap_from_page_number(ctx, doc, 0, fz_identity, fz_device_rgb(ctx), 0);
    write(1, ihdr, sprintf(ihdr, "P6\n%d %d\n255\n", pix->w, pix->h));
    write(1, pix->samples, pix->w * pix->h * 3);

    fz_drop_context(ctx);   // I think this does nothing
    syscall(60, 0);
}

I probably should only allow LANDLOCK_ACCESS_FS_READ_FILE before loading MuPDF. I'm not sure if no_new_privs does anything then. (08-06: no_new_privs is required for landlock_restrict_self.)

2026-08-01

Watched Don't Take the Black Pill by Andrew Kelley. I certainly do feel disillusioned, and would go further than "computers were a mistake" to say "life was a mistake". I don't have much hope now that the world is... Well, my favourite websites turn into shit, adopt Cloudflare or Anubis, or get shut down. People lie or bullshit all the time. The Internet is like "the thing that never works but somehow people all depend on". Not a great time to have faith.

Also, I hope I'll watch Matrix again.

I've been neglecting Anki for three weeks. Not good.

2026-07-31

Re-watched ギルティクラウン (2011-2012 anime). Good memories... Hope to watch it again sometime.

2026-07-27

Reminder to self: the law mostly works because whoever discloses or exploits a bug gets thrown in jail. Or not.

2026-07-26

I have a USB isolator-hub, an STLINK (cheap clone), a mouse receiver, and a thumb drive. The hub has four device indicator LEDs (one for each downstream port), which agree with lsusb and /sys/bus/usb/devices/ (simply drawing power doesn't light up the LEDs). Funny thing is, if I plug the STLINK into the hub while the hub is connected to my computer and nothing is connected downstream, the hub dies, in that it doesn't connect the STLINK nor the mouse receiver however I plug and unplug them, unless I unplug and replug the hub into my computer. (The hub doesn't die if anything is connected downstream when I plug in the STLINK.) But not really: while dead, the hub starts working again if I plug in the thumb drive, irrespective of whether the STLINK and/or the mouse receiver is plugged in. Wow.

I have no idea where the problem is: Linux, the host controller, the isolator, the hub, or the STLINK.

For some reason I did the STM32F103C8T6 blink LED thing again, and ran into the same problems as last time, so I might as well document it. First install stlink and arm-none-eabi-{binutils,gcc,gdb}. Make sure STLINK works with st-info --probe. To use GDB, start st-util and connect with target extended-remote localhost:4242 in the GDB shell. Useful GDB commands: x/i $pc, x/w addr, set *addr = val. Check the value of a hardware register after writing into it.

We toggle the LED manually, just to make sure everything works. The onboard LED is between PC13 and VCC. Download the datasheet and the reference manual (RM0008) for this chip. In the "memory mapping" section of the datasheet, look up the addresses of "RCC" and "Port C", in this case 0x40021000 and 0x40011000. In the "RCC registers" section of the manual, find "APB2 peripheral clock enable register"; we need to set the IOPCEN bit, or bit 4 of this register, offset 0x18 from the RCC itself, or at 0x40021018: set *0x40021018=0x10. This turns on "Port C", which drives PC13. Then, in the "GPIO registers" section of the manual, find "port configuration register high"; we need to make PC13 an output, so bits 23-20 should be 0011. (That's max speed 50 MHz. Maybe it consumes less power at lower speeds, but I don't care.) The reset value is 0x44444444, so set *0x40011004=0x44344444. Finally, we write to the "port output data register", specifically toggle bit 13: set *0x4001100c^=0x2000. Repeat a few times and the LED should blink.

It remains to make the chip do this itself. I'll use assembly since I don't want to mess with instruction encodings (I didn't enjoy x86), and I've never quite figured out how to make GCC do what I want. We're on a Cortex-M3 processor, which runs ARMv7-M, which runs Thumb instructions. (It's a bit complicated.) I'm also using the "port bit set/reset register" instead of the "port output data register" here:

.thumb
.cpu cortex-m3

_start: .globl _start
    ldr r0, rccaddr         @ enable Port C
    mov r1, #0x10
    str r1, [r0, #0x18]
    ldr r0, pcaddr          @ set PC13 output push-pull 50 MHz
    mov r1, #3
    lsl r1, r1, #20
    str r1, [r0, #0x04]
    mov r1, #1              @ r1 = set13, r2 = reset13
    lsl r1, r1, #13
    lsl r2, r1, #16
    mov r7, #1              @ r7 = delay count
    lsl r7, r7, #19
loop:
    str r1, [r0, #0x10]     @ pc13 high, led off
    mov r3, r7
    bl spin
    str r2, [r0, #0x10]     @ pc13 low, led on
    mov r3, r7
    bl spin
    b loop

spin:
    sub r3, r3, #1
    bne spin
    bx lr

.align 2                    @ 4-byte align
rccaddr: .word 0x40021000
pcaddr: .word 0x40011000

A few things:

Speaking of disassembly... here's the build script:

set -e
arm-none-eabi-gcc -nostdlib main.s
arm-none-eabi-objdump -d a.out
arm-none-eabi-objcopy -O binary a.out a.bin
{ printf '\0\0\0\0\x09\x00\x00\x08'; cat a.bin; } > a.img
st-flash --reset write a.img 0x08000000

The --reset doesn't seem to be necessary but anyway. The curious printf produces the first two entries of the interrupt vector table, the initial sp and pc. (I don't know why the initial sp is needed.) The initial pc has its lowest bit set to indicate Thumb mode. Simply prepending bytes can mess up absolute addresses; the "proper" way is to have more than two entries in the table, put it in its own section and use a linker script; but of course we're not doing that.

The address 0x08000000 is the start of flash, from the "memory mapping" section of the datasheet. When BOOT0 is zero, flash is also mapped to address zero, from where the processor reads these values. (Hence, an initial pc of 0x9 also works.)

Here's a hex dump in case I get a new board and just want a quick test:

00000000: 0000 0000 0900 0008 0b48 1021 8161 0b48
00000010: 0321 0905 4160 0121 4903 0a04 0127 bf04
00000020: 0161 3b1c 00f0 05f8 0261 3b1c 00f0 01f8
00000030: f6e7 013b fdd1 7047 0010 0240 0010 0140

And that's it for now.

2026-07-24

Just migrated my blog on Codeberg Pages to the new git-pages service. Took me a while to figure out that the branch must be named pages and that SHA-256 repos don't work, so I had to delete the repo and re-create it with SHA-1.

2026-07-15

It's not news that writing strictly conforming C is super hard, but I think I just found a new way to invoke UB: let CHAT_BIT be 8 as usual, but let int have 1 sign bit, 32 value bits, and 7 padding bits, then adding three uint32_t variables in a row may make an intermediate int addition overflow. Luckily, bit-precise integer types are exempt from integer promotion (I just learned about this), so with a normal 32-bit int type, unsigned _BitInt(31) doesn't suffer from this problem.

2026-07-11

Watched ゼロの使い魔F (2012 anime, season 4 of ゼロの使い魔).

Configured Wake-on-LAN on my PC using a systemd.link file and learned to use arp-scan to find its IP address from my server. While the IP address of my server may change as well, I assigned it a static IP address (in a presumably unused DHCP range — I hope there won't be a conflict) so I can always connect to it with an Ethernet cable. DDNS doesn't look quite simple enough to set up.

2026-07-09

Watched Terminator 3: Rise of the Machines (2003 film).

Here's a helper for using Vim with Fcitx5. Doesn't work for commands like r; see :h utf-8-char-arg. Put it in ~/.config/vim/im and type :ru im to load it.

set tenc=utf-8
let curim = 'us-keyboard'
au InsertEnter * call system('fcitx5-remote --check -s ' .. curim)
au InsertLeave * let curim = system('fcitx5-remote --check -n; fcitx5-remote --check -c')

2026-07-07

Watched ゼロの使い魔〜三美姫の輪舞〜 (2008 anime, season 3 of ゼロの使い魔), including the OVA 誘惑の砂浜. I heard that the anime is much worse than the original light novel though...

2026-07-05

Finished playing おにいちゃんコンティニュー!ゆうりとしーくれっとらぶ (2025 visual novel).

2026-07-03

Replaced a night's sleep with four cups of coffee for no reason. Feels fucking awesome. /s

Been learning Japanese vocabulary with Anki for about three months. It started fun but now feels more like a chore, as I spend way more time reviewing cards (and realizing how much I forget) than learning new cards, which to be fair I can't really complain as that's just how memory works. The bigger issue is that, recently, I skip it often and otherwise usually procrastinate till after midnight, for, uh, reasons, which is probably bad for retention, which makes it feel even less rewarding.

If your microphone doesn't work with Firefox: check about:config and make sure media.getusermedia.audio.max_channels is nonzero.

2026-07-02

Fixed my suitcase which broke a wheel about a year ago when I dragged it while going like thirty (km/h) on a bike and hit a speed bump. The wheels are made of plastic and mounted with screws pushing against another piece of plastic placed inside the suitcase. After the accident I took out the internal part to look for a replacement but failed, and then lost that part (silly me). Just now I found one for the external part but not the internal part, so I gave up and replaced the broken wheel with a good one from the diagonal position so at least I can drag the suitcase around. Problem is, the screw holes are so weak I'd strip them unless I pay extremely careful attention while driving the screws, which of course I didn't. Ugh. Hope it works.

It sucks that suitcase wheel mounts aren't standard.

2026-06-30

Watched ゼロの使い魔~双月の騎士~ (2007 anime, season 2 of ゼロの使い魔).

2026-06-29

Watched ゼロの使い魔 (2006 anime, season 1).

I've been thinking about a good way to think about things: to take as a fact that everything eventually goes to shit. It doesn't even need to be true: if something doesn't look like it's going to shit it's because your lifespan is limited. Easy, huh? Sure, this won't work well if you're reading this, say, twenty years from the death of the universe (whatever that means) and something is still steadily improving, but then one, you have more important things to do than reading this, and two, I'd be really proud that someone so (hopefully) far in the future bothers at all to read what I wrote.

Usually, if something improves over your lifetime it's nice, if it degrades it's sad but that's just how things go, but people really don't like it if something improves and then degrades. The point is, if everything is eventually going to shit then there must be some unlucky people living when a thing peaks in "goodness". Given that lots of things exist, it is a natural consequence that lots of things start getting worse during a person's lifetime. (Somewhat like xkcd 1053; I misremembered the number as 1054, by the way.) It's great when we see things improve and even better when we work to make things improve; the point is that it really isn't anyone's fault that a thing stops improving and starts getting worse: it is inevitably going away anyway.

If one pictures a "goodness" curve that goes up, reaches its peak, then goes down, it's obvious that for a given thing yet to reach its peak, the better it is at an instant, the closer that instant is to when the thing start getting worse. This is, of course, different from saying that the better a thing is, the closer it is from starting to get worse: things don't have a predetermined "time to peak"; however the latter is in a sense true. From a utilitarian view, to maximize total goodness over time before the peak, one either increases goodness without shortening time to peak, or reduces slope without reducing peak goodness. Thus, an improvement is not necessarily "good" if it makes the thing closer to peak.

2026-06-26

More playing with my new printer... It makes some interesting noise when printing evenly spaced horizontal lines, but not good enough for music. Another experiment was to put in a segment of paper roll, cellotape its ends to create a loop, and then make the printer feed paper. The loop eventually breaks because of accumulated errors in its horizontal position. I also tried the Möbius strip, but it breaks much faster, as one should expect.

Some AWK that prints 50-column text in a small 8x16 font:

{
    gsub("\"", "\\[\"]")
    printf "TEXT 0,%d,\"1\",0,1,1,\"%s\"\n", ((NR-1)%40)*18, $0
}
BEGIN { print "SIZE 50 mm,90 mm"; print "CLS" }
NR % 40 == 0 { print "PRINT 1"; print "CLS" }
END {
    if (NR % 40) {
        printf "SIZE 50 mm,%d mm\n", (((NR%40)*18)+7)/8
        print "PRINT 1"; print "CLS"
    }
    print "FEED 200"
}

2026-06-25

I set up this website a few weeks ago with Caddy running on Debian, using automatic HTTPS. Later, I tried doing the same on another machine running Arch, but it's behind a firewall that blocks port 80 and thus breaks Let's Encrypt ACME. Just now I randomly found a valid certificate (that is, from a random place, not by brute force searching for a valid signature), and ran Caddy on the new machine.

But it wouldn't start, saying it doesn't have permission to open the TLS certificate. I checked the PEM files' permissions, which are correct. Then I realized that I should also check the systemd unit file. Turns out, it says, under "Hardening options":

ReadWritePaths=/var/lib/caddy /var/log/caddy /run/caddy

And, after installing the package, I moved the automatically created Caddy user's home directory to /home/caddy because I did that on the Debian machine since it's shorter (easier to type) and doesn't need quoting. I ended up moving back to /var/lib/caddy, the "proper" place, on both machines.

More on quoting: in an scp command one may refer to the home directory of the Caddy user on the remote machine with remote:~caddy, unless the local machine has a Caddy user with a different home directory, since the shell doesn't expand ~caddy if the local machine doesn't have a Caddy user and the expansion happens to be correct if both machines have Caddy users with identical home directories. Looks to me like a footgun, so I always quote it.

At least Arch's Caddy is new enough to have sane defaults for the encode directive; on Debian I needed encode gzip zstd to do the same thing.

Unrelated trivia: explain

$ ssh foo sh -c 'echo foo; echo bar' 

bar

2026-06-21

Got a second-hand HPRT N31 thermal printer, which prints 72 mm wide at 8 dots per mm (~200 dpi). My old thermal printer, an Xprinter 58IIH, only prints 48 mm wide, so it's a nice upgrade. Both offer a USB Type-B port and appear as /dev/usb/lp0. The new printer offers a line-oriented command language called TSPL, for which I found a programming manual by HPRT online but it doesn't claim to apply to my model. It certainly didn't help that the indicator light flashes green even if the command is invalid. I eventually figured out that the basic commands do work, that I need GAP 0,0 to make it work with paper rolls, and that double quotes in strings are escaped as \["], so anyway, but I certainly prefer ESC/POS and Xprinter's manual for it.

The new printer can backfeed, which I wanted to combine with variable density to print grayscale, but backfeed is so imprecise I couldn't even double strike text, so that's a dead end.

I opened up the machine hoping to find a SOIC-8 flash chip I can dump, but instead found a big-ass QFP-100 MCU with a sticker over its top, which I guess has the flash built in. I didn't have the patience to carefully remove that sticker so I gave up. I did see an antenna in the PCB and a bunch of empty solder pads nearby, presumably for variants with Bluetooth and/or Wi-Fi interfaces. (I didn't open the Xprinter since it takes 220 V AC; the new one takes 24 V DC from a separate power adapter.)

Here's some bash that prints a PBM image (the printer treats zero bits as black, so if the width is not a multiple of 8, the zero padding bits at the end of each row become a black vertical bar):

magick logo: -resize 576x -dither FloydSteinberg -colors 2 -negate pbm:- | {
    read; read w h
    echo 'CLS'
    printf 'SIZE %d mm,%d mm\n' $(((w+7)/8)) $(((h+7)/8))  # for paper rolls
    printf 'BITMAP 0,0,%d,%d,0,' $(((w+7)/8)) $h
    cat
    echo 'PRINT 1'  # or any number of copies
} > /dev/usb/lp0

And this is for the Xprinter. The loop is because the printer cannot handle high images (I ran into this problem trying to print text banners like "KEEP OUT KEEP OUT KEEP OUT"); the HPRT has a similar limit but I haven't hit it yet:

le16() { printf $(printf '\\%o\\%o' $(($1&255)) $(($1>>8))); }

magick -font Comic-Sans-MS -pointsize 400 label:'DUMB SHIT' \
    -gravity center -extent x384 -rotate 90 pbm:- | {
    read; read w h
    for (( ; h > 2000; h -= 2000 )) do
        printf '\x1d\x76\x30\x30'
        le16 $(((w+7)/8)); le16 2000
        head -c $((w*2000))
    done
    printf '\x1d\x76\x30\x30'
    le16 $(((w+7)/8)); le16 $h
    cat
} > /dev/usb/lp0

2026-06-11

Just figured out how to use a crappy computer I bought earlier with a pathetic N3150 processor and 4 GB of RAM, without attaching a monitor (which is a huge hassle): SSH. Just boot an Archlinux install ISO on it, attach it to my laptop via Ethernet, attach a keyboard, wait until the Ethernet lights start blinking, and type (very carefully):

a=`echo /sys/class/net/e*`
a=${a#/sys/class/net/}
ip a a 192.168.0.2/30 dev $a
passwd
secret
secret

And, on my laptop:

ip address add 192.168.0.1/30 dev eth0
ssh -o StrictHostKeyChecking=no \
    -o UserKnownHostsFile=/dev/null \
    -o ObscureKeystrokeTiming=no \
    root@192.168.0.2

I came up with the trick to get the name of the Ethernet interface, the first two options to ssh keep the known_hosts file clean (see ArchWiki), and the third one makes the light blink exactly once per key stroke, which is nice.

Having to attach a keyboard is still annoying, and I can't persist anything since it doesn't have a disk and writing to the thumb drive is silly. (Update 2026-06-21: it's now running with an old crappy disk.)

2026-06-08

Yesterday I learned that JIS B5 is a different paper size than ISO B5.

2026-05-27

Just watched Hypernormalisation and it's quite good. Familiar ideas from a somewhat different perspective, which is always refreshing. One thing that bugs me though is attributing suicide bombing to the Middle East: one Chinese soldier did it to slow down the Japs (didn't kill any though; this is also disputed, but his comrades support the story and the authority claims more), and the Japs did it to the Americans (Kamikaze).

I tried the sleeping pill (that I have) and it seems to work, except it makes me sleepy when awake as well. I guess I'll live with that till I get to see a doctor. (I'm prescribing myself: a dead man can't see a doctor.)

2026-05-21

I'm having yet more sleep problems and I hate this. Maybe I should try and entertain myself some more: anime, music, movies, books for fun... I guess I won't get any work done anyway, even if I try all the time, so having some fun is the rational choice. I'll try taking sleep pills and see if that helps.

It's funny how easy updating this website is. I'm so lazy that organizing changes into git commits seems like work, and I don't use a static site generator so I don't benefit from CI. Updating this website is just rsync -r www/now.vursc.org vps:now.vursc.org.

I'm using the deprecated (or whatever people call that these days) <tt> tag here, and I really don't understand why the HTML people decided to remove it. Not everything monospace is code, and <b>, <i>, <u>, and <s> are kept anyway, so what is the point of removing <tt>?

2026-05-17

I'm thinking about a new "generic" text markup language. Markdown is not expressive enough and suffers from incompatibility. reStructuredText is tied to Python and has "weird" syntax rules like the double colon and whitespace around inline markup, which makes the format more intuitive at the expense of complexity. (La)TeX is too low-level and, though not inherent, mostly tied to paper.

I think I will build it in JavaScript first, since I need KaTeX. The dollar sign is too hard to type (I need to press shift), let alone the LaTeX-style \( and \[. The backtick is better: just one keystroke and not used much in math. Backticks are still useful for inline code, so the choice will be a document-wide option (or directive). Now that I have two kinds of backtick-delimited "raw" content, I might as well make the starting backtick take a type tag, so m`E=mc^2` is explicit math, c`foo(bar())` is explicit code, and if the starting backtick follows a space or newline the default type is used and the space is preserved.

Escaping is a problem. It wouldn't be if everyone just writes s-exprs, but real people are lazy. The easiest way is to just disallow the backtick in backtick-delimited content. Another delimiter is needed for markup containing literal backticks, and I choose brackets since they are also easy to type and not used much in prose. The escape character is the conventional backslash. Thus m[E=mc^2] is exactly the same as m`E=mc^2`. Brackets can nest into a tree, and it would be nice if the parser can be generic, so the syntax is mostly uniform, like s-exprs. (Todo: alternative designs for escaping and their problems; markup with multiple arguments.)

Paragraphs are so common they deserve special syntax, though. Paragraphs are usually delimited by empty lines, but for CJK languages, which doesn't separate words with spaces, either conversion to HTML or the browser has to decide if a space should be inserted when joining two lines, which is ugly. So one long line per paragraph is the way to go. I keep the empty lines in between because wrapped long lines are hard to tell apart.

A curiosity is to embed s-exprs in this markup. One may simply wrap each atom in brackets, [[like] [this]], or use backticks if the atom doesn't contain one, [`like` `this`]. It would be nice if simple words doesn't need quoting, but then one cannot tell if [foo] is the atom foo or the list (foo).


Legal notice: You must not access this website if you are a citizen, resident, or otherwise legally related to China, the US, the UK, Australia, or any member state of the EU.