SSG Migration #1

Merged
snit merged 18 commits from stxge into main 2025-08-19 21:19:42 +02:00
43 changed files with 905 additions and 554 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
dist/
eval/

View file

@ -1 +0,0 @@
<svg viewBox="0 0 88 31" xmlns="http://www.w3.org/2000/svg"><foreignObject x="0" y="0" width="88" height="31"><pre xmlns="http://www.w3.org/1999/xhtml" style="color-scheme:light dark;display: block;width:88px;height:31px;font-size:8px;box-shadow:1px 1px 0 0 inset,graytext -1px -1px 0 0 inset;padding:5px;box-sizing:border-box;color:blue;background:red;margin:0">&gt;Snit was here</pre></foreignObject></svg>

Before

Width:  |  Height:  |  Size: 409 B

124
Makefile Normal file
View file

@ -0,0 +1,124 @@
# Makefile
## Tools and flags
SHELL := /bin/sh
STE := ste
STG := stg
STX := stx
XIPP := xipp
GUILE_FLAGS := ""
STX_FLAGS = --title $(TITLE) --style $$STYLE_REL --favicon $$FAVICON_REL
XIPP_FLAGS = --relative-to $(WWW_DIR) --prefix '$(CAPSULE_NAME)'
CAPSULE_NAME := ~snit
TITLE := "isekai.rocks/$(CAPSULE_NAME)"
## Directories and files and such
SITE_DIR := site
INCL_DIR := incl
EVAL_DIR := eval
GMI_DIR := dist/gmi
WWW_DIR := dist/www
ASST_DIR := asst
ROOT_NAME := index
SCM := scm
SXP := sxp
GMI := gmi
HTM := xhtml
STYLE_SRC := $(ASST_DIR)/style.css
STYLE_DST := $(WWW_DIR)/style.css
FAVICON_SRC := $(ASST_DIR)/favicon.ico
FAVICON_DST := $(WWW_DIR)/favicon.ico
## Source files
INCLUDE_FILES := $(shell find $(INCL_DIR) -type f -name '*.$(SCM)')
SITE_FILES := $(shell find $(SITE_DIR) -type f -name '*.$(SCM)')
ASSET_FILES := $(shell find $(ASST_DIR) -type f)
BANNERS := $(WWW_DIR)/meta/27x81/index.$(HTM)
CHILD_FILES := $(filter-out $(SITE_DIR)/$(ROOT_NAME).$(SCM),$(SITE_FILES))
EVAL_FILES := $(patsubst $(SITE_DIR)/%.$(SCM),$(EVAL_DIR)/%.$(SXP),$(CHILD_FILES)) $(EVAL_DIR)/$(ROOT_NAME).$(SXP)
GMI_FILES := $(patsubst $(SITE_DIR)/%.$(SCM),$(GMI_DIR)/%/index.$(GMI),$(CHILD_FILES)) $(GMI_DIR)/$(ROOT_NAME).$(GMI)
WWW_FILES := $(patsubst $(SITE_DIR)/%.$(SCM),$(WWW_DIR)/%/index.$(HTM),$(CHILD_FILES)) $(WWW_DIR)/$(ROOT_NAME).$(HTM)
GMI_ASST := $(patsubst $(ASST_DIR)/%,$(GMI_DIR)/%,$(ASSET_FILES))
WWW_ASST := $(patsubst $(ASST_DIR)/%,$(WWW_DIR)/%,$(ASSET_FILES))
## Build rules (both, gemini-only, http-only)
all: gmi web
gmi: $(GMI_FILES) $(GMI_ASST)
web: $(WWW_FILES) $(WWW_ASST)
## Copy assets
$(GMI_DIR)/%: $(ASST_DIR)/%
@mkdir -p $(dir $@)
cp $< $@
$(WWW_DIR)/%: $(ASST_DIR)/%
@mkdir -p $(dir $@)
cp $< $@
## Evaluate templates (.scm -> .sxp)
$(EVAL_DIR)/%.$(SXP): $(SITE_DIR)/%.$(SCM) $(INCLUDE_FILES)
@mkdir -p $(dir $@)
GUILE_FLAGS=$(GUILE_FLAGS) $(STE) -I $(INCL_DIR) $< > $@
$(EVAL_DIR)/$(ROOT_NAME).$(SXP): $(SITE_DIR)/$(ROOT_NAME).$(SCM) $(INCLUDE_FILES)
@mkdir -p $(dir $@)
GUILE_FLAGS=$(GUILE_FLAGS) $(STE) -I $(INCL_DIR) $< > $@
## Render GemText from SGT data (.sxp -> .gmi)
$(GMI_DIR)/%/index.$(GMI): $(EVAL_DIR)/%.$(SXP) $(INCLUDE_FILES)
@mkdir -p $(dir $@)
GUILE_FLAGS=$(GUILE_FLAGS) $(STG) $< > $@
$(GMI_DIR)/$(ROOT_NAME).$(GMI): $(EVAL_DIR)/$(ROOT_NAME).$(SXP) $(INCLUDE_FILES)
@mkdir -p $(dir $@)
GUILE_FLAGS=$(GUILE_FLAGS) $(STG) $< > $@
## Render XHTML from SGT data (.sxp -> .xhtml)
$(BANNERS): XIPP_FLAGS += --no-link
$(WWW_DIR)/%/index.$(HTM): $(EVAL_DIR)/%.$(SXP) $(INCLUDE_FILES) $(STYLE_DST) $(FAVICON_DST) $(WWW_ASST)
@mkdir -p $(dir $@)
STYLE_REL=$$(realpath --relative-to=$(dir $@) $(STYLE_DST)); \
FAVICON_REL=$$(realpath --relative-to=$(dir $@) $(FAVICON_DST)); \
GUILE_FLAGS=$(GUILE_FLAGS) $(STX) $(STX_FLAGS) $< | \
GUILE_FLAGS=$(GUILE_FLAGS) $(XIPP) $(XIPP_FLAGS) > $@
$(WWW_DIR)/$(ROOT_NAME).$(HTM): $(EVAL_DIR)/$(ROOT_NAME).$(SXP) $(STYLE_DST) $(FAVICON_DST) $(INCLUDE_FILES) $(WWW_ASST)
@mkdir -p $(dir $@)
STYLE_REL=$$(realpath --relative-to=$(dir $@) $(STYLE_DST)); \
FAVICON_REL=$$(realpath --relative-to=$(dir $@) $(FAVICON_DST)); \
GUILE_FLAGS=$(GUILE_FLAGS) $(STX) $(STX_FLAGS) $< | \
GUILE_FLAGS=$(GUILE_FLAGS) $(XIPP) $(XIPP_FLAGS) > $@
## We want to keep intermediary files
.SECONDARY: $(EVAL_FILES)
## Delete rendered files or both
clean:
rm -rf $(GMI_DIR) $(WWW_DIR)
distclean: clean
rm -rf $(EVAL_DIR)
.PHONY: all gmi web clean distclean

37
README.md Normal file
View file

