commit 5a16d783af81967aec13429002f537b5234b642f Spenser Truex <truex@equwal.com> 2026-09-22 21:07:29 -0700 Add the sbm, SubRead and Rebind pages The owner wrote these three pages, and the home page links to them. site/ is the build of this commit, so the About and Projects pages in site/ now link to sbmsync.com too. pages/sbm.md builds to sbm.html, in place of the post posts/sbm.md.
pages/rebind.md | 29 ++ pages/sbm.md | 37 ++ pages/subread.md | 38 ++ site/about.html | 5 +- site/index.html | 3 + site/projects.html | 5 +- site/rebind.html | 78 ++++ site/rss.xml | 1042 ++++++++++++++++++++++++++-------------------------- site/sbm.html | 83 ++--- site/subread.html | 106 ++++++ 10 files changed, 849 insertions(+), 577 deletions(-)
diff --git a/pages/rebind.md b/pages/rebind.md new file mode 100644 index 0000000..a01b86f --- /dev/null +++ b/pages/rebind.md @@ -0,0 +1,29 @@ +--- +title: Rebind +--- + +Rebind is a tool to make the VIWoods AI Reader phone more usable with key rebindings and hardware hacks like the 5 extra-dim light settings. The VIWoods phone is a very nice piece of hardware, but the stock firmware that it comes with is not amazing. This app and the suite of tools that it spawned are a solution. Made with vibecode. + +## Get it + +By the time you read this it will probably be on F-Droid and the Google Play store. + +## Projects + +* [rebind](https://github.com/equwal/rebind): Core app for rebinding and for the hardware hacks. +* [awesome-rebind](https://github.com/equwal/awesome-rebind): Similar page to this one, but AWESOME!? +* [ink-recents](https://github.com/equwal/ink-recents): An eink recent apps slider that is way nicer than the one viwoods installs. +* [ink-dim](https://github.com/equwal/ink-dim): Standalone app to do the dimming hack. Requires shizuku or live ADB +* [ink-update](https://github.com/equwal/ink-update): App to update these apps. Will be obsolete when F-Droid and Google Play are working. + +## Promo video + +<https://www.youtube.com/watch?v=SRZi0YgoCJ0> + +## How it works + +Uses a bunch of hacks to get as much access to the buttons as possible. Most are possible on stock viwoods firmware, although the extra dim light feature does require the shizuku hack. + +## Support + +Support the work at [ko-fi.com/truex](https://ko-fi.com/truex). diff --git a/pages/sbm.md b/pages/sbm.md new file mode 100644 index 0000000..03d8152 --- /dev/null +++ b/pages/sbm.md @@ -0,0 +1,37 @@ +--- +title: sbm +--- + +Suckless Bookmark Manager (now sbm Sync) + +sbm is a bookmark manager, originally a dmenu script. It is now a multiplatform, cloud synced bookmark manager with support for teams. + +## Promo video + +<https://www.youtube.com/watch?v=iKmYWTCkW7c> + +## Try it on the web + +* [sbmsync.com](https://sbmsync.com) + +## Projects + +* [sbm](https://github.com/equwal/sbm) multiplatform computer application +* [sbm-android](https://github.com/equwal/sbm-android) android app +* [sbm-extension](https://github.com/equwal/sbm-extension) firefox and chrome extensions +* [sbm-sync](https://github.com/equwal/sbm-sync) the sync server +* [sbm-suckless](https://github.com/equwal/sbm-suckless) the original POSIX shell script, suckless edition (no vibecode) + +## How it works + +Fuzzy search bookmarks and quickly add/copy/view bookmarks. Now with syncing through the browser and everything. + +## Why + +This tool gives you the power to spam links to your friends to the point that it annoys them. + +Like many others, I find search engines to be pretty tedious to use. Searching my own bookmarks is much better. With sbm you can be like me and have BASED links at your fingertips. + +## Support + +Support the work at [ko-fi.com/truex](https://ko-fi.com/truex). diff --git a/pages/subread.md b/pages/subread.md new file mode 100644 index 0000000..fe6dc21 --- /dev/null +++ b/pages/subread.md @@ -0,0 +1,38 @@ +--- +title: SubRead +--- + +SubRead makes it possible to read books with synced subtitles that keep your place. This is very nice for language learning. + +Subread is a suite of tools that port forced alignment to a variety of platforms. It is 100% free when used locally, although it is possible to do conversions with my cloud for a fee. It is 100% self-hostable free software. BUY NOW! + +## Promo Video + +<https://www.youtube.com/watch?v=WRz7UQZwe-Q> + +## Try it on the web + +* [subread.space](https://subread.space): webpage to do the conversions +* [honjimaku.com](https://honjimaku.com): website to download or upload srt files for Japanese audiobooks +* [kikiyomi](https://rtr46.github.io/kikiyomi/): Try reading your audiobook/srt combo on the web + +## Projects + +* [subplz-web](https://github.com/equwal/subplz-web): subread.space source +* [subread-android](https://github.com/equwal/subread-android): subread.space android app (local and cloud conversions are possible) +* [subread-extension](https://github.com/equwal/subread-extension): Extension to use subread on youtube for audiobooks published there. +* [subread-overlay](https://github.com/equwal/subread-overlay): Android app to show the subtitles as an overlay on the phone. Can be used with the dictionary for a very nice AJATT experience. +* [subread-dictionary](https://github.com/equwal/subread-dictionary): Yomitan pop-up dictionary standalone android app. Works really good with the overlay, but can be used anywhere! +* [subread.koplugin](https://github.com/equwal/subread.koplugin): KOReader plugin that does live highlighting of the book while you listen to it in another app like Voice, VLC, or MPV. +* [subrep-android](https://github.com/equwal/subrep-android): Live whisper captions. Better than the ones that come with android. +* [desktop-subtitle-replay](https://github.com/equwal/desktop-subtitle-replay): Whisper on your computer, and broadcast them to your friends. Useful for online language classrooms or bilingual exchanges. +* [honjimaku](https://github.com/equwal/honjimaku): Book subtitles database for japanese +* [Hoshi-Reader-Android](https://github.com/equwal/Hoshi-Reader-Android): Fork of hoshi reader that can do the conversion inside hoshi reader. Hopefully gets merged. + +## Why + +Extremely useful for learning languages by reading books with the audiobook. + +## Support + +Support the work at [ko-fi.com/truex](https://ko-fi.com/truex). diff --git a/site/about.html b/site/about.html index 307ccee..bbf7c9d 100644 --- a/site/about.html +++ b/site/about.html @@ -44,9 +44,8 @@ <li><a href="https://honjimaku.com">honjimaku.com</a> - A library of Japanese subtitles for audiobooks, and Subrep live captions by share link.</li> - <li><a href="https://sbm.subread.space">sbm.subread.space</a> - sbm - Sync: one plain bookmark file, the same on every device. Free, - AGPL.</li> + <li><a href="https://sbmsync.com">sbmsync.com</a> - sbm Sync: one + plain bookmark file, the same on every device. Free, AGPL.</li> <li><a href="https://hentaibun.online">hentaibun.online</a> - Reading lists and tools to learn kanbun and kobun.</li> <li><a href="https://recentlywritten.com">recentlywritten.com</a> - diff --git a/site/index.html b/site/index.html index 1936df3..3cb8c97 100644 --- a/site/index.html +++ b/site/index.html @@ -122,10 +122,13 @@ <li><a href="newport-reference-manual.html">Newport Reference Manual</a></li> <li><a href="norda-naturo.html">norda naturo</a></li> <li><a href="projects.html">Projects</a></li> +<li><a href="rebind.html">Rebind</a></li> <li><a href="release.html">release</a></li> <li><a href="rut.html">rut</a></li> +<li><a href="sbm.html">sbm</a></li> <li><a href="serpentoj-en-la-puto.html">Serpentoj En La Puto</a></li> <li><a href="sten-johansson.html">Noveloj de Sten Johansson</a></li> +<li><a href="subread.html">SubRead</a></li> <li><a href="youtube.html">YouTube</a></li> </ul> diff --git a/site/projects.html b/site/projects.html index dcc3af1..a9f9e50 100644 --- a/site/projects.html +++ b/site/projects.html @@ -44,9 +44,8 @@ <li><a href="https://honjimaku.com">honjimaku.com</a> - A library of Japanese subtitles for audiobooks, and Subrep live captions by share link.</li> - <li><a href="https://sbm.subread.space">sbm.subread.space</a> - sbm - Sync: one plain bookmark file, the same on every device. Free, - AGPL.</li> + <li><a href="https://sbmsync.com">sbmsync.com</a> - sbm Sync: one + plain bookmark file, the same on every device. Free, AGPL.</li> <li><a href="https://hentaibun.online">hentaibun.online</a> - Reading lists and tools to learn kanbun and kobun.</li> <li><a href="https://recentlywritten.com">recentlywritten.com</a> - diff --git a/site/rebind.html b/site/rebind.html new file mode 100644 index 0000000..1667798 --- /dev/null +++ b/site/rebind.html @@ -0,0 +1,78 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <title>Rebind — Recently Written</title> + <meta property="og:type" content="article" /> + <meta property="og:site_name" content="Recently Written" /> + <meta property="og:title" content="Rebind" /> + <meta property="og:url" content="https://recentlywritten.com/rebind.html" /> + <meta property="og:image" content="https://recentlywritten.com/static/og.png" /> + <meta name="twitter:card" content="summary_large_image" /> + <link rel="stylesheet" href="style.css" /> + <link rel="alternate" type="application/rss+xml" title="Recently Written" href="rss.xml" /> +</head> +<body> +<div id="container"> + + <div id="top"> + <a class="site-title" href="index.html">Recently Written</a> + <nav> + <a href="index.html">Home</a> + <a href="about.html">about</a> + <a href="lair.html">code</a> + <a href="git/index.html">git</a> + <a href="youtube.html">youtube</a> + <a href="esperanto.html">esperanto</a> + <a href="call.html">contact</a> + <a href="rss.xml">rss</a> + </nav> + </div> + + <h1 class="post-title">Rebind</h1> + + <p>Rebind is a tool to make the VIWoods AI Reader phone more usable + with key rebindings and hardware hacks like the 5 extra-dim light + settings. The VIWoods phone is a very nice piece of hardware, but the + stock firmware that it comes with is not amazing. This app and the + suite of tools that it spawned are a solution. Made with vibecode.</p> + <h2 id="get-it">Get it</h2> + <p>By the time you read this it will probably be on F-Droid and the + Google Play store.</p> + <h2 id="projects">Projects</h2> + <ul> + <li><a href="https://github.com/equwal/rebind">rebind</a>: Core app + for rebinding and for the hardware hacks.</li> + <li><a + href="https://github.com/equwal/awesome-rebind">awesome-rebind</a>: + Similar page to this one, but AWESOME!?</li> + <li><a href="https://github.com/equwal/ink-recents">ink-recents</a>: + An eink recent apps slider that is way nicer than the one viwoods + installs.</li> + <li><a href="https://github.com/equwal/ink-dim">ink-dim</a>: + Standalone app to do the dimming hack. Requires shizuku or live + ADB</li> + <li><a href="https://github.com/equwal/ink-update">ink-update</a>: App + to update these apps. Will be obsolete when F-Droid and Google Play + are working.</li> + </ul> + <h2 id="promo-video">Promo video</h2> + <p><a href="https://www.youtube.com/watch?v=SRZi0YgoCJ0" + class="uri">https://www.youtube.com/watch?v=SRZi0YgoCJ0</a></p> + <h2 id="how-it-works">How it works</h2> + <p>Uses a bunch of hacks to get as much access to the buttons as + possible. Most are possible on stock viwoods firmware, although the + extra dim light feature does require the shizuku hack.</p> + <h2 id="support">Support</h2> + <p>Support the work at <a + href="https://ko-fi.com/truex">ko-fi.com/truex</a>.</p> + + <div id="footer"> + <a href="index.html">← Home</a> · + <a href="https://github.com/equwal">Github</a> + </div> + +</div> +</body> +</html> diff --git a/site/rss.xml b/site/rss.xml index c195bf8..c3713b7 100644 --- a/site/rss.xml +++ b/site/rss.xml @@ -11,25 +11,25 @@ <link>https://recentlywritten.com/lisprant.html</link> <guid isPermaLink="true">https://recentlywritten.com/lisprant.html</guid> <pubDate>Tue, 12 May 2026 00:00:00 +0000</pubDate> - <description><![CDATA[<p>Read doug hoyte then come back and tell me static typing is better -ecl is good for live servers (eg. “web”) for obvious reasons every -person who “uses lisp at work” refuses to share details so I know that -lisp in production does not exist and they are larping solving the -problem with a well-fitted language and modifying the (lisp) compiler -mogs leet coders because of Kolomogorov complexity (see Graham’s stuff) -props to style_warning for making his username a lisp shibboleth Before -vibecoding I knew plenty of stack overflow copy-pasters etc. Before -vibecode it was still the case that your average interviewee could not -solve a basic coding question. Reading a programming book and doing some -of the exercises will take you farther than l33tcode bullshit ever will. -You can also be vaccinated against AI retardation. Also before vibecode -I started to notice that 99% of the time I could solve problems with -unix-philosophy tools and duct tape instead of reinventing the wheel. -There is so much stuff on the internet which is easily accessible. This -is still the case although the well has been poisoned quite a bit -because tools rarely work anymore. The Bipolar Lisp Programmer finally -won against Mel The Real Programmer. schizo rant over back to your -regular scheduled programming</p> + <description><![CDATA[<p>Read doug hoyte then come back and tell me static typing is better +ecl is good for live servers (eg. “web”) for obvious reasons every +person who “uses lisp at work” refuses to share details so I know that +lisp in production does not exist and they are larping solving the +problem with a well-fitted language and modifying the (lisp) compiler +mogs leet coders because of Kolomogorov complexity (see Graham’s stuff) +props to style_warning for making his username a lisp shibboleth Before +vibecoding I knew plenty of stack overflow copy-pasters etc. Before +vibecode it was still the case that your average interviewee could not +solve a basic coding question. Reading a programming book and doing some +of the exercises will take you farther than l33tcode bullshit ever will. +You can also be vaccinated against AI retardation. Also before vibecode +I started to notice that 99% of the time I could solve problems with +unix-philosophy tools and duct tape instead of reinventing the wheel. +There is so much stuff on the internet which is easily accessible. This +is still the case although the well has been poisoned quite a bit +because tools rarely work anymore. The Bipolar Lisp Programmer finally +won against Mel The Real Programmer. schizo rant over back to your +regular scheduled programming</p> ]]></description> </item> <item> @@ -37,46 +37,46 @@ regular scheduled programming</p> <link>https://recentlywritten.com/aintitinit-Claude-INITIALIZER.html</link> <guid isPermaLink="true">https://recentlywritten.com/aintitinit-Claude-INITIALIZER.html</guid> <pubDate>Tue, 09 Sep 2025 00:00:00 +0000</pubDate> - <description><![CDATA[<p><a href="https://github.com/HACKERMEN-ORG/aintitinit" class="external-link">git -hub website repo</a></p> -<h2 id="claude-initializer">Claude INITIALIZER</h2> -<p>INITIALIZES a new git project in the directory if there isn’t one -already,<br /> -various files for claude in the directory to vibe code really -hard,<br /> -and hacks git to not track them.</p> -<p>The bare minimum necessary of course.</p> -<figure> -<a href="https://recentlywritten.com/static/gifmatrix.gif" target="_blank"><img src="https://recentlywritten.com/static/gifmatrix.gif" style="display:block;" alt="gifmatrix.gif" /></a> -</figure> -<h3 id="claude.md">CLAUDE.md</h3> -<p>This is the prompt claude will use in your project. Includes the -prompt<br /> -I had it generate, you can put anything you want in here.</p> -<h3 id="exclude-file">exclude (file)</h3> -<p>Appends this to the git exclusions to not track the claude-related -files</p> -<h3 id="mcp.json">.mcp.json</h3> -<p>The mcp servers you will use. There are a million already added by -the AI if you want to just use it as-ise.</p> -<h3 id="llms-full.txt">llms-full.txt</h3> -<p>Tells claude about the LLMs in -.mcp.jsonquire”cmp.utils.feedkeys”.run(2)<br /> -,</p> -<h3 id="regular-use">regular use</h3> -<pre><code>claude-init ; claude init</code></pre> -<h3 id="alias">alias</h3> -<p><code>ci</code> claude init.<br /> -<code>cli</code> try to continue, otherwise initialize in the -directory.</p> -<pre><code>alias ci='claude-init ; claude init' -alias cli='f(){ mkdir -p "$1" ; cd ${1:-.} ; claude-init ; claude init }; claude --continue || f'</code></pre> -<h3 id="todo">TODO</h3> -<ul> -<li>Automatically remove whitespace and base64 encode the CLAUDE.md -from</li> -</ul> -<p>the readable version to save tokens.</p> + <description><![CDATA[<p><a href="https://github.com/HACKERMEN-ORG/aintitinit" class="external-link">git +hub website repo</a></p> +<h2 id="claude-initializer">Claude INITIALIZER</h2> +<p>INITIALIZES a new git project in the directory if there isn’t one +already,<br /> +various files for claude in the directory to vibe code really +hard,<br /> +and hacks git to not track them.</p> +<p>The bare minimum necessary of course.</p> +<figure> +<a href="https://recentlywritten.com/static/gifmatrix.gif" target="_blank"><img src="https://recentlywritten.com/static/gifmatrix.gif" style="display:block;" alt="gifmatrix.gif" /></a> +</figure> +<h3 id="claude.md">CLAUDE.md</h3> +<p>This is the prompt claude will use in your project. Includes the +prompt<br /> +I had it generate, you can put anything you want in here.</p> +<h3 id="exclude-file">exclude (file)</h3> +<p>Appends this to the git exclusions to not track the claude-related +files</p> +<h3 id="mcp.json">.mcp.json</h3> +<p>The mcp servers you will use. There are a million already added by +the AI if you want to just use it as-ise.</p> +<h3 id="llms-full.txt">llms-full.txt</h3> +<p>Tells claude about the LLMs in +.mcp.jsonquire”cmp.utils.feedkeys”.run(2)<br /> +,</p> +<h3 id="regular-use">regular use</h3> +<pre><code>claude-init ; claude init</code></pre> +<h3 id="alias">alias</h3> +<p><code>ci</code> claude init.<br /> +<code>cli</code> try to continue, otherwise initialize in the +directory.</p> +<pre><code>alias ci='claude-init ; claude init' +alias cli='f(){ mkdir -p "$1" ; cd ${1:-.} ; claude-init ; claude init }; claude --continue || f'</code></pre> +<h3 id="todo">TODO</h3> +<ul> +<li>Automatically remove whitespace and base64 encode the CLAUDE.md +from</li> +</ul> +<p>the readable version to save tokens.</p> ]]></description> </item> <item> @@ -84,53 +84,53 @@ from</li> <link>https://recentlywritten.com/Hackermen-neomutt-config.html</link> <guid isPermaLink="true">https://recentlywritten.com/Hackermen-neomutt-config.html</guid> <pubDate>Mon, 08 Sep 2025 00:00:00 +0000</pubDate> - <description><![CDATA[<p><a href="https://github.com/HACKERMEN-ORG/neomutt-config" class="external-link">link -to git hub website repository</a></p> -<h2 id="why-this-exists">Why this exists</h2> -<p>So my friends can send me encrypted mail, bottom post, and -send/apply<br /> -patches.</p> -<p>> “I installed neomutt but I haven’t figured it out”</p> -<p>Neomutt defaults have legacy lock-in issues.</p> -<h2 id="barebones-neomutt-config">Barebones neomutt config</h2> -<h3 id="features">Features</h3> -<ul> -<li><p>optional PGP encryption/signing/both</p></li> -<li><p>Automatic PGP decryption</p></li> -<li><p>hjkl movement: navigate</p></li> -<li><p>n/p movement: read+page mails like in the GNUs client</p></li> -<li><p>open HTML mail in the $BROWSER with a bind</p></li> -<li><p>edit mail in the $EDITOR</p></li> -<li><p>Can setup multiple mailboxes (just source more files like -me-TEMPLATE)</p></li> -<li><p>arcane-config-TEMPLATE to keep user-specific config -separate</p></li> -<li><p>Lots of colors</p></li> -<li><p>A million default setting changes that don’t do much</p></li> -<li><p>signature</p></li> -</ul> -<h3 id="subjective-user-experience">Subjective User Experience</h3> -<p><a href="http://www.booksatoz.com/witsend/tea/orwell.htm" class="external-link">Like -this</a></p> -<h3 id="install">Install</h3> -<ul> -<li><p>clone to ~/.config/neomutt</p></li> -<li><p>install neomutt</p></li> -<li><p>install isync and sendmail for IMAP and SMTP</p></li> -<li><p>install notmuch to search your mails</p></li> -<li><p>install gpg (optional)</p></li> -<li><p>Edit and rename the TEMPLATE files</p></li> -<li><p>Edit the sources at the top of the neomuttrc to fit your -needs</p></li> -</ul> -<h3 -id="good-alias-to-do-background-mail-stuff-when-opening-the-client">Good -alias to do background mail stuff when opening the client</h3> -<h3 id="todo">TODO</h3> -<ul> -<li>Automatic WKD for automatic PGP encryption without manually adding -keys</li> -</ul> + <description><![CDATA[<p><a href="https://github.com/HACKERMEN-ORG/neomutt-config" class="external-link">link +to git hub website repository</a></p> +<h2 id="why-this-exists">Why this exists</h2> +<p>So my friends can send me encrypted mail, bottom post, and +send/apply<br /> +patches.</p> +<p>> “I installed neomutt but I haven’t figured it out”</p> +<p>Neomutt defaults have legacy lock-in issues.</p> +<h2 id="barebones-neomutt-config">Barebones neomutt config</h2> +<h3 id="features">Features</h3> +<ul> +<li><p>optional PGP encryption/signing/both</p></li> +<li><p>Automatic PGP decryption</p></li> +<li><p>hjkl movement: navigate</p></li> +<li><p>n/p movement: read+page mails like in the GNUs client</p></li> +<li><p>open HTML mail in the $BROWSER with a bind</p></li> +<li><p>edit mail in the $EDITOR</p></li> +<li><p>Can setup multiple mailboxes (just source more files like +me-TEMPLATE)</p></li> +<li><p>arcane-config-TEMPLATE to keep user-specific config +separate</p></li> +<li><p>Lots of colors</p></li> +<li><p>A million default setting changes that don’t do much</p></li> +<li><p>signature</p></li> +</ul> +<h3 id="subjective-user-experience">Subjective User Experience</h3> +<p><a href="http://www.booksatoz.com/witsend/tea/orwell.htm" class="external-link">Like +this</a></p> +<h3 id="install">Install</h3> +<ul> +<li><p>clone to ~/.config/neomutt</p></li> +<li><p>install neomutt</p></li> +<li><p>install isync and sendmail for IMAP and SMTP</p></li> +<li><p>install notmuch to search your mails</p></li> +<li><p>install gpg (optional)</p></li> +<li><p>Edit and rename the TEMPLATE files</p></li> +<li><p>Edit the sources at the top of the neomuttrc to fit your +needs</p></li> +</ul> +<h3 +id="good-alias-to-do-background-mail-stuff-when-opening-the-client">Good +alias to do background mail stuff when opening the client</h3> +<h3 id="todo">TODO</h3> +<ul> +<li>Automatic WKD for automatic PGP encryption without manually adding +keys</li> +</ul> ]]></description> </item> <item> @@ -138,64 +138,64 @@ keys</li> <link>https://recentlywritten.com/REPL-Driven-Development-as-an-analogy-for-proper-AI-Driven-Development.html</link> <guid isPermaLink="true">https://recentlywritten.com/REPL-Driven-Development-as-an-analogy-for-proper-AI-Driven-Development.html</guid> <pubDate>Mon, 08 Sep 2025 00:00:00 +0000</pubDate> - <description><![CDATA[<p>I recently “discovered” using an LLM to code with, and was looking -forward to doing some “REPL Driven Development” on it. Unfortunately, I -discovered that all of the vibe-coded vim plugins just use vim as a -(terrible) multiplexer for the Claude Code CLI program. The Emacs plugin -<a href="https://github.com/manzaltu/claude-code-ide.el" class="external-link">claude-code-ide.el</a> -does it right by having text selection and other send-to-repl-like -actions like a proper Lisp IDE does.</p> -<p>This was merely a lisp thing to do because the parentheses clearly -define selection to send. That’s no longer an issue, the LLM can filter -out the garbage in a way that a GOFAI symbolic rule-based pattern -matcher can’t.</p> -<p>The command line program likes to use diffs to edit files, and that -is reasonable, but vastly inferior to REPL Driven Development from a -scratch file. Below are some of my notes from 2019 for more context on -using the lisp REPL. With RDD, you will never type something directly -into a REPL again. “Never type into the REPL”.</p> -<p>It’s nice using grep to lookup some code I might have written 5 years -ago that would have been ephemeral and lost at the REPL.</p> -<h3 id="repl-driven-development">REPL driven development</h3> -<p>Stuard Halloway’s 2017 talk at Chicago Clojure:</p> -<p><a href="https://vimeo.com/223309989" class="external-link">vimeo</a><br /> -<a href="https://github.com/matthiasn/talk-transcripts/blob/master/Halloway_Stuart/REPLDrivenDevelopment.md" class="external-link">slide -notes</a></p> -<ul> -<li><p>DON’T type <em>into</em> the repl. Type into a file that you can -search later.</p></li> -<li><p>Use repl-interaction commands (like insert-in-repl, minibuffer, -etc.).</p></li> -<li><p>Have a plan to avoid wasting time (since repls are fun).</p></li> -<li><p>Know <em>all</em> the jump-to-documentation kinds of commands. -Searching for a regex,<br /> -jumping to the source of a thing, etc.</p></li> -<li><p>Analysing data carefully at the repl (don’t just stare at -stacktraces).</p></li> -<li><p>Debugging at O(log n)</p></li> -<li><p>Custom REPLs (especially debuggers/inspectors with breakpoints, -etc.)</p></li> -<li><p>Do use the debugger.</p></li> -</ul> -<h4 id="most-important-keystrokes">MOST important keystrokes</h4> -<ul> -<li><p>Execute a thing in the minibuffer</p></li> -<li><p>Tracing functions (or a short function to execute in the -minibuffer like =trace=)</p></li> -<li><p>Sending to repl from behind the point</p></li> -<li><p>Sending to repl from in front of the point</p></li> -<li><p>Sending the whole top-level expression at point to the -repl</p></li> -<li><p>Jump to the minibuffer (not for typing! just to see big -output)</p></li> -<li><p>A keystroke to jump back to the source file (or something like -windmove)</p></li> -<li><p><em>all</em> the documentation commands (search, jump to source, -doc-at-point, etc.)</p></li> -<li><p>Execute something and replace it with the output/write the output -as</p></li> -</ul> -<p>a comment in the scratch buffer.</p> + <description><![CDATA[<p>I recently “discovered” using an LLM to code with, and was looking +forward to doing some “REPL Driven Development” on it. Unfortunately, I +discovered that all of the vibe-coded vim plugins just use vim as a +(terrible) multiplexer for the Claude Code CLI program. The Emacs plugin +<a href="https://github.com/manzaltu/claude-code-ide.el" class="external-link">claude-code-ide.el</a> +does it right by having text selection and other send-to-repl-like +actions like a proper Lisp IDE does.</p> +<p>This was merely a lisp thing to do because the parentheses clearly +define selection to send. That’s no longer an issue, the LLM can filter +out the garbage in a way that a GOFAI symbolic rule-based pattern +matcher can’t.</p> +<p>The command line program likes to use diffs to edit files, and that +is reasonable, but vastly inferior to REPL Driven Development from a +scratch file. Below are some of my notes from 2019 for more context on +using the lisp REPL. With RDD, you will never type something directly +into a REPL again. “Never type into the REPL”.</p> +<p>It’s nice using grep to lookup some code I might have written 5 years +ago that would have been ephemeral and lost at the REPL.</p> +<h3 id="repl-driven-development">REPL driven development</h3> +<p>Stuard Halloway’s 2017 talk at Chicago Clojure:</p> +<p><a href="https://vimeo.com/223309989" class="external-link">vimeo</a><br /> +<a href="https://github.com/matthiasn/talk-transcripts/blob/master/Halloway_Stuart/REPLDrivenDevelopment.md" class="external-link">slide +notes</a></p> +<ul> +<li><p>DON’T type <em>into</em> the repl. Type into a file that you can +search later.</p></li> +<li><p>Use repl-interaction commands (like insert-in-repl, minibuffer, +etc.).</p></li> +<li><p>Have a plan to avoid wasting time (since repls are fun).</p></li> +<li><p>Know <em>all</em> the jump-to-documentation kinds of commands. +Searching for a regex,<br /> +jumping to the source of a thing, etc.</p></li> +<li><p>Analysing data carefully at the repl (don’t just stare at +stacktraces).</p></li> +<li><p>Debugging at O(log n)</p></li> +<li><p>Custom REPLs (especially debuggers/inspectors with breakpoints, +etc.)</p></li> +<li><p>Do use the debugger.</p></li> +</ul> +<h4 id="most-important-keystrokes">MOST important keystrokes</h4> +<ul> +<li><p>Execute a thing in the minibuffer</p></li> +<li><p>Tracing functions (or a short function to execute in the +minibuffer like =trace=)</p></li> +<li><p>Sending to repl from behind the point</p></li> +<li><p>Sending to repl from in front of the point</p></li> +<li><p>Sending the whole top-level expression at point to the +repl</p></li> +<li><p>Jump to the minibuffer (not for typing! just to see big +output)</p></li> +<li><p>A keystroke to jump back to the source file (or something like +windmove)</p></li> +<li><p><em>all</em> the documentation commands (search, jump to source, +doc-at-point, etc.)</p></li> +<li><p>Execute something and replace it with the output/write the output +as</p></li> +</ul> +<p>a comment in the scratch buffer.</p> ]]></description> </item> <item> @@ -203,74 +203,74 @@ as</p></li> <link>https://recentlywritten.com/Minimal-nvim-config-optional-AI-slop-enjoy.html</link> <guid isPermaLink="true">https://recentlywritten.com/Minimal-nvim-config-optional-AI-slop-enjoy.html</guid> <pubDate>Sun, 07 Sep 2025 00:00:00 +0000</pubDate> - <description><![CDATA[<p><a href="https://github.com/HACKERMEN-ORG/hackermen-neovim-config-file" class="external-link">code -on the git hub website</a></p> -<p>A friend sent me a neomutt configuration which was thousands of lines -of LLM code, using libraries where even the READMEs are written by LLMs. -Surprisingly, it worked pretty good. Human being were never any good at -writing VimScript anyway. Of course, to make even tiny edits, due to the -extreme unnecessary complexity brought in by the LLM, requires the use -of another LLM. Blargh!</p> -<p>The solution: actually use a decent, simple init written by a human, -and put the rest in the “optional” slop folder. Problem solved!</p> -<h2 id="install">Install</h2> -<p>Run nvim and do,<code>:PlugInstall</code>. BAM! Future travellers: -you should do <code>:PlugUpdate</code>.</p> -<h2 id="features">FEATURES</h2> -<ul> -<li><p><a href="http://danmidwood.com/content/2014/11/21/animated-paredit.html" class="external-link">Structural -editing</a></p></li> -<li><p>Global leader is Spacebar. Spacevim!</p></li> -<li><p>Local leader is comma.</p></li> -<li><p>Spellcheck and shellcheck keybindings.</p></li> -<li><p>(sane) Completion. See equwal’s -<a href="https://github.com/equwal/tag-gen" class="external-link">tag-gen</a> -project.</p></li> -<li><p>Which-key. Learn vim!</p></li> -<li><p>Goyo (For writing words. Automatically turns on when editing -neomutt buffers)</p></li> -<li><p><++> templating (see my <++> -<a href="https://recentlywritten.com/tmpl-insanely-simple-templates.html" class="external-link">tmpl</a> -project)</p></li> -<li><p>Ask what you meant using fzf when you try try to open a file that -doesn’t exist.</p></li> -<li><p>Save your place in the buffer for later.</p></li> -<li><p>mode line</p></li> -<li><p>Slightly modified vim defaults (very slightly). See the only file -for details.</p></li> -</ul> -<h2 id="non-features">NON-FEATURES</h2> -<ul> -<li><p>Not crazy modifications to vim defaults</p></li> -<li><p>Only one file (everything else in “slop” folder)</p></li> -<li><p>No major changes to the packages used</p></li> -<li><p>No window management. Use a terminal multiplexer.</p></li> -<li><p>No claude code. Same.</p></li> -</ul> -<p>Source your own config at the bottom of the init.lua and work from -these sane defaults.</p> -<h3 id="faq-frequent-answers-to-questions">FAQ: Frequent Answers to -Questions</h3> -<h4 -id="source-your-own-config-at-the-bottom-of-the-init.lua-and-work-from-these-sane-defaults">“Source -your own config at the bottom of the init.lua and work from these sane -defaults”</h4> -<p>Then, make changes to the init.lua and send a pull request.</p> -<h4 id="you-dont-need-claude-in-your-vim">You don’t need claude in your -vim</h4> -<p>ARGH. Just use dvtm/mtm/abduco or your window manager to deal with -it. None of the claude vim projects are smart enough to send parts of -buffers to the claude like slime does for lisp. Those claude vim -packages are just glorified terminals using vim as a (very bad) -multiplexer.</p> -<h4 id="plugged-is-better-than-lazy">Plugged *is* better than Lazy</h4> -<p>Lazy is written by AI. The point of this is to not be written -by<br /> -AI. Complex shit breaks!</p> -<h4 id="here-is-your-prompt-sir">Here is your prompt, SIR:</h4> -<pre><code>start adding individual feature s one by one which only take up 1-10 lines. Don't import all the config, just the most basic config. For individual lines, write what it does and ask to add it in. For packages, read the github pages and their default configuration to minimize the edits needed. Opt for the most default configuration if possible.</code></pre> -<h4 id="dont-add-hundreds-of-lines-of-ai-slop-to-my-config.">Don’t add -hundreds of lines of AI slop to my config.</h4> + <description><![CDATA[<p><a href="https://github.com/HACKERMEN-ORG/hackermen-neovim-config-file" class="external-link">code +on the git hub website</a></p> +<p>A friend sent me a neomutt configuration which was thousands of lines +of LLM code, using libraries where even the READMEs are written by LLMs. +Surprisingly, it worked pretty good. Human being were never any good at +writing VimScript anyway. Of course, to make even tiny edits, due to the +extreme unnecessary complexity brought in by the LLM, requires the use +of another LLM. Blargh!</p> +<p>The solution: actually use a decent, simple init written by a human, +and put the rest in the “optional” slop folder. Problem solved!</p> +<h2 id="install">Install</h2> +<p>Run nvim and do,<code>:PlugInstall</code>. BAM! Future travellers: +you should do <code>:PlugUpdate</code>.</p> +<h2 id="features">FEATURES</h2> +<ul> +<li><p><a href="http://danmidwood.com/content/2014/11/21/animated-paredit.html" class="external-link">Structural +editing</a></p></li> +<li><p>Global leader is Spacebar. Spacevim!</p></li> +<li><p>Local leader is comma.</p></li> +<li><p>Spellcheck and shellcheck keybindings.</p></li> +<li><p>(sane) Completion. See equwal’s +<a href="https://github.com/equwal/tag-gen" class="external-link">tag-gen</a> +project.</p></li> +<li><p>Which-key. Learn vim!</p></li> +<li><p>Goyo (For writing words. Automatically turns on when editing +neomutt buffers)</p></li> +<li><p><++> templating (see my <++> +<a href="https://recentlywritten.com/tmpl-insanely-simple-templates.html" class="external-link">tmpl</a> +project)</p></li> +<li><p>Ask what you meant using fzf when you try try to open a file that +doesn’t exist.</p></li> +<li><p>Save your place in the buffer for later.</p></li> +<li><p>mode line</p></li> +<li><p>Slightly modified vim defaults (very slightly). See the only file +for details.</p></li> +</ul> +<h2 id="non-features">NON-FEATURES</h2> +<ul> +<li><p>Not crazy modifications to vim defaults</p></li> +<li><p>Only one file (everything else in “slop” folder)</p></li> +<li><p>No major changes to the packages used</p></li> +<li><p>No window management. Use a terminal multiplexer.</p></li> +<li><p>No claude code. Same.</p></li> +</ul> +<p>Source your own config at the bottom of the init.lua and work from +these sane defaults.</p> +<h3 id="faq-frequent-answers-to-questions">FAQ: Frequent Answers to +Questions</h3> +<h4 +id="source-your-own-config-at-the-bottom-of-the-init.lua-and-work-from-these-sane-defaults">“Source +your own config at the bottom of the init.lua and work from these sane +defaults”</h4> +<p>Then, make changes to the init.lua and send a pull request.</p> +<h4 id="you-dont-need-claude-in-your-vim">You don’t need claude in your +vim</h4> +<p>ARGH. Just use dvtm/mtm/abduco or your window manager to deal with +it. None of the claude vim projects are smart enough to send parts of +buffers to the claude like slime does for lisp. Those claude vim +packages are just glorified terminals using vim as a (very bad) +multiplexer.</p> +<h4 id="plugged-is-better-than-lazy">Plugged *is* better than Lazy</h4> +<p>Lazy is written by AI. The point of this is to not be written +by<br /> +AI. Complex shit breaks!</p> +<h4 id="here-is-your-prompt-sir">Here is your prompt, SIR:</h4> +<pre><code>start adding individual feature s one by one which only take up 1-10 lines. Don't import all the config, just the most basic config. For individual lines, write what it does and ask to add it in. For packages, read the github pages and their default configuration to minimize the edits needed. Opt for the most default configuration if possible.</code></pre> +<h4 id="dont-add-hundreds-of-lines-of-ai-slop-to-my-config.">Don’t add +hundreds of lines of AI slop to my config.</h4> ]]></description> </item> <item> @@ -278,92 +278,92 @@ hundreds of lines of AI slop to my config.</h4> <link>https://recentlywritten.com/Using-an-init-system-for-many-instances-of-simple-programs.html</link> <guid isPermaLink="true">https://recentlywritten.com/Using-an-init-system-for-many-instances-of-simple-programs.html</guid> <pubDate>Sun, 07 Sep 2025 00:00:00 +0000</pubDate> - <description><![CDATA[<p><a href="https://github.com/equwal/tiny-runlevels" class="external-link">mirrored -on github for convenience here</a></p> -<p>Using OpenRC runlevels to have lots of instances of simple (network) -programs like quark for multiple http serving locally or -<a href="https://tools.suckless.org/ii/" class="external-link">ii</a> -(or -<a href="https://tools.suckless.org/sic/" class="external-link">sic</a>) -for IRC server connections.</p> -<p>To keep programs simple, they should not do the same process for -unrelated uses. It is much more complicated to configure and manage -multiple webservers in the same process (like how nginx does it) than -just one. Init systems are designed to manage processes, and should be -used instead. Do one thing etc. etc.</p> -<p>This is how to use the OpenRC runlevels for quark and ii runlevels as -examples.</p> -<h3 id="the-tree-on-my-machine">The Tree (on my machine)</h3> -<pre><code>/etc/runlevels -├── boot -│ └── ... -├── default -│ └── ... -├── irc-base -│ ├── oftc -> /etc/init.d/oftc -│ ├── liberachat -> /etc/init.d/liberachat -│ └── ... -├── net-base -│ ├── default -> ../default -│ └── quark -> ../quark -├── net-offline -│ ├── default -> ../default -│ └── net-base -> ../net-base -├── net-dns -│ ├── dnscrypt-proxy -> /etc/init.d/dnscrypt-proxy -│ └── unbound -> /etc/init.d/unbound -├── net-wifi -│ ├── dhcpcd -> /etc/init.d/dhcpcd -│ ├── net-base -> /etc/runlevels/net-base -│ ├── net-dns -> /etc/runlevels/net-dns -│ └── wpa_supplicant -> /etc/init.d/wpa_supplicant -├── net-wifi-irc -│ ├── irc-base -> ../irc-base -│ └── net-wifi -> ../net-wifi -├── quark -│ ├── quark-docs -> /etc/init.d/quark-docs -│ ├── quark-equwal -> /etc/init.d/quark-equwal -│ └── ... -├── shutdown -│ └── ... -└── sysinit - └── ...</code></pre> -<p>as you can see, IRC is connected after the real internet on wifi -(net-wifi), but quark runs on any network runlevel using net-base.</p> -<h3 id="how-to">How To:</h3> -<p>OpenRC has its own commands for making the runlevels, but I find them -confusing. Let’s just edit the files.</p> -<pre><code># make runlevel -mkdir /etc/runlevels/quark -# add services (as many as needed) -ln -s /etc/int.d/quark-whatever /etc/runlevels/quark -# add runlevel to parent -ln -s /etc/runlevels/default /etc/runlevels/quark -# Reload since openrc is in default -openrc default</code></pre> -<p>That works, but what about for networked IRC on a custom networking -runlevel? Just add it to the networking runlevel.</p> -<pre><code># (first, make a network runlevel that contains default! Without default the system will crash, obviously.) -mkdir /etc/runlevels/net-wifi -ln -s /etc/runlevels/net-wifi /etc/runlevels/default -ln -s /etc/init.d/wpa_supplicant /etc/runlevels/net-wifi -# etc. -# Now add the irc-base to the network runlevel -mkdir /etc/runlevels/irc-base -ln -s /etc/init.d/liberachat irc-base -ln -s /etc/init.d/oftc irc-base -ln -s /etc/runlevels/irc-base /etc/runlevels/net-wifi -openrc net-wifi</code></pre> -<h3 id="tool-restart-runlevel">Tool: restart-runlevel</h3> -<p>Openrc wants switch the whole stack <code>openrc runlevel</code> so I -made a little tool to just restart a specific runlevel. Nice for -debugging.</p> -<pre><code>#!/bin/bash - -for link in /etc/runlevels/${1}/* -do [[ -L "$link" && "$(readlink "$link")" == /etc/init.d/* ]] && \ - rc-service "$(basename "$link")" restart -done</code></pre> + <description><![CDATA[<p><a href="https://github.com/equwal/tiny-runlevels" class="external-link">mirrored +on github for convenience here</a></p> +<p>Using OpenRC runlevels to have lots of instances of simple (network) +programs like quark for multiple http serving locally or +<a href="https://tools.suckless.org/ii/" class="external-link">ii</a> +(or +<a href="https://tools.suckless.org/sic/" class="external-link">sic</a>) +for IRC server connections.</p> +<p>To keep programs simple, they should not do the same process for +unrelated uses. It is much more complicated to configure and manage +multiple webservers in the same process (like how nginx does it) than +just one. Init systems are designed to manage processes, and should be +used instead. Do one thing etc. etc.</p> +<p>This is how to use the OpenRC runlevels for quark and ii runlevels as +examples.</p> +<h3 id="the-tree-on-my-machine">The Tree (on my machine)</h3> +<pre><code>/etc/runlevels +├── boot +│ └── ... +├── default +│ └── ... +├── irc-base +│ ├── oftc -> /etc/init.d/oftc +│ ├── liberachat -> /etc/init.d/liberachat +│ └── ... +├── net-base +│ ├── default -> ../default +│ └── quark -> ../quark +├── net-offline +│ ├── default -> ../default +│ └── net-base -> ../net-base +├── net-dns +│ ├── dnscrypt-proxy -> /etc/init.d/dnscrypt-proxy +│ └── unbound -> /etc/init.d/unbound +├── net-wifi +│ ├── dhcpcd -> /etc/init.d/dhcpcd +│ ├── net-base -> /etc/runlevels/net-base +│ ├── net-dns -> /etc/runlevels/net-dns +│ └── wpa_supplicant -> /etc/init.d/wpa_supplicant +├── net-wifi-irc +│ ├── irc-base -> ../irc-base +│ └── net-wifi -> ../net-wifi +├── quark +│ ├── quark-docs -> /etc/init.d/quark-docs +│ ├── quark-equwal -> /etc/init.d/quark-equwal +│ └── ... +├── shutdown +│ └── ... +└── sysinit + └── ...</code></pre> +<p>as you can see, IRC is connected after the real internet on wifi +(net-wifi), but quark runs on any network runlevel using net-base.</p> +<h3 id="how-to">How To:</h3> +<p>OpenRC has its own commands for making the runlevels, but I find them +confusing. Let’s just edit the files.</p> +<pre><code># make runlevel +mkdir /etc/runlevels/quark +# add services (as many as needed) +ln -s /etc/int.d/quark-whatever /etc/runlevels/quark +# add runlevel to parent +ln -s /etc/runlevels/default /etc/runlevels/quark +# Reload since openrc is in default +openrc default</code></pre> +<p>That works, but what about for networked IRC on a custom networking +runlevel? Just add it to the networking runlevel.</p> +<pre><code># (first, make a network runlevel that contains default! Without default the system will crash, obviously.) +mkdir /etc/runlevels/net-wifi +ln -s /etc/runlevels/net-wifi /etc/runlevels/default +ln -s /etc/init.d/wpa_supplicant /etc/runlevels/net-wifi +# etc. +# Now add the irc-base to the network runlevel +mkdir /etc/runlevels/irc-base +ln -s /etc/init.d/liberachat irc-base +ln -s /etc/init.d/oftc irc-base +ln -s /etc/runlevels/irc-base /etc/runlevels/net-wifi +openrc net-wifi</code></pre> +<h3 id="tool-restart-runlevel">Tool: restart-runlevel</h3> +<p>Openrc wants switch the whole stack <code>openrc runlevel</code> so I +made a little tool to just restart a specific runlevel. Nice for +debugging.</p> +<pre><code>#!/bin/bash + +for link in /etc/runlevels/${1}/* +do [[ -L "$link" && "$(readlink "$link")" == /etc/init.d/* ]] && \ + rc-service "$(basename "$link")" restart +done</code></pre> ]]></description> </item> <item> @@ -371,18 +371,18 @@ done</code></pre> <link>https://recentlywritten.com/Mailing-list-in-one-line.html</link> <guid isPermaLink="true">https://recentlywritten.com/Mailing-list-in-one-line.html</guid> <pubDate>Sat, 06 Sep 2025 00:00:00 +0000</pubDate> - <description><![CDATA[<h1 id="list-of-emails.txt">==> list-of-emails.txt <==</h1> -<pre><code>Your Name <youremail@example.com> -... -... -# ==> mailing-list.sh <== -#!/bin/sh -while read email; do neomutt -H "$MESSAGEFILE" "$email" < /dev/null; done < /dev/stdin</code></pre> -<p>Make an mbox email with neomutt of whatever.<br /> -Now run it.</p> -<pre><code>cat list-of-emails.txt | mailing-list.sh email-file.mbox</code></pre> -<p>Now make an alias in (zsh) for extreme FAST mailing</p> -<pre><code>alias mail2list='f(){ [ -n "$1" ] && cat /home/jose/.config/mailing-list/the-mailing-list | mailing-list "$1" }; f'</code></pre> + <description><![CDATA[<h1 id="list-of-emails.txt">==> list-of-emails.txt <==</h1> +<pre><code>Your Name <youremail@example.com> +... +... +# ==> mailing-list.sh <== +#!/bin/sh +while read email; do neomutt -H "$MESSAGEFILE" "$email" < /dev/null; done < /dev/stdin</code></pre> +<p>Make an mbox email with neomutt of whatever.<br /> +Now run it.</p> +<pre><code>cat list-of-emails.txt | mailing-list.sh email-file.mbox</code></pre> +<p>Now make an alias in (zsh) for extreme FAST mailing</p> +<pre><code>alias mail2list='f(){ [ -n "$1" ] && cat /home/jose/.config/mailing-list/the-mailing-list | mailing-list "$1" }; f'</code></pre> ]]></description> </item> <item> @@ -390,124 +390,124 @@ Now run it.</p> <link>https://recentlywritten.com/Dont-use-make-uninstall.html</link> <guid isPermaLink="true">https://recentlywritten.com/Dont-use-make-uninstall.html</guid> <pubDate>Sat, 06 Sep 2025 00:00:00 +0000</pubDate> - <description><![CDATA[<p>Much like “sending a file over the internet”, “installing software” -has not been solved generally. There’s more than one way to do it. A -mixed system that uses both declarative and traditional package managers -in unison is the way to go for now. It would be ideal to package a -non-specific declarative package install definition together with the -source of programs, and make unnecessary the concept of a “package -maintainer” for each package manager. The existence of two declarative -package managers already suggests the need for an arbitrary standard -which can transformed into a definition for any declarative system.</p> -<p>I used an LLM to generate hundreds of uninstall targets for make and -submit patches to the authors. Three authors wouldn’t patch my changes -in. Are they right? The argument goes like this: the software should not -be installed using make because make doesn’t register file install -locations in any way. Therefore make only uninstalles the correct files -by coincidence. For installing, it can do a little bit better using the -<code>install</code> program.</p> -<p>There is a better way which has been around forever: just use the -build from the source tree.</p> -<p>Let’s consider how the ASDF manager for Common Lisp works (and by -extension, quicklisp, which gets ASDF systems from the internet). It has -a central registry variable with a list of paths, and it recurs down it -to findsystem definitions when the definition loader is called. Then it -loads the files into the lisp core. As a result there is no need to have -code and binaries in different places. If compiled, it will just store -the compiled files together with the source. To “uninstall”, just delete -that project’s directory. Let’s call this “in-situ” package -management.</p> -<p>With POSIX make and arbitrary build systems like it, the subordinate -model can’t work, because ASDF can’t possibly predetermine what binaries -to use and where to put them. The logic can’t be generalized in the -package manager, and has to be managed per-project. Every package -manager now needs thousands of packages with hundreds of maintainers. -Typical package managers do installs imperatively and tracking the file -location metadata in the system flies. When the binaries or libraries -are edited or moved by an outside program or a user without editing the -registry, (for example, by trying to re-install gcc manually from -source) it can break the system.</p> -<p>The simplest way to get this kind of management is to use the -symlinks to the files from directories in the PATH. If the installed -files change, but the path stays the same, they can be updated without -changing the “installed” data at all. IT’s still tenuous – an update to -the build system could change the locations of built binaries.</p> -<h2 -id="declarative-and-in-situ-package-managers-nix-and-guix">Declarative -and in-situ package managers: Nix and Guix</h2> -<p>The Nix package manager uses the model of keeping the binaries in the -package manager’s repo without “installing” them. This is why nix -systems can’t break unless impure hacks are used.. Since binaries and -libraries are not <em>moved</em>, there is no chance of overwriting -things or losing track of where they are!</p> -<p>Let’s not distribute installers in the code builders like make, but -instead build it and use it as-is from the folder using an in-situ -package manager. By chance, that’s exactly how declarative package -managers work, and not how traditional registry managers work.</p> -<p>The benefits of declarative package management are plentiful, but -come at the cost of making development of one’s own programs and -installation of as-yet unpackaged software from the source more -difficult. Even simple shell scripts added to the PATH can’t be done -simply, the whole abstraction of the package manager has to be invoked, -or some impure hacks are needed.</p> -<p>The declarative package managers can be installed on another linux -which has a traditional registry package manager and impure environment. -Why not have both? It is “possible” to install two traditional package -managers on the same system, and will almost immediately break it due to -out of sync dependency management. With in-situ and system registry -managers installed together there are no conflicts, because the in-situ -manager stays in its own folder.</p> -<p>Package management solutions:</p> -<ul> -<li><p>In the build system -(<code>make install/uninstall</code>)</p></li> -<li><p>Using symlinks in the path (<code>ln -s</code>)</p></li> -<li><p>In-situ</p></li> -<li><p>Declarative + in-situ</p></li> -<li><p>Traditional system registry package managers</p></li> -<li><p>Declarative meta-package management language (does not exist -yet).</p></li> -</ul> -<h2 -id="final-note-should-there-be-an-uninstall-target-in-the-makefile">Final -note: should there be an uninstall target in the Makefile?</h2> -<ul> -<li><p>No, if the makefile doesn’t “install” the software but just -builds it.</p></li> -<li><p>Yes, if the makefile does “install” the software, it should also -have a way to “uninstall” the software.</p></li> -</ul> -<h2 -id="final-note-but-i-want-to-uninstall-something-anyway-with-nothing-more-than-make-and-not-use-an-uninstall">Final -note: but I want to uninstall something anyway with nothing more than -make and not use an uninstall!</h2> -<h3 -id="use-make-install-to-a-destdir-to-see-what-files-it-installs-and-remove-them">Use -make install to a DESTDIR to see what files it installs and remove -them</h3> -<p>It is the best way, albeit tedious and manual.</p> -<p>“rofl0r” says:</p> -<p>As the maintainer of a -<a href="https://github.com/sabotage-linux/sabotage" class="external-link">linux -distro</a>, i quickly learned that the DESTDIR <<a -href="https://www.gnu.org/prep/standards/html_node/DESTDIR.html" -class="uri">https://www.gnu.org/prep/standards/html_node/DESTDIR.html</a>> -variable is really *the* key to cleanly track the files installed by -arbitrary source projects, apart from much more elaborate solutions such -as doing installs in a sandbox with before/after comparison or using -file-system monitoring (e.g. via ptrace). it allows to install all files -into an arbitrary location, which makes it easy to e.g. create a -filelist, or in the case of my distro, the DESTDIR is used as the final -location where the package actually lives. if we take curl as an -example, it would be installed with empty prefix and DESTDIR=/opt/curl, -so the curl binary would live in /opt/curl/bin/curl, headers in -/opt/curl/include, etc. the package manager, as the last step of the -build/install process, then iterates over all files in /opt/curl and -symlinks them into the root prefix, e.g. /bin/curl will point to -/opt/curl/bin/curl. uninstalling a package then is as easy as to iterate -again over the files in /opt/curl (or in my case a filelist made -thereof, to reduce the amount of syscalls) to remove the symlinks and -finally rm -rf /opt/curl to delete the actual files.</p> + <description><![CDATA[<p>Much like “sending a file over the internet”, “installing software” +has not been solved generally. There’s more than one way to do it. A +mixed system that uses both declarative and traditional package managers +in unison is the way to go for now. It would be ideal to package a +non-specific declarative package install definition together with the +source of programs, and make unnecessary the concept of a “package +maintainer” for each package manager. The existence of two declarative +package managers already suggests the need for an arbitrary standard +which can transformed into a definition for any declarative system.</p> +<p>I used an LLM to generate hundreds of uninstall targets for make and +submit patches to the authors. Three authors wouldn’t patch my changes +in. Are they right? The argument goes like this: the software should not +be installed using make because make doesn’t register file install +locations in any way. Therefore make only uninstalles the correct files +by coincidence. For installing, it can do a little bit better using the +<code>install</code> program.</p> +<p>There is a better way which has been around forever: just use the +build from the source tree.</p> +<p>Let’s consider how the ASDF manager for Common Lisp works (and by +extension, quicklisp, which gets ASDF systems from the internet). It has +a central registry variable with a list of paths, and it recurs down it +to findsystem definitions when the definition loader is called. Then it +loads the files into the lisp core. As a result there is no need to have +code and binaries in different places. If compiled, it will just store +the compiled files together with the source. To “uninstall”, just delete +that project’s directory. Let’s call this “in-situ” package +management.</p> +<p>With POSIX make and arbitrary build systems like it, the subordinate +model can’t work, because ASDF can’t possibly predetermine what binaries +to use and where to put them. The logic can’t be generalized in the +package manager, and has to be managed per-project. Every package +manager now needs thousands of packages with hundreds of maintainers. +Typical package managers do installs imperatively and tracking the file +location metadata in the system flies. When the binaries or libraries +are edited or moved by an outside program or a user without editing the +registry, (for example, by trying to re-install gcc manually from +source) it can break the system.</p> +<p>The simplest way to get this kind of management is to use the +symlinks to the files from directories in the PATH. If the installed +files change, but the path stays the same, they can be updated without +changing the “installed” data at all. IT’s still tenuous – an update to +the build system could change the locations of built binaries.</p> +<h2 +id="declarative-and-in-situ-package-managers-nix-and-guix">Declarative +and in-situ package managers: Nix and Guix</h2> +<p>The Nix package manager uses the model of keeping the binaries in the +package manager’s repo without “installing” them. This is why nix +systems can’t break unless impure hacks are used.. Since binaries and +libraries are not <em>moved</em>, there is no chance of overwriting +things or losing track of where they are!</p> +<p>Let’s not distribute installers in the code builders like make, but +instead build it and use it as-is from the folder using an in-situ +package manager. By chance, that’s exactly how declarative package +managers work, and not how traditional registry managers work.</p> +<p>The benefits of declarative package management are plentiful, but +come at the cost of making development of one’s own programs and +installation of as-yet unpackaged software from the source more +difficult. Even simple shell scripts added to the PATH can’t be done +simply, the whole abstraction of the package manager has to be invoked, +or some impure hacks are needed.</p> +<p>The declarative package managers can be installed on another linux +which has a traditional registry package manager and impure environment. +Why not have both? It is “possible” to install two traditional package +managers on the same system, and will almost immediately break it due to +out of sync dependency management. With in-situ and system registry +managers installed together there are no conflicts, because the in-situ +manager stays in its own folder.</p> +<p>Package management solutions:</p> +<ul> +<li><p>In the build system +(<code>make install/uninstall</code>)</p></li> +<li><p>Using symlinks in the path (<code>ln -s</code>)</p></li> +<li><p>In-situ</p></li> +<li><p>Declarative + in-situ</p></li> +<li><p>Traditional system registry package managers</p></li> +<li><p>Declarative meta-package management language (does not exist +yet).</p></li> +</ul> +<h2 +id="final-note-should-there-be-an-uninstall-target-in-the-makefile">Final +note: should there be an uninstall target in the Makefile?</h2> +<ul> +<li><p>No, if the makefile doesn’t “install” the software but just +builds it.</p></li> +<li><p>Yes, if the makefile does “install” the software, it should also +have a way to “uninstall” the software.</p></li> +</ul> +<h2 +id="final-note-but-i-want-to-uninstall-something-anyway-with-nothing-more-than-make-and-not-use-an-uninstall">Final +note: but I want to uninstall something anyway with nothing more than +make and not use an uninstall!</h2> +<h3 +id="use-make-install-to-a-destdir-to-see-what-files-it-installs-and-remove-them">Use +make install to a DESTDIR to see what files it installs and remove +them</h3> +<p>It is the best way, albeit tedious and manual.</p> +<p>“rofl0r” says:</p> +<p>As the maintainer of a +<a href="https://github.com/sabotage-linux/sabotage" class="external-link">linux +distro</a>, i quickly learned that the DESTDIR <<a +href="https://www.gnu.org/prep/standards/html_node/DESTDIR.html" +class="uri">https://www.gnu.org/prep/standards/html_node/DESTDIR.html</a>> +variable is really *the* key to cleanly track the files installed by +arbitrary source projects, apart from much more elaborate solutions such +as doing installs in a sandbox with before/after comparison or using +file-system monitoring (e.g. via ptrace). it allows to install all files +into an arbitrary location, which makes it easy to e.g. create a +filelist, or in the case of my distro, the DESTDIR is used as the final +location where the package actually lives. if we take curl as an +example, it would be installed with empty prefix and DESTDIR=/opt/curl, +so the curl binary would live in /opt/curl/bin/curl, headers in +/opt/curl/include, etc. the package manager, as the last step of the +build/install process, then iterates over all files in /opt/curl and +symlinks them into the root prefix, e.g. /bin/curl will point to +/opt/curl/bin/curl. uninstalling a package then is as easy as to iterate +again over the files in /opt/curl (or in my case a filelist made +thereof, to reduce the amount of syscalls) to remove the symlinks and +finally rm -rf /opt/curl to delete the actual files.</p> ]]></description> </item> <item> @@ -515,33 +515,33 @@ finally rm -rf /opt/curl to delete the actual files.</p> <link>https://recentlywritten.com/tmpl-insanely-simple-templates.html</link> <guid isPermaLink="true">https://recentlywritten.com/tmpl-insanely-simple-templates.html</guid> <pubDate>Sat, 06 Sep 2025 00:00:00 +0000</pubDate> - <description><![CDATA[<p><a href="https://github.com/equwal/tmpl" class="external-link">git -repo here</a></p> -<p>Templates for all kinds of things. Just read a file into your editor -at the cursor and jump to the <++> locations.</p> -<p>Here is one such template:</p> -<pre><code>(defpackage :<++>-system (:use :cl :asdf)) -(in-package :<++>-system) -(defsystem <++> - :name "<++>" - :author "<++> <<++>@<++>.<++>>" - :version "<++>" - :maintainer "<++> <<++>@<++>.<++>>" - :license "GNU GPLv3.0" - :description "<++>" - ;; put the most general files first to minimize the "depends on" use - ;; and in that case you'll need :serial t - :serial <++> - :components ((:file "packages") - (:file "<++>" :depends-on ("<++>"))) - :weakly-depends-on (<++>) - :depends-on (<++>))</code></pre> -<h2 id="using-with-vim">Using with Vim</h2> -<pre><code>:read /path/to/tmpl/thing</code></pre> -<p>Make sure to add a templating shortcut to your leader key to jump to -the <code><++></code> spots.</p> -<pre><code> -- Templating shortcut - map("n", "<leader><Space>", "/<++><CR>dt>a<BS>", { desc = "Jump to next template placeholder" })</code></pre> + <description><![CDATA[<p><a href="https://github.com/equwal/tmpl" class="external-link">git +repo here</a></p> +<p>Templates for all kinds of things. Just read a file into your editor +at the cursor and jump to the <++> locations.</p> +<p>Here is one such template:</p> +<pre><code>(defpackage :<++>-system (:use :cl :asdf)) +(in-package :<++>-system) +(defsystem <++> + :name "<++>" + :author "<++> <<++>@<++>.<++>>" + :version "<++>" + :maintainer "<++> <<++>@<++>.<++>>" + :license "GNU GPLv3.0" + :description "<++>" + ;; put the most general files first to minimize the "depends on" use + ;; and in that case you'll need :serial t + :serial <++> + :components ((:file "packages") + (:file "<++>" :depends-on ("<++>"))) + :weakly-depends-on (<++>) + :depends-on (<++>))</code></pre> +<h2 id="using-with-vim">Using with Vim</h2> +<pre><code>:read /path/to/tmpl/thing</code></pre> +<p>Make sure to add a templating shortcut to your leader key to jump to +the <code><++></code> spots.</p> +<pre><code> -- Templating shortcut + map("n", "<leader><Space>", "/<++><CR>dt>a<BS>", { desc = "Jump to next template placeholder" })</code></pre> ]]></description> </item> <item> @@ -549,52 +549,52 @@ the <code><++></code> spots.</p> <link>https://recentlywritten.com/tag-gen.html</link> <guid isPermaLink="true">https://recentlywritten.com/tag-gen.html</guid> <pubDate>Fri, 05 Sep 2025 00:00:00 +0000</pubDate> - <description><![CDATA[<p><a href="https://github.com/equwal/tag-gen" class="external-link">git -hub website link here</a></p> -<h2 id="purpose">PURPOSE:</h2> -<p>Specify which directories to generate tags for, and what kinds of -files<br /> -to generate them for in each. Good for tag jumping in an editor.</p> -<h2 id="requirements">Requirements</h2> -<ul> -<li><p>An ANSI Common Lisp</p></li> -<li><p>ASDF (for UIOP portable shell facilities)</p></li> -<li><p>A ctags-like program.</p></li> -<li><p>Desire</p></li> -</ul> -<h2 id="non-featuresnon-requirements">Non-features/Non-Requirements</h2> -<ul> -<li><p>Not multithreaded!</p></li> -<li><p>Works with any tag program (doesn’t do any tagging -itself)!</p></li> -<li><p>No special configuration language, just two sexps!</p></li> -<li><p>Does not use Roswell!</p></li> -<li><p>Works on my machine!</p></li> -</ul> -<h2 id="install">Install</h2> -<ol type="1"> -<li><p>put this folder somewhere</p></li> -<li><p>put the config folder somewhere</p></li> -<li><p>put the tag-gen.sh and tag-gen-root.sh somewhere</p></li> -<li><p>put the cron job in</p></li> -<li><p>put your configuration in</p></li> -</ol> -<p>Edit the config/ files with the paths you want tagged.</p> -<p>Add a command to cron like:</p> -<pre><code>*/29 * * * * su username -c 'tag-gen.sh /path/to/tag-gen/local.conf /usr/bin/etags' -*/29 * * * * su root -c 'tag-gen-root.sh /path/to/tag-gen/root.conf /usr/bin/etags'</code></pre> -<p>for routine tagging.</p> -<p>tags.conf needs to contain this kind of format:</p> -<pre><code>"/path/to/ctags/program" - -(("<directory>" ("<ext>"...)) - ...)</code></pre> -<p>The tags program reads the file extensions to infer what language to -do tags for. Specify the directories you want to use tag browsing -programs on.</p> -<p>See examples in config-examples. Configuration is -<strong>mandatory</strong> for the program to work. The format is just -read with the lisp reader and is very simple.</p> + <description><![CDATA[<p><a href="https://github.com/equwal/tag-gen" class="external-link">git +hub website link here</a></p> +<h2 id="purpose">PURPOSE:</h2> +<p>Specify which directories to generate tags for, and what kinds of +files<br /> +to generate them for in each. Good for tag jumping in an editor.</p> +<h2 id="requirements">Requirements</h2> +<ul> +<li><p>An ANSI Common Lisp</p></li> +<li><p>ASDF (for UIOP portable shell facilities)</p></li> +<li><p>A ctags-like program.</p></li> +<li><p>Desire</p></li> +</ul> +<h2 id="non-featuresnon-requirements">Non-features/Non-Requirements</h2> +<ul> +<li><p>Not multithreaded!</p></li> +<li><p>Works with any tag program (doesn’t do any tagging +itself)!</p></li> +<li><p>No special configuration language, just two sexps!</p></li> +<li><p>Does not use Roswell!</p></li> +<li><p>Works on my machine!</p></li> +</ul> +<h2 id="install">Install</h2> +<ol type="1"> +<li><p>put this folder somewhere</p></li> +<li><p>put the config folder somewhere</p></li> +<li><p>put the tag-gen.sh and tag-gen-root.sh somewhere</p></li> +<li><p>put the cron job in</p></li> +<li><p>put your configuration in</p></li> +</ol> +<p>Edit the config/ files with the paths you want tagged.</p> +<p>Add a command to cron like:</p> +<pre><code>*/29 * * * * su username -c 'tag-gen.sh /path/to/tag-gen/local.conf /usr/bin/etags' +*/29 * * * * su root -c 'tag-gen-root.sh /path/to/tag-gen/root.conf /usr/bin/etags'</code></pre> +<p>for routine tagging.</p> +<p>tags.conf needs to contain this kind of format:</p> +<pre><code>"/path/to/ctags/program" + +(("<directory>" ("<ext>"...)) + ...)</code></pre> +<p>The tags program reads the file extensions to infer what language to +do tags for. Specify the directories you want to use tag browsing +programs on.</p> +<p>See examples in config-examples. Configuration is +<strong>mandatory</strong> for the program to work. The format is just +read with the lisp reader and is very simple.</p> ]]></description> </item> </channel> diff --git a/site/sbm.html b/site/sbm.html index dcf4c98..94cdf70 100755 --- a/site/sbm.html +++ b/site/sbm.html @@ -32,60 +32,43 @@ <h1 class="post-title">sbm</h1> - <p>How to keep track of thousands of bookmarks with a simple tool and - your own tags.</p> - <h3 id="copy-or-add-a-bookmark">Copy or add a bookmark:</h3> - <figure> - <img src="static/firstscrn.png" alt="Copy or Add a bookmark." /> - <figcaption aria-hidden="true">Copy or Add a bookmark.</figcaption> - </figure> - <h3 - id="dmenu-fuzzy-search-dialogue-for-all-your-bookmarks.-simple-text-format.">dmenu - fuzzy search dialogue for all your bookmarks. Simple text format.</h3> - <p><img src="static/secondscrn.png" - alt="Searching for booksmarks" /><br /> - <a href="https://github.com/equwal/sbm">github.com/equwal/sbm</a></p> - <p>It needs to be made with make and the config file should be edited - too. More docs soon, although it is a simple program. Details in the - source.</p> - <p><a href="https://karl-voit.at/2022/01/29/How-to-Use-Tags/">Karl - Voit’s article (the good ideas are from here)</a><br /> - <a href="static/sbm-0.1.tar.gz">download the dmenu package</a></p> - <p>Grand Generalized Dmenu Tagger coming soon to stores near you.</p> - <h3 id="scripts">Scripts</h3> + <p>Suckless Bookmark Manager (now sbm Sync)</p> + <p>sbm is a bookmark manager, originally a dmenu script. It is now a + multiplatform, cloud synced bookmark manager with support for + teams.</p> + <h2 id="promo-video">Promo video</h2> + <p><a href="https://www.youtube.com/watch?v=iKmYWTCkW7c" + class="uri">https://www.youtube.com/watch?v=iKmYWTCkW7c</a></p> + <h2 id="try-it-on-the-web">Try it on the web</h2> <ul> - <li><ol type="1"> - <li>bm – search & copy, add, or edit/plumb a bookmark (edit/plumb - not implemented yet).</li> - </ol></li> + <li><a href="https://sbmsync.com">sbmsync.com</a></li> </ul> - <h3 id="install">Install</h3> - <p>Requirements: xclip, dmenu, make</p> + <h2 id="projects">Projects</h2> <ul> - <li>Export the $BOOKMARKS variable containing the location of the - bookmarks. I like to use ~/.local/share/sbm to store my config.<br /> - mkdir -p ~/.local/share/sbm/<br /> - ~/.bashrc<br /> - export BOOKMARKS=“~/.local/share/sbm/bookmarks”</li> - <li>define your tag choices in USERTAGS and export that too. The file - syntax is:<br /> - <tag><space><description><newline><br /> - See the included usertags file for an example.<br /> - ~/.bashrc<br /> - export USERTAGS=“~/.local/share/sbm/usertags”<br /> - </li> - <li>make install</li> + <li><a href="https://github.com/equwal/sbm">sbm</a> multiplatform + computer application</li> + <li><a href="https://github.com/equwal/sbm-android">sbm-android</a> + android app</li> + <li><a + href="https://github.com/equwal/sbm-extension">sbm-extension</a> + firefox and chrome extensions</li> + <li><a href="https://github.com/equwal/sbm-sync">sbm-sync</a> the sync + server</li> + <li><a href="https://github.com/equwal/sbm-suckless">sbm-suckless</a> + the original POSIX shell script, suckless edition (no vibecode)</li> </ul> - <h3 id="usage">Usage</h3> - <p>Execute</p> - <p>search-term is an extended regex for grep.</p> - <p>Bookmark lines are space separated values<br /> - URL description</p> - <h3 id="tip">Tip</h3> - <p>The bookmarks can be converted from the web browser formats using - netscape-bookmark-converter at</p> - <p><a - href="https://github.com/jhh/netscape-bookmark-converter">github.com/jhh/netscape-bookmark-converter</a></p> + <h2 id="how-it-works">How it works</h2> + <p>Fuzzy search bookmarks and quickly add/copy/view bookmarks. Now + with syncing through the browser and everything.</p> + <h2 id="why">Why</h2> + <p>This tool gives you the power to spam links to your friends to the + point that it annoys them.</p> + <p>Like many others, I find search engines to be pretty tedious to + use. Searching my own bookmarks is much better. With sbm you can be + like me and have BASED links at your fingertips.</p> + <h2 id="support">Support</h2> + <p>Support the work at <a + href="https://ko-fi.com/truex">ko-fi.com/truex</a>.</p> <div id="footer"> <a href="index.html">← Home</a> · diff --git a/site/subread.html b/site/subread.html new file mode 100644 index 0000000..0ab4125 --- /dev/null +++ b/site/subread.html @@ -0,0 +1,106 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8" /> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <title>SubRead — Recently Written</title> + <meta property="og:type" content="article" /> + <meta property="og:site_name" content="Recently Written" /> + <meta property="og:title" content="SubRead" /> + <meta property="og:url" content="https://recentlywritten.com/subread.html" /> + <meta property="og:image" content="https://recentlywritten.com/static/og.png" /> + <meta name="twitter:card" content="summary_large_image" /> + <link rel="stylesheet" href="style.css" /> + <link rel="alternate" type="application/rss+xml" title="Recently Written" href="rss.xml" /> +</head> +<body> +<div id="container"> + + <div id="top"> + <a class="site-title" href="index.html">Recently Written</a> + <nav> + <a href="index.html">Home</a> + <a href="about.html">about</a> + <a href="lair.html">code</a> + <a href="git/index.html">git</a> + <a href="youtube.html">youtube</a> + <a href="esperanto.html">esperanto</a> + <a href="call.html">contact</a> + <a href="rss.xml">rss</a> + </nav> + </div> + + <h1 class="post-title">SubRead</h1> + + <p>SubRead makes it possible to read books with synced subtitles that + keep your place. This is very nice for language learning.</p> + <p>Subread is a suite of tools that port forced alignment to a variety + of platforms. It is 100% free when used locally, although it is + possible to do conversions with my cloud for a fee. It is 100% + self-hostable free software. BUY NOW!</p> + <h2 id="promo-video">Promo Video</h2> + <p><a href="https://www.youtube.com/watch?v=WRz7UQZwe-Q" + class="uri">https://www.youtube.com/watch?v=WRz7UQZwe-Q</a></p> + <h2 id="try-it-on-the-web">Try it on the web</h2> + <ul> + <li><a href="https://subread.space">subread.space</a>: webpage to do + the conversions</li> + <li><a href="https://honjimaku.com">honjimaku.com</a>: website to + download or upload srt files for Japanese audiobooks</li> + <li><a href="https://rtr46.github.io/kikiyomi/">kikiyomi</a>: Try + reading your audiobook/srt combo on the web</li> + </ul> + <h2 id="projects">Projects</h2> + <ul> + <li><a href="https://github.com/equwal/subplz-web">subplz-web</a>: + subread.space source</li> + <li><a + href="https://github.com/equwal/subread-android">subread-android</a>: + subread.space android app (local and cloud conversions are + possible)</li> + <li><a + href="https://github.com/equwal/subread-extension">subread-extension</a>: + Extension to use subread on youtube for audiobooks published + there.</li> + <li><a + href="https://github.com/equwal/subread-overlay">subread-overlay</a>: + Android app to show the subtitles as an overlay on the phone. Can be + used with the dictionary for a very nice AJATT experience.</li> + <li><a + href="https://github.com/equwal/subread-dictionary">subread-dictionary</a>: + Yomitan pop-up dictionary standalone android app. Works really good + with the overlay, but can be used anywhere!</li> + <li><a + href="https://github.com/equwal/subread.koplugin">subread.koplugin</a>: + KOReader plugin that does live highlighting of the book while you + listen to it in another app like Voice, VLC, or MPV.</li> + <li><a + href="https://github.com/equwal/subrep-android">subrep-android</a>: + Live whisper captions. Better than the ones that come with + android.</li> + <li><a + href="https://github.com/equwal/desktop-subtitle-replay">desktop-subtitle-replay</a>: + Whisper on your computer, and broadcast them to your friends. Useful + for online language classrooms or bilingual exchanges.</li> + <li><a href="https://github.com/equwal/honjimaku">honjimaku</a>: Book + subtitles database for japanese</li> + <li><a + href="https://github.com/equwal/Hoshi-Reader-Android">Hoshi-Reader-Android</a>: + Fork of hoshi reader that can do the conversion inside hoshi reader. + Hopefully gets merged.</li> + </ul> + <h2 id="why">Why</h2> + <p>Extremely useful for learning languages by reading books with the + audiobook.</p> + <h2 id="support">Support</h2> + <p>Support the work at <a + href="https://ko-fi.com/truex">ko-fi.com/truex</a>.</p> + + <div id="footer"> + <a href="index.html">← Home</a> · + <a href="https://github.com/equwal">Github</a> + </div> + +</div> +</body> +</html>