@ -0,0 +1,37 @@
# ~snit
The source files for my personal capsule, which can be viewed at:
[=> Capsule (HTTPS)](https://isekai.rocks/~snit)
[=> Capsule (Gemini)](gemini://isekai.rocks/~snit)
This capsule relies on STXGE, which is a static site generator I wrote myself
using Guile Scheme. STXGE takes in source files written in Scheme, evaluates
them to produce SGT(akin to SXML for GemText), then renders the SGT to XHTML
and GemText.
[=> STXGE Repository](https://forge.fsky.io/snit/stxge)
[=> SXML on Wikipedia](https://en.wikipedia.org/wiki/SXML)
## Building
The `Makefile` includes variables up top that may be messed with, such as paths
to the STXGE tools if they aren't on your `${PATH}`.
To build this capsule, you can run any of the following:
```
$ make # Build everything
$ make gmi # Only build for Gemini
$ make web # Only build for HTTP(S)
$ make clean # Delete rendered GMI/XHTML
$ make distclean # Delete all build files
```
By default, the following directories are used:
* `site/` contains document templates to render
* `incl/` contains templates that can be included to provide code or data
* `asst/` contains asset files such as media or stylesheets
* `eval/` will contain intermediary s-expression data from evaluating templates
* `dist/{www,gmi}/` will contain rendered XHTML and GemText documents, respectively

BIN
asst/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

25
asst/media/27x81/snit.svg Normal file
View file

@ -0,0 +1,25 @@
<?xml version="1.0"?>
<svg width="27" height="81" xmlns="http://www.w3.org/2000/svg">
<foreignObject x="0" y="0" width="27" height="81">
<div xmlns="http://www.w3.org/1999/xhtml"
style="display: flex;
align-items: center;
justify-content: center;
writing-mode: vertical-rl;
text-orientation: upright;
font-family: sans-serif;
font-size: 20px;
white-space: nowrap;
padding: 3px;
padding-top: 0px;
border: 1px solid black;
box-sizing: border-box;
width: 100%;
height: 100%;">
「え?」
</div>
</foreignObject>
<text x="3" y="78" fill="black" font-family="sans-serif" font-size="9px">
~snit
</text>
</svg>

After

Width:  |  Height:  |  Size: 931 B

BIN
asst/media/27x81/vel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

Before

Width:  |  Height:  |  Size: 726 KiB

After

Width:  |  Height:  |  Size: 726 KiB

Before After
Before After

38
asst/style.css Normal file
View file

@ -0,0 +1,38 @@
* { font-family: sans-serif; font-size: 14pt; padding: 0; margin: 0; }
body {
margin: 0 auto;
padding: 4ch;
width: 70ch;
}
img, video, audio { max-width: 70ch; }
h1::before { content: "# "; }
h2::before { content: "## "; }
h3::before { content: "### "; }
ul li::before { content: "* "; }
a::before {
content: "=>";
display: inline-block;
color: black;
padding-right: 1ch;
}
ul { list-style: none; }
blockquote {
border-left: 1px solid;
padding-left: calc(1ch - 1px);
}
pre {
font-family: monospace;
padding: calc(1ch - 1px);
font-size: 10pt;
border: 1px solid;
}

View file

@ -1,42 +0,0 @@
# Browser Tabs are Stupid
I hate tabs in browsers. Well, I hate when any program adds built-in tab support. The concept of built-in tabs inherently violates the concept of programs doing only one thing and one thing well.
In an ideal world*, there should be genuinely no reason for programs to each write their own implementation of tabs. They aren't compatible with each other, limiting their flexibility, and each implementation looks and acts different, so you have to configure them and learn how they work separately for each and every program.
In an ideal world*, you could just have a single program that you run your programs in which will automatically manage tabbing them together. You only need to configure one thing to have tabs work the same globally, and you can put any program in those tabs.
Luckily, these programs already exist. Many window managers come with support for tabbing windows, such as i3/Sway or Haiku's; and there're several programs that implement tabs in the terminal, such as tmux or screen. So if they already exist, why not just use them?
Even more ironically, certain newer browsers are actually implementing EVEN MORE features found in tiling window managers. Want two tabs side-by-side now? Browsers like Vivaldi can do that natively. A lot of browsers include support for grouping tabs by category. Now imagine these tiled or grouped tabs worked seamlessly with every other program you have running.
## Removing tabs from my browser
Since I already have a tiling window manager, I could theoretically just find a browser that doesn't come with support for tabs, and just use that in combination with my window manager. Unfortunately, not many such browsers exist, and the ones that do are so outdated that they're next to useless on any site made in the past decade or two. Surf, for example, seems to just freeze on most websites.
Its unfortunate, but the alternative is to just use a tabbed browser, and do what I can to pretend it doesn't have tabs. I've opted for Firefox in this case. Firefox has extensions to force each tab into its own window, and its flexible enough to let me customise the CSS to hide the now-useless tab bar.
This extension, which I use, is open source and has worked mostly flawlessly for me:
=> https://gitlab.com/adsum/firefox-notabs Firefox No Tabs
The only annoyance, documented in issue #2, is that certain special Firefox tabs just don't get their own windows, but these tabs are rarely-used, so its not a big problem.
The method to remove tabs from the UI is linked in the README, but I'll also just tell you here. You'll need to go to your profile folder in ~/.mozilla/firefox/. For example, mine is called ~/.mozilla/firefox/vhj2i22f.default-release. Within it, you'll create chrome/userChrome.css with the following content:
```
#TabsToolbar{ visibility: collapse !important }
```
And that's literally all I had to do. For the past few months, I've used this exact setup in combination with the Sway window manager with zero problems. There might be a performance penalty from doing this, but, if there is, I haven't noticed anything personally.
Also, you may notice that this setup is basically just recreating Electron apps, but it has a few crucial differences. For one, as mentioned, I don't notice any real performance penalty from having multiple windows open at once in the same way I do with Electron. Secondly, I can have multiple instances of the same app open using this method, which to my knowledge isn't possible/easy to do with Electron. Third, Wayland support with Electron apps fucking sucks, but in Firefox a lot of things just seem to work fine. And lastly, I get all the benefits of Firefox's configuration, such as blocking ads and trackers, or being able to use Vim keybinds.
## This is not an ideal world
Earlier I said "in an ideal" world programs wouldn't implement their own tabs. Unfortunately, this is not an ideal world. I do have to admit that I at least UNDERSTAND why so many programs have built-in tabs. The reality is that most people don't use tiling window managers; they don't use Haiku; they use Windows or Mac, or a generic floating window manager that's actually incredibly bad at managing windows, and has no support for grouping them into tabs.
In such an environment, having twenty separate windows to manage by manually positioning and resizng them would be an absolute nightmare, so it makes perfect sense that these programs all have to take matters into their own hands.
I don't have to like it, but it does really suck. I do find it funny that browsers are becoming full-blown tiling window managers though; goes to show that its just a better way of managing windows.
Actually, if this WERE an ideal world, the web never would've gotten to the point where we need to implement full-blown window managers. Web browsers are basically full operating systems unto themselves at this point, each website a full desktop program. In an ideal world, the web would'nt've become a massive monolith that a typical person can spend literally 100% of their digital activities within.
But I digress; the point is that built-in tabs are bloat, and tiling window manager folks can just delete them entirely and use the tabs they already have to achieve the same thing but better. Unfortunately, though, if you didn't think tabs were bloat before, doing this does objectively make them bloat, since they're a feature you don't even use, yet still have full support for (worse, you had to actually ADD MORE to pretend they aren't there).
I don't know if this was informative at all (I feel like I couldn't word any of this properly), or if you even necessarily agree, but, as always, feel free to message or email me your thoughts or questions.

View file

@ -1,78 +0,0 @@
# Making the CapsLock Key More Useful
The CapsLock key is one of the most useless keys on the keyboard for me, yet placed in the single best place a non-letter key could be placed. It's an obvious candidate for people looking to improve their keyboard layout.
I often heard people saying they rebound it to control or escape, which both sounded equally good to me, so I was never sure which to use. Then I heard someone mention that they use the key for BOTH at once. You press it and get the escape key, and hold it to get the control key. This sounded perfect, and is now in fact my single most-used key rebinding, to the point where I feel helpless when on a system without it.
Originally, I used some odd X11-specific software to achieve the rebind, but it was really flaky, and, of course, didn't work in a TTY or on Wayland. I then switched to interception-tools with the dual-function-keys plugin, but it's Linux-specific, and I couldn't even get it working on Gentoo, but it worked flawlessly on Arch.
## Keyd
Nowadays I use a piece of software called keyd. Its super simple, works on X11, TTY, and Wayland, and works* on FreeBSD.
=> https://github.com/rvaiya/keyd Keyd Github
> *On FreeBSD, it currently locks your input in a TTY, so it really only works on X11 and Wayland.
### Configuration
The configuration file goes in /etc/keyd/default.conf. Its capable of a lot of things, which you can find in its documentation, but this particular rebind is incredibly simple:
```
[ids]
*
[main]
capslock = overload(control, esc)
```
### Starting the Daemon
Now you just need to start the daemon. It comes with a systemd service file out of the box, so nothing special is needed there.
On systems running OpenRC, such as Gentoo, I recommend using the service file written in this blog post:
=> https://technex.us/2024/07/keyd-on-gentoo-with-openrc-and-kde-plasma/ Keyd on Gentoo with OpenRC and KDE Plasma
For convenience, I'll paste the script here. It should be put into /etc/init.d/keyd:
```
#!/sbin/openrc-run
# Description of the service
description="keyd key remapping daemon"
# The location of the keyd binary
command="/usr/local/bin/keyd"
#command_args="-d"
pidfile="/run/keyd.pid"
depend() {
need localmount
after bootmisc
}
start() {
ebegin "Starting keyd"
start-stop-daemon --start --exec $command --background --user root --make-pidfile --pidfile $pidfile --
eend $?
}
stop() {
ebegin "Stopping keyd"
start-stop-daemon --stop --pidfile $pidfile
eend $?
}
restart() {
ebegin "Restarting keyd"
start
eend $?
}
```
Once you have that, you can start and enable the daemon like any other.
FreeBSD has a service script built-in, but, as mentioned earlier, keyd on FreeBSD doesn't work in a TTY, so I actually just recommend starting keyd with your window manager. Note that you have to run it as root, though. I put the following into my /etc/doas.conf to let me run it without a password:
```
permit nopass :wheel cmd keyd
```
## Caveats
I find keyd to work great for my use-case, but I have noticed some caveats. Of course, there's the big one with FreeBSD, which does suck, but I don't use a TTY often enough to be too annoyed.
Another caveat is that it isn't particularly good at Unicode. It seems to emit Unicode characters as macros, using a really hacky solution, and I never actually managed to get it working. Github issues suggest that even when it does work, Wayland users still can't do it in Electron apps. Not that I use Electron anymore, but it's still something to look out for.
These caveats are fine with me, but I could see them being deal-breakers for others, so do be aware of them. There're plenty of alternatives, like interception-tools/dual-function-keys, or kmodmap, which can achieve the same thing.

View file

@ -1,31 +0,0 @@
# Rob Pike on Dotfiles
Rob Pike, 2012-08-02
=> https://plus.google.com/101960720994009339267/posts/R58WgWwN9jp Original post
=> https://web.archive.org/web/20190317000040/https://plus.google.com/101960720994009339267/posts/R58WgWwN9jp Original post (Wayback Machine archive)
## Post Text
A lesson in shortcuts.
Long ago, as the design of the Unix file system was being worked out, the entries . and .. appeared, to make navigation easier. I'm not sure but I believe .. went in during the Version 2 rewrite, when the file system became hierarchical (it had a very different structure early on). When one typed ls, however, these files appeared, so either Ken or Dennis added a simple test to the program. It was in assembler then, but the code in question was equivalent to something like this:
```
if (name[0] == '.') continue;
```
This statement was a little shorter than what it should have been, which is
```
if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) continue;
```
but hey, it was easy.
Two things resulted.
First, a bad precedent was set. A lot of other lazy programmers introduced bugs by making the same simplification. Actual files beginning with periods are often skipped when they should be counted.
Second, and much worse, the idea of a "hidden" or "dot" file was created. As a consequence, more lazy programmers started dropping files into everyone's home directory. I don't have all that much stuff installed on the machine I'm using to type this, but my home directory has about a hundred dot files and I don't even know what most of them are or whether they're still needed. Every file name evaluation that goes through my home directory is slowed down by this accumulated sludge.
I'm pretty sure the concept of a hidden file was an unintended consequence. It was certainly a mistake.
How many bugs and wasted CPU cycles and instances of human frustration (not to mention bad design) have resulted from that one small shortcut about 40 years ago?
Keep that in mind next time you want to cut a corner in your code.
(For those who object that dot files serve a purpose, I don't dispute that but counter that it's the files that serve the purpose, not the convention for their names. They could just as easily be in $HOME/cfg or $HOME/lib, which is what we did in Plan 9, which had no dot files. Lessons can be learned.)

View file

@ -1,77 +0,0 @@
# Hosting Gemini Capsules via Yggdrasil
Getting a gemini capsule running on Yggdrasil was harder than I would have thought. The main complexity came from the fact that gemini has mandatory TLS, combined with Yggdrasil predominantly being bare IPv6 addresses.
I suspect that this would have been no different than hosting a clearnet capsule had I been using Alfis to get an actual domain name, but I haven't set that up.
> NOTE: This guide assumes the use of gmid as the server. I have no clue how this works (or doesn't) on any other server.
## Prerequisites
This is NOT a guide to setting up Yggdrasil, nor for setting up gmid. I assume you already have a working Yggdrasil setup, as well as know how to run gmid for clearnet capsules.
## Self-signed Certificates
First of all, we have to generate a certificate. If you use a CA normally, you can't use their certificates; they don't usually issue certificates for IP addresses. This leaves us to issue our own, but gemini explicitly allows (and encourages) self-signed certificates, so you should probably use a self-signed one anyways.
I used openssl to generate the certificate we need. The gencert program included in gmid isn't meant to work with raw IP addresses, so it results in some sort of SANS error.
> NOTE: For full clarity, I didn't find much online about this, so I used ChatGPT to help me here. It worked for me, but I don't know if this is foolproof.
First we need to create a configuration file with the following content (replace 200:: with your Yggdrasil address):
```
[req]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn
[dn]
CN = 200::
[req_ext]
subjectAltName = @alt_names
[alt_names]
IP.1 = 200::
[ v3_ca ]
subjectAltName = @alt_names
basicConstraints = CA:TRUE
keyUsage = digitalSignature, keyEncipherment, keyCertSign
```
The file can be named whatever; we'll be passing it manually into openssl next:
```
openssl req -x509 -nodes \
-days 365 \
-keyout ipv6.key \
-out ipv6.pem \
-config $YOUR_CONFIG
-extensions v3_ca
```
Finally, move the resulting ipv6.key and ipv6.pem files to your preferred location. I put my gmid keys in /etc/ssl/gmid/
## gmid Configuration
On my clearnet capsule, I'd used a wildcard statement for the listen declaration, but apparently that doesn't fly here. Replace the wildcard with the same IP address as used in the server declaration part. Also, do not surround them with brackets.
Here's an example:
```
server "200::1" {
listen on 200:1 port 1965
root "/srv/gmi/yggsite"
cert "/etc/ssl/gmid/ipv6.pem"
key "/etc/ssl/gmid/ipv6.key"
}
```
=> https://github.com/omar-polo/gmid/issues/25 Relevant discussion on GitHub.
Start up gmid and you should be able to connect!
As an aside, even though you can't put brackets in gmid's configuration, amfora won't work unless you DO put brackets into the URL:
```
amfora gemini://[200::1]
```
I'm not sure if this is a problem with gmid or amfora, or how it works on other clients, but I figured I'd note it down here, because I spent an extra twenty minutes thinking this wasn't working just because I stopped using brackets on amfora after gmid told me to.

View file

@ -1,173 +0,0 @@
# Regarding hier(7) in $HOME
Taking a look at hier(7) is a valuable way to understand how your Unix-like system is structured. It tells you exactly what each directory on your filesystem does, so you always know exactly where to put system files.
## The Hierarchy for System Files
Taking a look at the overall structure, you may notice that a lot of directory names seem to be repeated, but in different locations. You'll also notice that these directories seem to be structured roughly the same way the / directory is. For example, you have /bin/, /usr/bin/, and /usr/local/bin/.
On my Arch Linux install, according to hier(7):
* / is for critical utilities required to boot and repair the system
* /usr/ is the main place system files get installed to, including all of the programs installed by the package manager
* /usr/local/, to my understanding, is where you'd place system files that you compiled and installed manually, rather than using the package manager
=> https://man.archlinux.org/man/hier.7 View Arch Linux's hier(7) online
On FreeBSD, according to hier(7), the equivalent directories are as follows:
* / is essentially the same as on Arch Linux
* /usr/ seems to be for core operating system files that aren't required for boot or repair
* /usr/local/ is for system files not part of the core operating system, such as package files or locally-compiled programs
=> https://man.freebsd.org/cgi/man.cgi?hier(7) View FreeBSD's hier(7) online
As you can see, there seem to be three separate ""root"" directories, each one with a specific purpose. However, these aren't the only three directories that seem to be root directories. The /root/ and /home/$USER/ directories, which act as user home directories, ALSO seem to be root directories, but its nearly impossible to tell at first, because they use an entirely different set of directories.
## The Hierarchy for User Files
The user's home directory follows its own hierarchy conventions completely unlike any of the aforementioned system tree hierarchies. Even worse, the home directory makes extensive use of dotfiles, which are an unintended bug that's most often leveraged by lazy programmers who don't want to learn how the system they're programming on works.
=> ./dotfiles-rob-pike.gmi Rob Pike on Dotfiles
The home directory tree as compared to the system tree:
* ~/.config/, as opposed to /etc/
* ~/.cache/, as opposed to /var/cache/
* ~/.local/bin/, as opposed to /bin/
* ~/.local/share/, as opposed to /share/
* ~/.local/state/, as opposed to /var/lib/
=> https://specifications.freedesktop.org/basedir-spec/latest/ XDG Base Directory Specification
As you can see, the user's home directory has all of the same data as any of the system trees, but with completely different names, all leveraging the dotfile bug. Perhaps I would've been fine if the files made use of the usual names, but were all placed in ~/.local/, because then it'd just mean the tree root isn't at ~/, but at ~/.local/, but this isn't the case.
Even worse, even though all of these directories can be moved using $XDG_*_HOME variables, an incredible number of programs completely ignore the XDG Base Directory Specification, and hardcode the path, or place their files straight into ~/, completely ignoring any standard directories, with no possible way to change it. Some of these programs think they're so special that they even refuse to consider this a bug, like OpenSSH with ~/.ssh/.
=> https://wiki.archlinux.org/title/XDG_Base_Directory#Hardcoded Arch Wiki's list of hardcoded dotfiles
=> https://web.archive.org/web/20190925004614/https://bugzilla.mindrot.org/show_bug.cgi?id=2050 OpenSSH bug report
To finish off talking about the home directory tree, we can't forget to mention the XDG User Directories:
* ~/Downloads/
* ~/Desktop/
* ~/Documents/
* ~/Music/
* ~/Pictures/
* ~/Public
* ~/Templates/
* ~/Videos/
=> https://wiki.archlinux.org/title/XDG_user_directories Arch Wiki's page on XDG User Directories
Honestly, other than the fact that they use capital letters, which is a personal preference thing, I can't really complain about these. I'd prefer them somewhere else, but the xdg-user-dirs tool combined with $XDG_CONFIG_HOME/user-dirs.dirs lets me move and rename them, which most programs do actually seem to respect.
The main point here is that system files have THREE locations that have the exact same directory structure, but user files aren't the same. You can't leverage existing knowledge to know where to put user files, and programs have to handle user files as an entirely separate case from system files. The directory structure CAN be changed, but not all programs respect those changes, and some completely ignore the structure to begin with, which seems to be caused predominantly due to a specific bug allowing lazy programs to shove files wherever they want with the knowledge that those files will be ""hidden"" and thus not a bother.
## My Current Home Directory Setup
With all this said, I decided to make use of what I could in order to make my home directory mimic the structure of the system trees, as well as to stop making use of dotfiles as hidden directories.
### Unhiding Dotfiles
This one was pretty simple. All I really had to do is add to my ~/.shrc:
```
alias ls="ls -A"
```
I also added to my $XDG_CONFIG_HOME/ranger/rc.conf for the ranger file manager:
```
set show_hidden true
```
### Undotting My Dotfiles
This predominantly involved adding a bunch of variables to my ~/.profile:
```
## Add /bin for executables instead of .local/bin
PATH="${PATH}:${HOME}/bin"
## Should replace .config, .cache, and .local/{share,state} for most programs
XDG_CACHE_HOME="${HOME}/var/cache"; export XDG_CACHE_HOME
XDG_CONFIG_HOME="${HOME}/etc"; export XDG_CONFIG_HOME
XDG_STATE_HOME="${HOME}/var/lib"; export XDG_STATE_HOME
XDG_DATA_HOME="${HOME}/share"; export XDG_DATA_HOME
## These programs think they're special and should go to hell
## but they give me an option at all which I appreciate
### Bash
HISTFILE="${XDG_STATE_HOME}/bash/history"; export HISTFILE
### Python (>3.12)
PYTHON_HISTORY="${XDG_STATE_HOME}/python/history"; export PYTHON_HISTORY
PYTHONPYCACHEPREFIX="${XDG_CACHE_HOME}/python"; export PYTHONPYCACHEPREFIX
PYTHONUSERBASE="${XDG_DATA_HOME}/python"; export PYTHONUSERBASE
```
### Moving Desktop Files
As mentioned earlier, the xdg-user-dirs tool in combination with $XDG_CONFIG_HOME/user-dirs.dirs achieves what I want:
```
XDG_DESKTOP_DIR="$HOME/tmp"
XDG_TEMPLATES_DIR="$HOME/tmp"
XDG_PUBLICSHARE_DIR="$HOME/tmp"
XDG_DOWNLOAD_DIR="$HOME/tmp"
XDG_PICTURES_DIR="$HOME/media/img"
XDG_DOCUMENTS_DIR="$HOME/media/doc"
XDG_MUSIC_DIR="$HOME/media/audio"
XDG_VIDEOS_DIR="$HOME/media/video"
```
This one probably needs some explaining.
To start, the hier(7) manpage says that /media/ is meant for removable media, like CDs or floppy disks, with a subdirectory for each type of media (i.e. /media/floppy[0-9]/), which clearly isn't quite what I'm using it for here. However, to begin with, I normally only use /mnt/ to mount external drives, but I COULD see myself mounting an external drive dedicated specifically to hosting my media files at ~/media/, if I'd been a desktop user. Of course, I'm also forgoing the media type subdirectories, which I do because I can only see myself mounting multiple drives here under the condition that its a single LVM or ZFS pool. Essentially, I'm bending the meaning of ~/media/ here to OPTIONALLY mean "removable media", and more predominantly mean "media files".
It might also seem weird that I listed so many of them at ~/tmp/, but hear me out here. For one, I don't have a desktop, since I use a tiling window manager, and I have zero clue what the templates or public share directories are for, so I combined these all into my downloads directory to act as a large catch-all for any file I'm not immediately sure should go elsewhere. The reason I put these in ~/tmp/ specifically, though, is because I've found that the only files that remain in my downloads directory for a long time tend to be those that I really only needed once for a particular purpose, such as a Linux ISO image to write to a USB drive. Thus, I've actually gone so far as to add the following to my /etc/fstab:
```
tmpfs /home/snit/tmp tmpfs rw,relatime 0 0
```
Which, of course, means that my ~/tmp/ directory will be cleared every time I reboot; this may seem inconvenient to some, so I don't recommend this part, but, again, I only use this directory for files I'm probably gonna delete soon anyways.
### Issues I've Encountered
The main issue I have is just with software that doesn't follow the specifications properly. OpenSSH places files in ~/.ssh/, Firefox has ~/.mozilla/ (I'm told this will soon be fixed), and it seems that changing settings in Firefox's filechooser dialogue causes a file to be created at ~/.config/dconf/user, even though dconf claims to support $XDG_CONFIG_HOME.
There's also ~/.profile and ~/.shrc. I can move the latter using ENV, but the former to my knowledge simply can't be moved. However, I've opted to leave both as is and accept them, simply because FreeBSD seems to put similar files straight into /, so it technically has the consistency I'm looking for here, even if its slightly inelegant.
### Directory Structure
Currently this is what my home directory looks like:
* ~/bin/ for local scripts and executables (replaces ~/.local/bin/)
* ~/etc/ for configuration files (replaces ~/.config/)
* ~/media/ for media files like images or documents
* ~/media/audio for audio files
* ~/media/video for video files
* ~/media/img for images (this actually contains a lot of videos for convenience, but I might change that)
* ~/media/doc for text-based files like PDF documents and personal notes
* ~/mnt/ as an alternative to /mnt/ for easier access
* ~/share/ for architecture-agnostic data (replaces ~/.local/share/); this is actually where I put my desktop wallpapers
* ~/src/ for program source code
* ~/src/foreign/ for code I didn't write for organisation purposes (might also add ~/src/local/)
* ~/tmp/ for the default download directory, mounted as a tmpfs
* ~/var/cache/ for cache data (replaces ~/.cache/)
* ~/var/lib/ for state data (replaces ~/.local/state)
* ~/.mozilla/ for Firefox data (can't move)
* ~/.ssh/ for OpenSSH data (can't move)
* ~/.profile for my shell profile (can't move)
* ~/.shrc for my interactive shell settings
## Conclusion
Mainly I just wish user directory trees worked similar to system trees. Why can't we leverage existing knowledge for this? Why do I have to write special cases based on whether its a system or user tree? Why can't programs just follow standards properly?
It'd be cool if, for example, I could actually compile a package and install it to my user directories just the same as if I were installing it to the system itself. In conjunction with Plan 9's bind(1), I could see this being genuinely useful on multi-user systems like pubnixes. After all, I can download, compile, and run that program regardless, so, in my opinion, there's no real point in NOT giving me the option to use the package manager in my own home directory.
Anyways, that's all I've got for now. If you've any questions or feedback on this admittedly incredibly cursed and controversial topic, I'd love to hear it:
=> mailto:snit@cock.li Email
=> https://matrix.to/#/@snit:isekai.rocks Matrix
## Addendum I
Just wanted to add that I no longer mount ~/tmp/ as a tmpfs. It honestly works fine for the most part, but I had transmission set to download incomplete torrents to ~/tmp/ before moving them to ~/media/ when finished, which gave me a lot of out-of-memory errors if I downloaded a large enough torrent, or a lot of torrents at once.
Also, I use trash-cli and have rm aliased to it. When ~/tmp/ is mounted as a tmpfs, it actually gets its own ~/tmp/.Trash/ directory, as its a different filesystem from /home. Its not a big deal but its somewhat annoying having two separate trash directories. And if you haven't figured it out already from uh everything above this, annoyances when it comes to directories are intolerable on my system.
So I don't mount it anymore, and instead just use it as a regular directory that I clear out sometimes. The only real benefit it used to bring was clearing out automatically on shutdown, but I could probably just add an rm line to my .profile for a similar effect.
## Adendum II
I've made a couple more changes since the last update.
First, I've updated my ~/.profile to work similarly to Arch's /etc/profile, which actually outsources most of its work to files in /etc/profile.d/. I've opted to do the same thing, with specific files for my XDG Base Directory compliance, and for setting other variables related to Wayland or fcitx5. Since I'd put most of ~/.profile in ~/etc/, and ~/.shrc can be put literally anywhere (as it's set by $ENV), I've opted to move it to ~/etc/sh/shrc. This reduces my total number of cringe noncompliant dotfiles in $HOME to three.
The other change that I've made is the addition of ~/libexec/ and ~/sbin/, which I think are truly underutilised directories even in the system hierarchies (Arch foregoes them entirely in favour of just using /bin/ and /lib/).
I use ~/libexec/ for anything I'd normally put in ~/bin/, but that I'd rarely, if ever, run directly. Most of these are scripts related to setting up my window manager, and are thus only ever executed by my window manager. There's also one that I have run at shell startup, which prints every dotfile that clutters my home directory, and automatically deletes all dotfiles in a specified list (only deleting what I know I don't care about). I mostly added ~/libexec/ because I've been thinking of ways to keep my $PATH namespace less cluttered, and this is something easy to implement AND quite elegant in my opinion.
I don't actually use ~/sbin/ on my home systems. There's only one script I use at home that needs to be run as root, and it's run by my window manager, so I've opted instead to just give it a nopass option in my /etc/doas.conf, and place it in ~/libexec/. On isekai.rocks, though, I do actually use ~/sbin/. The main two scripts I use in ~/sbin/ are one to sync the live isekai.rocks capsule to the git repository, and another to set up a new user account on the pubnix. There was also previously one that updated Minecraft mods, automatically creating new zip files for download, and restarting the server to load the new mods.
So, to recap, the changes I've made since the original post were:
* Stop mounting ~/tmp/ as a tmpfs
* Move ~/.shrc to ~/etc/sh/shrc
* Create ~/libexec/
* Create ~/sbin/

View file

@ -1,8 +0,0 @@
# ~snit/comp/
This section is for technology-related content. Most of it is probably related to programming or especially just really bad takes on how operating systems should work.
The following are listed in no particular order:
=> ./gemini-yggdrasil.gmi Hosting Gemini Capsules via Yggdrasil
=> ./hier7.gmi Regarding hier(7) in $HOME
=> ./capslock.gmi Making the CapsLock Key More Useful
=> ./browser-tabs.gmi Browser Tabs are Stupid

View file

@ -1,24 +0,0 @@
# Contact
The main media I use are as follows:
=> xmpp:snit@isekai.rocks snit@isekai.rocks (XMPP) (preferred)
=> matrix:u/rinte:isekai.rocks @rinte:isekai.rocks (Matrix)
=> mailto:snit@cock.li snit@cock.li (E-Mail) (subject to change)
## Alternative Accounts
I also own the following accounts, although I prefer you use the accounts listed above if you wish to contact me.
### Matrix
=> matrix:u/snite:telepath.im @snite:telepath.im
=> matrix:u/snute:ip-logger.com @snute:ip-logger.com
=> matrix:u/bartholomew:squarebowl.club @bartholomew:squarebowl.club
### XMPP
=> xmpp:snite@telepath.im snite@telepath.im
=> xmpp:snute@ip-logger.com snute@ip-logger.com
## PGP Key
If someone claiming to be me contacts you, please ask to verify my PGP key:
=> ./pgp.txt Public PGP Key
This page has been signed with my PGP key:
=> ./contact.gmi.asc Page Signature

View file

@ -1,16 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEG/OokXpvc/2lQKEiNbMOb/3SjwQFAmh2YlkACgkQNbMOb/3S
jwQCfw/+Np93x4VbaE6fK1xNubcIoMu+GHN9o0RUZ+d2tWZlJc8L9hIpBMN47Z+C
jjDEv7fUt/G31audFf6VVRID4oMO14qiFKSiBQQHe9ofoRy0dsFhjAwdDnbMWumU
a+jOTwYml6TFoMpn9ZAt2BMt/SvbG4gtjOyQXqMVQ6Wl/arKbdB7QpGTgkIt64bh
EJszh8ZYmnRsY9k3glDBb2Ahviar/uhJqkSv65ETYkTUDsrWW+gJ4LAetNdMIlvP
ujCpee0HtH3T4d4q76cwnO5x06ux3ojbG8AE0eUfDVy+k+WFjEXnHFxECl/OojTQ
2JOYfh7qmaqrb/Eaxacj0KaAr273w3jyO/1FFVz3kXzTnS5dt/909k7F5dwL97Xh
nKTdYP3C3CWM91q/RmBW1q69AdnwNZl1n+egYfZg//BLEaAKzxAXgZKhgUNoeStx
F0d2CUJsuaEmu8gTV603Y2y4eQVhNSmPmYIvXXTVtjcSMN9+snLifZFiKOzY979l
tBNEIk1czRWkjiQyqrDxh/snOWaJmH1jEb/BVg84on9ZD5bn4TFu6VvN4weqiwoI
THWV+QazNaYdm3NI/kl6SOiNgeabe528iumCtyzibX8G2w4RTMhQ+7IegGJ2Cwrw
HA2+85AoqmDuTe+V30lUIfFwZdiD+wt6wNHcGizdBfqOPa2PQS4=
=FbTq
-----END PGP SIGNATURE-----

12
incl/header.scm Normal file
View file

@ -0,0 +1,12 @@
;;; incl/header.scm
;; A title and a list of links to display at the top of the page
(define (make-link uri)
(if (pair? uri)
`(a ,(car uri) ,(cdr uri))
`(a ,uri)))
`((h1 ,title)
,@(map make-link header-uris)
(p))

25
incl/util.scm Normal file
View file

@ -0,0 +1,25 @@
;;; incl/util.scm
;; A bunch of utilities that I'll probably want to just build into stxge
(define (join-path type x . xs)
;; Join (cons x xs) into a slash-delimited string
(string-join (cons x xs) "/" type))
(define (make-relative-uri type x . xs)
(build-uri-reference #:path (apply join-path type (cons x xs))))
(define (make-capsule-uri-builder prefix)
;; Generate a function that creates URIs relative to the capsule's root
(lambda (x . xs) (apply make-relative-uri 'prefix prefix x xs)))
(define build-uri/capsule (make-capsule-uri-builder "~snit"))
(define header-uris
(list (cons (build-uri-reference #:path "/") "Root")
(cons (build-uri/capsule "") "Home")))

View file

@ -1,21 +0,0 @@
# ~snit
Hello, I am ~snit, an avid enjoyer of all things isekai, as well as the administrator of isekai.rocks. This capsule is my own personal space to talk about isekai (or other weeb media), technology, privacy/security, linguistics, and other esoteric topics.
## Topics
Fair warning that there's not much here at the moment; some of these sections have nothing interesting.
=> ./comp/index.gmi ~/comp/
=> ./lang/index.gmi ~/lang/
=> ./meta/index.gmi ~/meta/
=> ./rand/index.gmi ~/rand/
=> ./weeb/index.gmi ~/weeb/
## Meta
All original content in this capsule is licensed under the following terms:
=> ./LICENSE.gmi License
The source for the capsule can be found here:
=> https://forge.fsky.io/snit/gemini.git
For questions, comments, concerns, or just to chat, you can contact me here:
=> ./contact.gmi Contact

View file

@ -1,2 +0,0 @@
# ~/snit/lang/
Linguistic-related content. Languages (natural or artificial), linguistics, orthography, etc. is placed here.

View file

@ -1,10 +0,0 @@
# ~snit/meta/
The purpose of this one is threefold; it contains:
* content about this Gemini capsule (~snit)
* nonessential information regarding isekai.rocks and its associated services
* writing about me as a person (as opposed to just my opinions) for whatever reason
There's a good chance those first two will also be found in ~snit/comp/, as well.
=> ./links.gmi Link Garden
=> ./post-ideas.gmi Post Ideas

View file

@ -1,10 +0,0 @@
# Link Garden
A list of sites I like or from people I know, sorted by protocol.
Hoping to add more darknet sites at some point (Ygg, Tor, I2P); I haven't taken
a good look at any of them yet really.
## HTTP
=> https://nyx.everypizza.im
=> https://squarebowl.club
=> https://telepath.im

View file

@ -1,50 +0,0 @@
# Post Ideas
A collection of ideas that I'd like to write about if I ever feel like it, sorted by category, but in no particular order.
## /comp/
* That one time I tried replacing GNU coreutils with uutils on Gentoo
* My failed attempt to use a pure TTY environment on a spare laptop
* Language-oriented programming
* UNIX philosophy extremism
* Why writing a compiler/interpreter is a good project regardless of skill level
* More specialised software/services to replace various aspects of the web, in the spirit of UNIX philosphy "do one thing and do it well"
* My browser setup, or really any other odd aspect of my current setup
* A list of things I would like to see in my ideal operating system, POSIX-compatibility be damned
* Tag-based filesystem benefits from a perspective other than media curation (system administration, programming, everyday usage)
* Customisation and choice in software versus having a cohesive system, and how to have both at once (standard interfaces between programs?)
## /lang/
* Holistic conlanging
* Measuring relative complexity of various languages
* Lexicalisation in Toki Pona
* Neopronouns lol
* Every argument boils down to an argument of semantics in the end, it seems
* How the medium of writing affects average message lenth
* Literally anything about phonoaesthetics/phonosemantics/sound symbolism
* Dialects of English that are unique to specific spaces of the internet (i.e. 4chan)
* Case study a polysynthetic language to see how various features work together
* Case study a single (generally polysynthetic) feature across several languages to see different ways it can develop and be used
* The difference between being polysynthetic and just being really really synthetic
## /weeb/
* Literally anything I'm consuming now (just monologue into a .gmi instead of Matrix)
* Isn't it interesting that SAO takes an oddly positive outlook on being trapped in a death game that kills four thousand?
* Slavery is pretty common in isekai series. What's up with that?
* Shield Hero vs Ningen Fushin in regards to portrayals of trust (or the lack thereof)
* Why I like certain objectively bad series and why I hate some objectively good ones
* Development of isekai as a genre and its associated tropes over time
* Of course, the question of what even counts as "isekai" (its probably not what you think)
* Why I like isekai specifically so much
* Comparison of certain common isekai worldbuilding tropes across series (i.e. magic, races, gods, countries, monsters, adventurers, etc.)
* More series should dedicate time to showing viewers exactly what the main character is fighting for; long prologues are a really good way to do this (i.e. Mushoku Tensei, Vinland Saga, Oshi no Ko)
## /meta/
* Just a list of things I like regardless of what it is
## /rand/
* Why people should stop defaulting to a blog structure for everythng, and possible alternatives to use instead
* Old Minecraft versions and Luanti feel very eerie and liminal, but modern Minecraft doesn't. How come? What causes it?
* Gatekeeping is good, actually (sometimes) (i.e. IRC, 4chan)
* What makes a good Minecraft (or general in-game) currency?
* Why Minecraft is a really bad game for (purely in-game) capitalism most of the time
* Why do people find suffering to be cool? The kind of suffering that you see in people who fake mental illness or disability, or that you see in certain cases of chuunibyou

View file

@ -1,5 +1,4 @@
```
THE STRONGEST PUBLIC LICENSE
`((pre " THE STRONGEST PUBLIC LICENSE
Draft 1, November 2010
Everyone is permitted to copy and distribute verbatim or modified
@ -14,5 +13,4 @@ as the name is changed.
This program is distributed in the hope that it will be THE STRONGEST,
but WITHOUT ANY WARRANTY; without even the implied warranty of
USEFULNESS or FITNESS FOR A PARTICULAR PURPOSE.
```
USEFULNESS or FITNESS FOR A PARTICULAR PURPOSE."))

16
site/comp.scm Normal file
View file

@ -0,0 +1,16 @@
;;; site/comp.scm
(import "util.scm")
(define title "~snit/comp/")
`(,@(import "header.scm")
(p "This section is for technology-related content. Most of it is probably related to programming or especially just really bad takes on how operating systems should work.")
(p)
(p "The following are listed in no particular order:")
,@(map (lambda (path name) `(a ,(make-relative-uri 'suffix "." path) ,name))
(list "gemini-yggdrasil" "hier7" "capslock" "browser-tabs")
(list "Hosting Gemini Capsules via Yggdrasil"
"Regarding hier(7) in $HOME"
"Making the CapsLock Key More Useful"
"Browser Tabs are Stupid")))

View file

@ -0,0 +1,49 @@
;;; site/comp/browser-tabs.scm
(import "util.scm")
(define title "Browser Tabs are Stupid")
`(,@(import "header.scm")
(p "I hate tabs in browsers. Well, I hate when any program adds built-in tab support. The concept of built-in tabs inherently violates the concept of programs doing only one thing and one thing well.")
(p)
(p "In an ideal world*, there should be genuinely no reason for programs to each write their own implementation of tabs. They aren't compatible with each other, limiting their flexibility, and each implementation looks and acts different, so you have to configure them and learn how they work separately for each and every program.")
(p)
(p "In an ideal world*, you could just have a single program that you run your programs in which will automatically manage tabbing them together. You only need to configure one thing to have tabs work the same globally, and you can put any program in those tabs.")
(p)
(p "Luckily, these programs already exist. Many window managers come with support for tabbing windows, such as i3/Sway or Haiku's; and there're several programs that implement tabs in the terminal, such as tmux or screen. So if they already exist, why not just use them?")
(p)
(p "Even more ironically, certain newer browsers are actually implementing EVEN MORE features found in tiling window managers. Want two tabs side-by-side now? Browsers like Vivaldi can do that natively. A lot of browsers include support for grouping tabs by category. Now imagine these tiled or grouped tabs worked seamlessly with every other program you have running.")
(p)
(h2 "Eliminating Browser Tabs")
(p "Since I already have a tiling window manager, I could theoretically just find a browser that doesn't come with support for tabs, and just use that in combination with my window manager. Unfortunately, not many such browsers exist, and the ones that do are so outdated that they're next to useless on any site made in the past decade or two. Surf, for example, seems to just freeze on most websites.")
(p)
(p "Its unfortunate, but the alternative is to just use a tabbed browser, and do what I can to pretend it doesn't have tabs. I've opted for Firefox in this case. Firefox has extensions to force each tab into its own window, and its flexible enough to let me customise the CSS to hide the now-useless tab bar.")
(p)
(p "This extension, which I use, is open source and has worked mostly flawlessly for me:")
(a ,(build-uri 'https #:host "gitlab.com"
#:path (join-path 'prefix "adsum" "firefox-notabs"))
"Firefox No Tabs")
(p)
(p "The only annoyance, documented in issue #2, is that certain special Firefox tabs just don't get their own windows, but these tabs are rarely-used, so its not a big problem.")
(p)
(p "The method to remove tabs from the UI is linked in the README, but I'll also just tell you here. You'll need to go to your profile folder in ~/.mozilla/firefox/. For example, mine is called ~/.mozilla/firefox/vhj2i22f.default-release. Within it, you'll create chrome/userChrome.css with the following content:")
(pre "#TabsToolbar{ visibility: collapse !important }")
(p)
(p "And that's literally all I had to do. For the past few months, I've used this exact setup in combination with the Sway window manager with zero problems. There might be a performance penalty from doing this, but, if there is, I haven't noticed anything personally.")
(p)
(p "Also, you may notice that this setup is basically just recreating Electron apps, but it has a few crucial differences. For one, as mentioned, I don't notice any real performance penalty from having multiple windows open at once in the same way I do with Electron. Secondly, I can have multiple instances of the same app open using this method, which to my knowledge isn't possible/easy to do with Electron. Third, Wayland support with Electron apps fucking sucks, but in Firefox a lot of things just seem to work fine. And lastly, I get all the benefits of Firefox's configuration, such as blocking ads and trackers, or being able to use Vim keybinds.")
(p)
(h2 "This is not an ideal world")
(p "Earlier I said \"in an ideal\" world programs wouldn't implement their own tabs. Unfortunately, this is not an ideal world. I do have to admit that I at least UNDERSTAND why so many programs have built-in tabs. The reality is that most people don't use tiling window managers; they don't use Haiku; they use Windows or Mac, or a generic floating window manager that's actually incredibly bad at managing windows, and has no support for grouping them into tabs.")
(p)
(p "In such an environment, having twenty separate windows to manage by manually positioning and resizng them would be an absolute nightmare, so it makes perfect sense that these programs all have to take matters into their own hands.")
(p)
(p "I don't have to like it, but it does really suck. I do find it funny that browsers are becoming full-blown tiling window managers though; goes to show that its just a better way of managing windows.")
(p)
(p "Actually, if this WERE an ideal world, the web never would've gotten to the point where we need to implement full-blown window managers. Web browsers are basically full operating systems unto themselves at this point, each website a full desktop program. In an ideal world, the web would'nt've become a massive monolith that a typical person can spend literally 100% of their digital activities within.")
(p)
(p "But I digress; the point is that built-in tabs are bloat, and tiling window manager folks can just delete them entirely and use the tabs they already have to achieve the same thing but better. Unfortunately, though, if you didn't think tabs were bloat before, doing this does objectively make them bloat, since they're a feature you don't even use, yet still have full support for (worse, you had to actually ADD MORE to pretend they aren't there).")
(p)
(p "I don't know if this was informative at all (I feel like I couldn't word any of this properly), or if you even necessarily agree, but, as always, feel free to message or email me your thoughts or questions."))

83
site/comp/capslock.scm Normal file
View file

@ -0,0 +1,83 @@
;;; site/comp/capslock.scm
(import "util.scm")
(define title "Making the CapsLock Key More Useful")
`(,@(import "header.scm")
(p "The CapsLock key is one of the most useless keys on the keyboard for me, yet placed in the single best place a non-letter key could be placed. It's an obvious candidate for people looking to improve their keyboard layout.")
(p)
(p "I often heard people saying they rebound it to control or escape, which both sounded equally good to me, so I was never sure which to use. Then I heard someone mention that they use the key for BOTH at once. You press it and get the escape key, and hold it to get the control key. This sounded perfect, and is now in fact my single most-used key rebinding, to the point where I feel helpless when on a system without it.")
(p)
(p "Originally, I used some odd X11-specific software to achieve the rebind, but it was really flaky, and, of course, didn't work in a TTY or on Wayland. I then switched to interception-tools with the dual-function-keys plugin, but it's Linux-specific, and I couldn't even get it working on Gentoo, but it worked flawlessly on Arch.")
(p)
(h2 "Keyd")
(p "Nowadays I use a piece of software called keyd. Its super simple, works on X11, TTY, and Wayland, and works* on FreeBSD.")
(p)
(q "*On FreeBSD, it currently locks your input in a TTY, so it really only works on X11 and Wayland.")
(p)
(h3 "Configuration")
(p "The configuration file goes in /etc/keyd/default.conf. Its capable of a lot of things, which you can find in its documentation, but this particular rebind is incredibly simple:")
(pre "[ids]"
"*"
""
"[main]"
"capslock = overload(control, esc)")
(p)
(h3 "Starting the Daemon")
(p "Now you just need to start the daemon. It comes with a systemd service file out of the box, so nothing special is needed if that's your init of choice")
(p)
(p "On systems running OpenRC, such as Gentoo, I recommend using the service file written in this blog post:")
(a ,(build-uri 'https #:host "technex.us"
#:path "/2024/07/keyd-on-gentoo-with-openrc-and-kde-plasma/")
"Keyd on Gentoo with OpenRC and KDE Plasma")
(p)
(p "For convenience, I'll paste the script here. It should be put into /etc/init.d/keyd:")
(pre "#!/sbin/openrc-run"
""
"# Description of the service"
"description=\"keyd key remapping daemon\""
""
"# The location of the keyd binary"
"command=\"/usr/local/bin/keyd\""
"#command_args=\"-d\""
"pidfile=\"/run/keyd.pid\""
""
"depend() {"
" need localmount"
" after bootmisc"
"}"
""
"start() {"
" ebegin \"Starting keyd\""
" start-stop-daemon --start --background \\"
" --user root \\"
" --exec $command \\"
" --make-pidfile --pidfile $pidfile --"
" eend $?"
"}"
""
"stop() {"
" ebegin \"Stopping keyd\""
" start-stop-daemon --stop --pidfile $pidfile"
" eend $?"
"}"
""
"restart() {"
" ebegin \"Restarting keyd\""
" start"
" eend $?"
"}")
(p)
(p "Once you have that, you can start and enable the daemon like any other.")
(p)
(p "FreeBSD has a service script built-in, but, as mentioned earlier, keyd on FreeBSD doesn't work in a TTY, so I actually just recommend starting keyd with your window manager. Note that you have to run it as root, though. I put the following into my /etc/doas.conf to let me run it without a password:")
(pre "permit nopass :wheel cmd keyd")
(p)
(h2 "Caveats")
(p "I find keyd to work great for my use-case, but that's not to say it isn't without it's flaws. Of course, there's the big one with FreeBSD, which does suck, but I don't use a TTY often enough to be too annoyed.")
(p)
(p "Another caveat is that it isn't particularly good at Unicode. It seems to emit Unicode characters as macros, using a really hacky solution, and I never actually managed to get it working. Github issues suggest that even when it does work, Wayland users still can't do it in Electron apps. Not that I use Electron anymore, but it's still something to look out for.")
(p)
(p "These caveats are fine with me, but I could see them being deal-breakers for others, so do be aware of them. There're plenty of alternatives, like interception-tools/dual-function-keys, or kmodmap, which can achieve the same thing."))

View file

@ -0,0 +1,40 @@
;;; site/comp/dotfiles-rob-pike.scm
(import "util.scm")
(define title "Rob Pike on Dotfiles")
`(,@(import "header.scm")
(p "Rob Pike, 2012-08-02")
(a ,(build-uri 'https #:host "plus.google.com"
#:path "/101960720994009339267/posts/R58WgWwN9jp")
"Original Google+ Post")
(a ,(build-uri 'https #:host "web.archive.org"
#:path (join-path 'prefix
"web" "20190317000040" "https://plus.google.com"
"101960720994009339267" "posts" "R58WgWwN9jp"))
"Archived on Wayback Machine")
(p)
(h2 "Post Text")
(p "A lesson in shortcuts.")
(p)
(p "Long ago, as the design of the Unix file system was being worked out, the entries . and .. appeared, to make navigation easier. I'm not sure but I believe .. went in during the Version 2 rewrite, when the file system became hierarchical (it had a very different structure early on). When one typed ls, however, these files appeared, so either Ken or Dennis added a simple test to the program. It was in assembler then, but the code in question was equivalent to something like this:")
(pre " if (name[0] == '.') continue;")
(p "This statement was a little shorter than what it should have been, which is")
(pre " if (strcmp(name, \".\") == 0 || strcmp(name, \"..\") == 0) continue;")
(p "but hey, it was easy.")
(p)
(p "Two things resulted.")
(p)
(p "First, a bad precedent was set. A lot of other lazy programmers introduced bugs by making the same simplification. Actual files beginning with periods are often skipped when they should be counted.")
(p)
(p "Second, and much worse, the idea of a \"hidden\" or \"dot\" file was created. As a consequence, more lazy programmers started dropping files into everyone's home directory. I don't have all that much stuff installed on the machine I'm using to type this, but my home directory has about a hundred dot files and I don't even know what most of them are or whether they're still needed. Every file name evaluation that goes through my home directory is slowed down by this accumulated sludge.")
(p)
(p "I'm pretty sure the concept of a hidden file was an unintended consequence. It was certainly a mistake.")
(p)
(p "How many bugs and wasted CPU cycles and instances of human frustration (not to mention bad design) have resulted from that one small shortcut about 40 years ago?")
(p)
(p "Keep that in mind next time you want to cut a corner in your code.")
(p)
(p "(For those who object that dot files serve a purpose, I don't dispute that but counter that it's the files that serve the purpose, not the convention for their names. They could just as easily be in $HOME/cfg or $HOME/lib, which is what we did in Plan 9, which had no dot files. Lessons can be learned.)"))

View file

@ -0,0 +1,77 @@
;;; site/comp/gemini-yggdrasil.scm
(import "util.scm")
(define title "Hosting Gemini Capsules via Yggdrasil")
`(,@(import "header.scm")
(p "Getting a Gemini capsule running on Yggdrasil was harder than I would have thought. The main complexity came from the fact that Gemini has mandatory TLS, combined with Yggdrasil predominantly being bare IPv6 addresses.")
(p)
(p "I suspect that this would have been no different than hosting a clearnet capsule had I been using Alfis to get an actual domain name, but I haven't set that up.")
(p)
(q "NOTE: This guide assumes the use of gmid as the server. I have no clue how this works (or doesn't) on any other server.")
(p)
(h2 "Prerequisites")
(p "This is NOT a guide to setting up Yggdrasil, nor for setting up gmid. I assume you already have a working Yggdrasil setup, as well as know how to run gmid for clearnet capsules.")
(p)
(h2 "Self-signed Certificates")
(p "First of all, we have to generate a certificate. If you use a CA normally, you can't use their certificates; they don't usually issue certificates for IP addresses. This leaves us to issue our own, but Gemini explicitly allows (and encourages) self-signed certificates, so you should probably use a self-signed one anyways.")
(p)
(p "I used OpenSSL to generate the certificate we need. The gencert program included in gmid isn't meant to work with raw IP addresses, so it results in some sort of SANS error.")
(p)
(q "NOTE: I couldn't find much information regarding how to achieve this, so, to be transparent, it should be noted that the following file was created with help from LLM. It worked in my case, but your mileage my vary.")
(p)
(p "First we need to create a configuration file with the following content (replace 200:: with your Yggdrasil address):")
(pre "[req]"
"default_bits = 2048"
"prompt = no"
"default_md = sha256"
"req_extensions = req_ext"
"distinguished_name = dn"
""
"[dn]"
"CN = 200::"
""
"[req_ext]"
"subjectAltName = @alt_names"
""
"[alt_names]"
"IP.1 = 200::"
""
"[v3_ca]"
"subjectAltName = @alt_names"
"basicConstraints = CA:TRUE"
"keyUsage = digitalSignature, keyEncipherment, keyCertSign")
(p)
(p "The file can be named whatever; we'll be passing it manually into OpenSSL next:")
(pre "openssl req -x509 -nodes \\"
" -days 365 \\"
" -keyout ipv6.key \\"
" -out ipv6.pem \\"
" -config $YOUR_CONFIG \\"
" -extensions v3_ca")
(p)
(p "Finally, move the resulting ipv6.key and ipv6.pem files to your preferred location. I put my gmid keys in /etc/ssl/gmid/.")
(p)
(h2 "Configuring gmid")
(p "On my clearnet capsule, I'd used a wildcard statement for the listen declaration, but apparently that doesn't fly here. Replace the wildcard with the same IP address as used in the server declaration part. Also, do not surround them with brackets.")
(p)
(p "Here's an example:")
(pre "server \"200::1\" {"
" listen on 200:1 port 1965"
""
" root \"/srv/gmi/yggsite\""
""
" cert \"/etc/ssl/gmid/ipv6.pem\""
" key \"/etc/ssl/gmid/ipv6.key\""
"}")
(p)
(a ,(build-uri 'https #:host "github.com"
#:path "/omar-polo/gmid/issues/25")
"Relevant GitHub discussion")
(p)
(p "Start up gmid and you should be able to connect!")
(p)
(p "As an aside, even though you can't put brackets in gmid's configuration, amfora won't work unless you DO put brackets into the URL:")
(pre "amfora gemini://[200::1]")
(p "I'm not sure if this is a problem with gmid or amfora, or how it works on other clients, but I figured I'd note it down here, because I spent an extra twenty minutes thinking this wasn't working just because I stopped using brackets on amfora after gmid told me to."))

180
site/comp/hier7.scm Normal file
View file

@ -0,0 +1,180 @@
;;; site/comp/hier7.scm
(import "util.scm")
(define title "Regarding hier(7) in $HOME")
`(,@(import "header.scm")
(p "Taking a look at hier(7) is a valuable way to understand how your Unix-like system is structured. It tells you exactly what each directory on your filesystem does, so you always know exactly where to put system files.")
(p)
(h2 "The Hierarchy for System Files")
(p "Taking a look at the overall structure, you may notice that a lot of directory names seem to be repeated, but in different locations. You'll also notice that these directories seem to be structured roughly the same way the / directory is. For example, you have /bin/, /usr/bin/, and /usr/local/bin/.")
(p)
(p "On my Arch Linux install, according to hier(7):")
(ul (li "/ is for critical utilities required to boot and repair the system")
(li "/usr/ is the main place system files get installed to, including all of the programs installed by the package manager")
(li "/usr/local/, to my understanding, is where you'd place system files that you compiled and installed manually, rather than using the package manager"))
(a ,(build-uri 'https #:host "man.archlinux.org" #:path "/man/hier.7")
"Arch Linux hier(7)")
(p)
(q "It is worth noting that Arch Linux's manpage is somewhat outdated. Arch has taken steps to merge the first two directories in recent years. The /bin/ and /lib/ directories are now symlinks to their /usr/ counterparts.")
(p)
(p "On FreeBSD, according to hier(7), the equivalent directories are as follows:")
(ul (li "/ is essentially the same as on Arch Linux")
(li "/usr/ seems to be for core operating system files that aren't required for boot or repair")
(li "/usr/local/ is for system files not part of the core operating system, such as package files or locally-compiled programs"))
(a ,(build-uri 'https #:host "man.freebsd.org"
#:path "/cgi/man.cgi" #:query "hier(7)")
"FreeBSD hier(7)")
(p)
(p "As you can see, there seem to be three separate \"\"root\"\" directories, each one with a specific purpose. However, these aren't the only three directories that seem to be root directories. The /root/ and /home/$USER/ directories, which act as user home directories, ALSO seem to be root directories, but its nearly impossible to tell at first, because they use an entirely different set of directories.")
(p)
(h2 "The Hierarchy for User Files")
(p "The user's home directory follows its own hierarchy conventions completely unlike any of the aforementioned system tree hierarchies. Even worse, the home directory makes extensive use of dotfiles, which are an unintended bug that's most often leveraged by lazy programmers who don't want to learn how the system they're programming on works.")
(a ,(make-relative-uri 'suffix ".." "dotfiles-rob-pike") "Rob Pike on Dotfiles")
(p)
(p "The home directory tree as compared to the system tree:")
(ul (li "~/.config/, as opposed to /etc/")
(li "~/.cache/, as opposed to /var/cache/")
(li "~/.local/bin/, as opposed to /bin/")
(li "~/.local/share/, as opposed to /share/")
(li "~/.local/state/, as opposed to /var/lib/"))
(a ,(build-uri 'https #:host "specifications.freedesktop.org"
#:path "/basedir-spec/latest/")
"XDG Base Directory Specification")
(p)
(p "As you can see, the user's home directory has all of the same data as any of the system trees, but with completely different names, all leveraging the dotfile bug. Perhaps I would've been fine if the files made use of the usual names, but were all placed in ~/.local/, because then it'd just mean the tree root isn't at ~/, but at ~/.local/, but this isn't the case.")
(p)
(p "Even worse, even though all of these directories can be moved using $XDG_*_HOME variables, an incredible number of programs completely ignore the XDG Base Directory Specification, and hardcode the path, or place their files straight into ~/, completely ignoring any standard directories, with no possible way to change it. Some of these programs think they're so special that they even refuse to consider this a bug, like OpenSSH with ~/.ssh/.")
(a ,(build-uri 'https #:host "wiki.archlinux.org"
#:path "/title/XDG_Base_Directory"
#:fragment "Hardcoded")
"The Arch Wiki's list of programs using hardcoded dotfiles")
(a ,(build-uri 'https #:host "web.archive.org"
#:path (join-path 'prefix
"web" "20190925004614"
"https://bugzilla.mindrot.org" "show_bug.cgi")
#:query "id=2050")
"OpenSSH bug report")
(p)
(p "To finish off talking about the home directory tree, we can't forget to mention the XDG User Directories:")
(ul (li "~/Downloads/")
(li "~/Desktop/")
(li "~/Documents/")
(li "~/Music/")
(li "~/Pictures/")
(li "~/Public/")
(li "~/Templates/")
(li "~/Videos/"))
(a ,(build-uri 'https #:host "wiki.archlinux.org"
#:path "/title/XDG_user_directories")
"The Arch Wiki's page on XDG User Directories")
(p)
(p "Honestly, other than the fact that they use capital letters, which is a personal preference thing, I can't really complain about these. I'd prefer them somewhere else, but the xdg-user-dirs tool combined with $XDG_CONFIG_HOME/user-dirs.dirs lets me move and rename them, which most programs do actually seem to respect.")
(p)
(p "The main point here is that system files have THREE locations that have the exact same directory structure, but user files aren't the same. You can't leverage existing knowledge to know where to put user files, and programs have to handle user files as an entirely separate case from system files. The directory structure CAN be changed, but not all programs respect those changes, and some completely ignore the structure to begin with, which seems to be caused predominantly due to a specific bug allowing lazy programs to shove files wherever they want with the knowledge that those files will be \"\"hidden\"\" and thus not a bother.")
(p)
(h2 "My Current Home Directory Setup")
(p "With all this said, I decided to make use of what I could in order to make my home directory mimic the structure of the system trees, as well as to stop making use of dotfiles as hidden directories.")
(p)
(h3 "Unhiding Dotfiles")
(p "This one was pretty simple. All I really had to do is add to my ~/.shrc:")
(pre "alias ls=\"ls -A\"")
(p "I also added to my $XDG_CONFIG_HOME/ranger/rc.conf for the ranger file manager:")
(pre "set show_hidden true")
(p)
(h3 "Undotting My Dotfiles")
(p "This predominantly involved adding a bunch of variables to my ~/.profile:")
(pre "## Add /bin for executables instead of .local/bin"
"PATH=\"${PATH}:${HOME}/bin\""
""
"## Should replace .config, .cache, and .local/{share,state} for most programs"
"XDG_CACHE_HOME=\"${HOME}/var/cache\"; export XDG_CACHE_HOME"
"XDG_CONFIG_HOME=\"${HOME}/etc\"; export XDG_CONFIG_HOME"
"XDG_STATE_HOME=\"${HOME}/var/lib\"; export XDG_STATE_HOME"
"XDG_DATA_HOME=\"${HOME}/share\"; export XDG_DATA_HOME"
""
"## These programs must be configured to follow specification"
"### Bash"
"HISTFILE=\"${XDG_STATE_HOME}/bash/history\"; export HISTFILE"
""
"### Python (>3.12)"
"PYTHON_HISTORY=\"${XDG_STATE_HOME}/python/history\"; export PYTHON_HISTORY"
"PYTHONPYCACHEPREFIX=\"${XDG_CACHE_HOME}/python\"; export PYTHONPYCACHEPREFIX"
"PYTHONUSERBASE=\"${XDG_DATA_HOME}/python\"; export PYTHONUSERBASE")
(p)
(h3 "Moving Desktop Files")
(p "As mentioned earlier, the xdg-user-dirs tool in combination with $XDG_CONFIG_HOME/user-dirs.dirs achieves what I want:")
(pre "XDG_DESKTOP_DIR=\"$HOME/tmp\""
"XDG_TEMPLATES_DIR=\"$HOME/tmp\""
"XDG_PUBLICSHARE_DIR=\"$HOME/tmp\""
"XDG_DOWNLOAD_DIR=\"$HOME/tmp\""
""
"XDG_PICTURES_DIR=\"$HOME/media/img\""
"XDG_DOCUMENTS_DIR=\"$HOME/media/doc\""
"XDG_MUSIC_DIR=\"$HOME/media/audio\""
"XDG_VIDEOS_DIR=\"$HOME/media/video\"")
(p "This one probably needs some explaining.")
(p)
(p "To start, the hier(7) manpage says that /media/ is meant for removable media, like CDs or floppy disks, with a subdirectory for each type of media (i.e. /media/floppy[0-9]/), which clearly isn't quite what I'm using it for here. However, to begin with, I normally only use /mnt/ to mount external drives, but I COULD see myself mounting an external drive dedicated specifically to hosting my media files at ~/media/, if I'd been a desktop user. Of course, I'm also forgoing the media type subdirectories, which I do because I can only see myself mounting multiple drives here under the condition that its a single LVM or ZFS pool. Essentially, I'm bending the meaning of ~/media/ here to OPTIONALLY mean \"removable media\", and more predominantly mean \"media files\".")
(p)
(p "It might also seem weird that I listed so many of them at ~/tmp/, but hear me out here. For one, I don't have a desktop, since I use a tiling window manager, and I have zero clue what the templates or public share directories are for, so I combined these all into my downloads directory to act as a large catch-all for any file I'm not immediately sure should go elsewhere. The reason I put these in ~/tmp/ specifically, though, is because I've found that the only files that remain in my downloads directory for a long time tend to be those that I really only needed once for a particular purpose, such as a Linux ISO image to write to a USB drive. Thus, I've actually gone so far as to add the following to my /etc/fstab:")
(pre "tmpfs /home/snit/tmp tmpfs rw,relatime 0 0")
(p "Which, of course, means that my ~/tmp/ directory will be cleared every time I reboot; this may seem inconvenient to some, so I don't recommend this part, but, again, I only use this directory for files I'm probably gonna delete soon anyways.")
(p)
(h3 "Issues I've Encountered")
(p "The main issue I have is just with software that doesn't follow the specifications properly. OpenSSH places files in ~/.ssh/, Firefox has ~/.mozilla/ (I'm told this will soon be fixed), and it seems that changing settings in Firefox's filechooser dialogue causes a file to be created at ~/.config/dconf/user, even though dconf claims to support $XDG_CONFIG_HOME.")
(p)
(p "There's also ~/.profile and ~/.shrc. I can move the latter using ENV, but the former to my knowledge simply can't be moved. However, I've opted to leave both as is and accept them, simply because FreeBSD seems to put similar files straight into /, so it technically has the consistency I'm looking for here, even if its slightly inelegant.")
(p)
(h3 "Directory Structure")
(p "Currently this is what my home directory looks like:")
(ul (li "~/bin/ for local scripts and executables (replaces ~/.local/bin/)")
(li "~/etc/ for configuration files (replaces ~/.config/)")
(li "~/media/ for media files like images or documents")
(li "~/media/audio for audio files")
(li "~/media/video for video files")
(li "~/media/img for images (this actually contains a lot of videos for convenience, but I might change that)")
(li "~/media/doc for text-based files like PDF documents and personal notes")
(li "~/mnt/ as an alternative to /mnt/ for easier access")
(li "~/share/ for architecture-agnostic data (replaces ~/.local/share/); this is actually where I put my desktop wallpapers")
(li "~/src/ for program source code")
(li "~/src/foreign/ for code I didn't write for organisation purposes (might also add ~/src/local/)")
(li "~/tmp/ for the default download directory, mounted as a tmpfs")
(li "~/var/cache/ for cache data (replaces ~/.cache/)")
(li "~/var/lib/ for state data (replaces ~/.local/state)")
(li "~/.mozilla/ for Firefox data (can't move)")
(li "~/.ssh/ for OpenSSH data (can't move)")
(li "~/.profile for my shell profile (can't move)")
(li "~/.shrc for my interactive shell settings"))
(p)
(h2 "Conclusion")
(p "Mainly I just wish user directory trees worked similar to system trees. Why can't we leverage existing knowledge for this? Why do I have to write special cases based on whether its a system or user tree? Why can't programs just follow standards properly?")
(p)
(p "It'd be cool if, for example, I could actually compile a package and install it to my user directories just the same as if I were installing it to the system itself. In conjunction with Plan 9's bind(1), I could see this being genuinely useful on multi-user systems like pubnixes. After all, I can download, compile, and run that program regardless, so, in my opinion, there's no real point in NOT giving me the option to use the package manager in my own home directory.")
(p)
(p)
(h2 "Addendum I")
(p "Just wanted to add that I no longer mount ~/tmp/ as a tmpfs. It honestly works fine for the most part, but I had transmission set to download incomplete torrents to ~/tmp/ before moving them to ~/media/ when finished, which gave me a lot of out-of-memory errors if I downloaded a large enough torrent, or a lot of torrents at once.")
(p)
(p "Also, I use trash-cli and have rm aliased to it. When ~/tmp/ is mounted as a tmpfs, it actually gets its own ~/tmp/.Trash/ directory, as its a different filesystem from /home. Its not a big deal but its somewhat annoying having two separate trash directories. And if you haven't figured it out already from uh everything above this, annoyances when it comes to directories are intolerable on my system.")
(p)
(p "So I don't mount it anymore, and instead just use it as a regular directory that I clear out sometimes. The only real benefit it used to bring was clearing out automatically on shutdown, but I could probably just add an rm line to my .profile for a similar effect.")
(p)
(h2 "Adendum II")
(p "I've made a couple more changes since the last update.")
(p)
(p "First, I've updated my ~/.profile to work similarly to Arch's /etc/profile, which actually outsources most of its work to files in /etc/profile.d/. I've opted to do the same thing, with specific files for my XDG Base Directory compliance, and for setting other variables related to Wayland or fcitx5. Since I'd put most of ~/.profile in ~/etc/, and ~/.shrc can be put literally anywhere (as it's set by $ENV), I've opted to move it to ~/etc/sh/shrc. This reduces my total number of cringe noncompliant dotfiles in $HOME to three.")
(p)
(p "The other change that I've made is the addition of ~/libexec/ and ~/sbin/, which I think are truly underutilised directories even in the system hierarchies (Arch foregoes them entirely in favour of just using /bin/ and /lib/).")
(p)
(p "I use ~/libexec/ for anything I'd normally put in ~/bin/, but that I'd rarely, if ever, run directly. Most of these are scripts related to setting up my window manager, and are thus only ever executed by my window manager. There's also one that I have run at shell startup, which prints every dotfile that clutters my home directory, and automatically deletes all dotfiles in a specified list (only deleting what I know I don't care about). I mostly added ~/libexec/ because I've been thinking of ways to keep my $PATH namespace less cluttered, and this is something easy to implement AND quite elegant in my opinion.")
(p)
(p "I don't actually use ~/sbin/ on my home systems. There's only one script I use at home that needs to be run as root, and it's run by my window manager, so I've opted instead to just give it a nopass option in my /etc/doas.conf, and place it in ~/libexec/. On isekai.rocks, though, I do actually use ~/sbin/. The main two scripts I use in ~/sbin/ are one to sync the live isekai.rocks capsule to the git repository, and another to set up a new user account on the pubnix. There was also previously one that updated Minecraft mods, automatically creating new zip files for download, and restarting the server to load the new mods.")
(p)
(p "So, to recap, the changes I've made since the original post were:")
(ul (li "Stop mounting ~/tmp/ as a tmpfs")
(li "Move ~/.shrc to ~/etc/sh/shrc")
(li "Create ~/libexec/")
(li "Create ~/sbin/")))

38
site/contact.scm Normal file
View file

@ -0,0 +1,38 @@
;;; site/contact.scm
(import "util.scm")
(define title "Contact")
(define (make-matrix-uri type mxid)
(build-uri 'matrix #:path (join-path 'infix type mxid)))
(define (make-xmpp-uri localpart domainpart)
(build-uri 'xmpp #:path (string-append localpart "@" domainpart)))
`(,@(import "header.scm")
(p "The main media I use are as follows:")
(a ,(make-xmpp-uri "snit" "isekai.rocks")
"snit@isekai.rocks (XMPP) (Preferred)")
(a ,(make-matrix-uri "u" "rinte:isekai.rocks")
"@rinte:isekai.rocks (Matrix)")
(a ,(build-uri 'mailto #:path (string-append "snit" "@" "cock.li"))
"snit@cock.li (E-Mail)")
(p)
(h2 "Secondary Accounts")
(p "I also own the following accounts, although I prefer you use the accounts listed above if you wish to contact me. Note that this is not a comprehensive list.")
(p)
(h3 "Matrix")
,@(map (lambda (mxid) `(a ,(make-matrix-uri "u" mxid) ,(string-append "@" mxid)))
'("snite:telepath.im"
"snute:ip-logger.com"
"bartholomew:squarebowl.club"))
(p)
(h3 "XMPP")
,@(map (lambda (l d) `(a ,(make-xmpp-uri l d) ,(string-append l "@" d)))
'("snite" "snute")
'("telepath.im" "ip-logger.com"))
(p)
(h2 "PGP Key")
(p "If someone claiming to be me contacts you, please ask to verify my PGP key:")
(a ,(build-uri/capsule "pgp.txt") "PGP Key"))

25
site/index.scm Normal file
View file

@ -0,0 +1,25 @@
;;; site/index.scm
(import "util.scm")
(define title "~snit")
`(,@(import "header.scm")
(p "Hello, I am ~snit, an avid enjoyer of all things isekai, as well as the administrator of isekai.rocks. This capsule is my own personal space to talk about isekai (or other weeb media), technology, privacy/security, linguistics, and other esoteric topics.")
(p)
(h2 "Topics")
(p "Fair warning that there's not much here at the moment; some of these sections have nothing interesting.")
,@(map (lambda (name)
`(a ,(make-relative-uri 'suffix "." name)
,(join-path 'suffix "~" name)))
'("comp" "lang" "meta" "weeb"))
(p)
(h2 "Meta")
(p "All original content in this capsule is licensed under the following terms:")
(a ,(make-relative-uri 'suffix "LICENSE") "License")
(p)
(p "The source for the capsule can be found here:")
(a ,(build-uri 'https #:host "forge.fsky.io" #:path "/snit/gemini.git"))
(p)
(p "For questions, comments, concerns, or just to chat, you can contact me here:")
(a ,(make-relative-uri 'suffix "contact") "Contact"))

9
site/lang.scm Normal file
View file

@ -0,0 +1,9 @@
;;; site/lang.scm
(import "util.scm")
(define title "~snit/lang/")
`(,@(import "header.scm")
(p "Linguistic-related content. Languages (natural or artificial), linguistics, orthography, etc. is placed here."))

18
site/meta.scm Normal file
View file

@ -0,0 +1,18 @@
;;; site/meta.scm
(import "util.scm")
(define title "~snit/meta/")
`(,@(import "header.scm")
(p "The purpose of this one is threefold; it contains:")
(ul (li "content about this Gemini capsule (~snit)")
(li "nonessential information regarding isekai.rocks and its associated services")
(li "writing about me as a person (as opposed to just my opinions) for whatever reason"))
(p)
(p "There's a good chance those first two will also be found in ~snit/comp/, as well.")
(p)
(a ,(make-relative-uri 'suffix "links") "Link Garden")
(a ,(make-relative-uri 'suffix "27x81") "27x81 Banners")
(a ,(make-relative-uri 'suffix "post-ideas") "Post Ideas"))

11
site/meta/27x81.scm Normal file
View file

@ -0,0 +1,11 @@
;;; site/meta/27x81.scm
(import "util.scm")
(define title "27x81 Collection")
`(,@(import "header.scm")
,@(map (lambda (user)
`(a ,(build-uri/capsule "media" "27x81" (car user)) ,(cdr user)))
'(("snit.svg" . "snit")
("vel.png" . "vel"))))

16
site/meta/links.scm Normal file
View file

@ -0,0 +1,16 @@
;;; site/meta/links.scm
(import "util.scm")
(define title "Link Garden")
`(,@(import "header.scm")
(p "A list of sites I like or from people I know, sorted by protocol.")
(p)
(p "Hoping to add more darknet sites at some point (Ygg, Tor, I2P); I haven't taken
a good look at any of them yet really.")
(p)
(h2 "HTTP(S)")
(a ,(build-uri 'https #:host "nyx.ip-logger.com"))
(a ,(build-uri 'https #:host "squarebowl.club"))
(a ,(build-uri 'https #:host "telepath.im")))

56
site/meta/post-ideas.scm Normal file
View file

@ -0,0 +1,56 @@
;;; site/meta/post-ideas.scm
(import "util.scm")
(define title "Post Ideas")
`(,@(import "header.scm")
(p "A collection of ideas that I'd like to write about if I ever feel like it, sorted by category, but in no particular order.")
(p)
(h2 "~/comp/")
(ul (li "That one time I tried replacing GNU coreutils with uutils on Gentoo")
(li "My failed attempt to use a pure TTY environment on a spare laptop")
(li "Language-oriented programming")
(li "UNIX philosophy extremism")
(li "Why writing a compiler/interpreter is a good project regardless of skill level")
(li "More specialised software/services to replace various aspects of the web, in the spirit of UNIX philosphy \"do one thing and do it well\"")
(li "My browser setup, or really any other odd aspect of my current setup")
(li "A list of things I would like to see in my ideal operating system, POSIX-compatibility be damned")
(li "Tag-based filesystem benefits from a perspective other than media curation (system administration, programming, everyday usage)")
(li "Customisation and choice in software versus having a cohesive system, and how to have both at once (standard interfaces between programs?)"))
(p)
(h2 "~/lang/")
(ul (li "Holistic conlanging")
(li "Measuring relative complexity of various languages")
(li "Lexicalisation in Toki Pona")
(li "Neopronouns lol")
(li "Every argument boils down to an argument of semantics in the end, it seems")
(li "How the medium of writing affects average message length")
(li "Literally anything about phonoaesthetics/phonosemantics/sound symbolism")
(li "Dialects of English that are unique to specific spaces of the internet (i.e. 4chan)")
(li "Case study a polysynthetic language to see how various features work together")
(li "Case study a single (generally polysynthetic) feature across several languages to see different ways it can develop and be used")
(li "The difference between being polysynthetic and just being really really synthetic"))
(p)
(h2 "~/weeb/")
(ul (li "Literally anything I'm consuming now (just monologue into a .gmi instead of Matrix)")
(li "Isn't it interesting that SAO takes an oddly positive outlook on being trapped in a death game that kills four thousand?")
(li "Slavery is pretty common in isekai series. What's up with that?")
(li "Shield Hero vs Ningen Fushin in regards to portrayals of trust (or the lack thereof)")
(li "Why I like certain objectively bad series and why I hate some objectively good ones")
(li "Development of isekai as a genre and its associated tropes over time")
(li "Of course, the question of what even counts as \"isekai\" (its probably not what you think)")
(li "Why I like isekai specifically so much")
(li "Comparison of certain common isekai worldbuilding tropes across series (i.e. magic, races, gods, countries, monsters, adventurers, etc.)")
(li "More series should dedicate time to showing viewers exactly what the main character is fighting for; long prologues are a really good way to do this (i.e. Mushoku Tensei, Vinland Saga, Oshi no Ko)"))
(p)
(h2 "~/meta/")
(ul (li "Just a list of things I like regardless of what it is"))
(p)
(h2 "~/rand/")
(ul (li "Why people should stop defaulting to a blog structure for everythng, and possible alternatives to use instead")
(li "Old Minecraft versions and Luanti feel very eerie and liminal, but modern Minecraft doesn't. How come? What causes it?")
(li "Gatekeeping is good, actually (sometimes) (i.e. IRC, 4chan)")
(li "What makes a good Minecraft (or general in-game) currency?")
(li "Why Minecraft is a really bad game for (purely in-game) capitalism most of the time")
(li "Why do people find suffering to be cool? The kind of suffering that you see in people who fake mental illness or disability, or that you see in certain cases of chuunibyou")))

12
site/weeb.scm Normal file
View file

@ -0,0 +1,12 @@
;;; site/weeb.scm
(import "util.scm")
(define title "~snit/weeb/")
`(,@(import "header.scm")
(p "Content relating to anime, manga, {light,web,visual} novels, etc. is placed here. As one might expect from the owner of a domain called isekai.rocks, a lot of it is likely isekai-related.")
(p)
(a ,(make-relative-uri 'suffix "julie")
"Some random copypasta an /a/non posted in every Mushoku Tensei thread whilst it was airing"))

10
site/weeb/julie.scm Normal file
View file

@ -0,0 +1,10 @@
;;; site/weeb/julie.scm
(import "util.scm")
(define title "Jaegerbombs with Julie!")
`(,@(import "header.scm")
(p "Jaegerbombs with Julie! Jaegerbombs with Julie and it isn't even child abuse! Teaching her how to microsolder a motherboard afterwards! Then more Jaegerbombs! With Julie!")
(p)
(a ,(build-uri/capsule "media" "julie.jpeg") "Jaegerbombs with Julie!"))

View file

@ -1,4 +0,0 @@
# ~/snit/weeb/
Content relating to anime, manga, {light,web,visual} novels, etc. is placed here. As one might expect from the owner of a domain called isekai.rocks, a lot of it is likely isekai-related.
=> ./julie.gmi A copypasta some /a/non posted in every Mushoku Tensei thread while it aired

View file

@ -1,3 +0,0 @@
Jaegerbombs with Julie! Jaegerbombs with Julie and it isn't even child abuse! Teaching her how to microsolder a motherboard afterwards! Then more Jaegerbombs! With Julie!
=> ./image/julie.jpg Jaegerbombs with Julie JPEG