The pages where I write about Emacs. It doesn’t happen very often. I think you’re probably best off following Planet Emacsen, the ultimate Emacs related blog aggregator.

2020-07-02 An overview over my Gemini projects

A while ago I started writing lots of stuff for Gemini. Time for an overview, both for myself and for you, the hypothetical reader. 😀

I’m not going to link to the various blog posts where I’ve talked about the various projects before. If you want to find them, take a look at the Gemini tag.

Gemini Server is a server that serves an existing Oddmuse wiki via Gemini protocol. It also tries translate the wiki text from a typical Markdown + Wiki mess like the one I’m using on this wiki here into Gemini format. I think it works and you can look at it using your favourite Gemini Client. It’s at alexschroeder.ch:1965.

Gemini & Titan for Bash are two functions for bash. I use them all the time to debug stuff. The gemini function uses the Gemini protocol to fetch stuff from the Internet and dumps it. No formatting, header and all. The titan function uses the Titan protocol to write text and files to a Titan-enabled Gemini server, such as the ones I run.

Titan is where I’ve written down a few words on the protocol I use to upload files to my wiki. There hasn’t been much talk about the Titan protocol, partly because I felt pretty much alone in my interest for wikis. On the Gemini mailing list, people were talking about using SFTP or mail to upload or comment, or about how they disliked commenting, and so on. I figured I’ll just have to implement some stuff and then maybe other people might get interested, once it’s shown its utility, even if we then change small aspects of the protocol. If you want to talk about Titan, feel free to contact me, or comment or edit that Titan page. It’s also hosted on a wiki!

Community Wiki, where the Titan page is being hosted, is also reachable via Gemini and editable via Titan. The quality of the translation from wiki text to Gemini format isn’t all that great because it never switched to Markdown. It’s mostly Wiki Creole and a bunch of specific extensions. It’s available at communitywiki.org:1966.

Next, I wanted to see how to translate a dense hypertext like Wikipedia to the Gemini format and I wrote Gemini Wikipedia, a Wikipedia proxy strips most of the links in order to provide you with a nice reading experience; it also tries its best to translate tables to text (probably not a good way to read those tables if you’re blind, sadly). If you really want to, you can always get the HTML including all the links, and depending on your browser, it might work. It’s available at alexschroeder.ch:1967. I recommend starting with the Project Gemini page. It’s the page I used to check my code as I was developing it. 😀

Gemini Wiki, finally, is my wiki for everybody. It builds on the Gemini Server I used for this site. It uses a Gemini format internally. It allows you to add pages and files to the wiki directly. It even has a very simple, read-only web interface! It has “spaces” so you can host multiple wikis for different people. I’ve been using my installation to write about it. It’s at alexschroeder.ch:1968, and as I said, you can also access it via a web browser on the same port.

Oh, and if you’re an Emacs person, there’s more...

Gemini Write is an extension to Elpher, the Emacs Gopher and Gemini client, which allows you to edit pages right there, in Emacs. I also started working on a “multiple buffers” branch for Elpher. You can find it in The Lambda Lab’s git repository, via Gopher!

Ah, and before I forget: here’s a video of me editing Gemini Wiki, from Emacs! You might have to right-click the preview image and choose “Play” from the context menu. It depends on your browser and your settings, I guess.

So happy. 😀


Add Comment

2020-06-11 Demonstrating Gemini Wiki

This wiki is also served via the Gemini protocol (something between Gopher and the Web as we know it). I’ve proposed an extension that allows me to write back to the wiki (and not just leave a single line of comments). In case you’re curious, today I made a short 50s video!

Made using Emacs, Elpher, Gemini, Oddmuse, Peek, and Garage Band. 😀

If you’re interested in how this works, I think the two two bash functions I wrote on 2020-06-17 Tiny Gemini Client in Bash make perfectly good examples: gemini allows you to read and titan allows you to write.

There’s a separate Titan page.


Comments on 2020-06-11 Demonstrating Gemini Wiki

Let’s see how this works with a gemini client.

– Anonymous 2020-06-11 22:52 UTC

If you want to be non-anonymous, I guess you need Gemini Write support. If you have it, just edit the page and there you go.

Or I could add another back and forth to ask your name every time you comment. Do you think that would be worth it?

– Alex Schroeder 2020-06-12 18:05 UTC

Starting a series of wiki pages on how to set up your own Gemini Wiki using Oddmuse.

– Alex Schroeder 2020-06-13 20:25 UTC

Add Comment

2020-06-05 Gemini Write

My new package gemini-write can be used to edit this site via my Gemini Write proposal.

In order to browse Gemini sites, I use Elpher.

In order to get Gemini highlighting, I use Gemini Mode.

Once you have all three packages installed, visit this site, find a page you want to edit, follow the link to the “Raw text” at the bottom and then use e to edit it. The raw pages are the only pages that can be edited. Use C-c C-c to save, use C-c C-k to cancel. Customize elpher-gemini-tokens to set passwords, tokens, or whatever you need in order to edit sites.

Currently this only works on this site, I guess.

And I currently don’t have a markup rule to render Gemini links, but I’ll add that as soon as somebody posts one. 😀

Test it here: Gemini Test.


Comments on 2020-06-05 Gemini Write

I wonder if you also plan to support search functionality at some point?

deshipu 2020-06-05 13:57 UTC

Yes. I did that just now.

– Alex Schroeder 2020-06-05 21:21 UTC

There is still some sort of bug where saving doesn’t always work and if it does not, then whatever you wrote is lost. That is definitely disappointing. I’m suspecting that it depends on the page name.

– Alex Schroeder 2020-06-07 09:32 UTC

I’m starting to see the difficulties of rendering the raw wiki text to Gemini using regular expressions. That part is definitely trickier than I thought.

– Alex 2020-06-08 15:54 UTC

Video! 😀

– Alex Schroeder 2020-06-11 18:12 UTC

Add Comment

2020-05-30 XP, Gold, and Emacs

There are those rare occasions where my love for an editor that can be extended while you’re using it – Emacs! – and my love for role-playing games come together.

I use big tables like the following on the status pages of my various campaign wikis:

|= Character    |= Share |=     XP |=   Gold |=      Level |= XP next |= Home / final rest |= Health |= Player |
|[[Vangelis]]        | 1 |    12367|    10033|      thief 5| 20'001|[[Greyheim]] | |Sam |
|[[Maram]]           | ½ |    11793|     5324|   halfling 4| 16’251|[[Greyheim]] | |Sam |
|[[Magdalena]]       | ½ |    13203|     1816| magic-user 4| 20'001|[[Greyheim]] | |Sam |
|[[Delina]]          | ½ |     6781|     4095|      thief 3|  5'001|[[Greyheim]] | |Sam |
|[[Eldakkar]]        | 1 |    48013|     9938| magic-user 5| 40'001|[[Greyheim]] | |Flavio |
|[[Ernst Ormott]]    | ½ |    18158|     2626|    fighter 4|  16250|[[Greyheim]] | |Flavio |
|[[Mia]]             | ½ |     6843|      108|  Assistant 4| 10'001|[[Greyheim]] | |Flavio |
|[[Anouk]]           | 1 |    35001|        0|      dwarf 6| 70'001|[[Stormhold]] | |Ben |
|[[Strahl]]          | ½ |    40001|       95| magic-user 6| 80'001|[[Stormhold]] | |Ben |
|[[Kristina]]        | ½ |    11188|     2740|    fighter 4| 16'250|[[Stormhold]] | |Ben |
|[[John Greene]]     | ½ |    20001|        0| magic-user 5| 40'001|[[Stormhold]] | |Ben |
|[[Dorn Ironfoot]]   | ½ |     5501|        0|      dwarf 3|  8'751|[[Stormhold]] | |Ben |
|[[Yifan]]           | 1 |    34219|    16450|        elf 5| 65’001|[[Deathwatch Keep]] | |Grisha |
|[[Annica]]          | ½ |    18670|     8671|      dwarf 5| 35’001|[[Greyheim]] | |Grisha |
|[[Joana]]           | ½ |     2643|      300|    fighter 2|  4'065|[[Greyheim]] | |Grisha |
|[[Lila-Marie]]      | ½ |       52|     1792|        elf 1|  4'065|[[Greyheim]] | |Grisha |
|[[Sugo]]            | 1 |    19895|     7073|    fighter 5| 32'501|[[Greyheim]] | |Petr |
|[[Slui]]            | ½ |     5264|     1965|   halfling 3|  8,125|[[Greyheim]] | |Petr |
|[[Maxim]]           | ½ |     6033|      243|    fighter 3|  8'125|[[Greyheim]] | |Petr |
|[[Saray]]           | 1 |     1878|     2537| aquamancer 1|  2'501|[[Greyheim]] | |Natalie |
|[[Pringles]]        | 1 |    16468|     7577|    fighter 5| 32'501|[[Greyheim]] | |Petr's wife |
|[[Maximo]]          | 1 |     2042|      885|      thief 2|  2'501|[[Greyheim]] | |Giorgio |
|[[Adrijana]]        |   |     4560|     1743|  geomancer 2|  5'001|killed by bugbears | ☠ |Flavio |
|[[Tugra]]           |   |     5272|     -262|    fighter 2|  4'065|petriefied by a basilisk | ⌛ |Adrian |
|[[Sascha]]          | 1 |    13554|     1704|     cleric 5| 25'001|retired and runs a church | 💜 |Flavio |
|[[Lothar]]          |   |      750|       41|      dwarf 1|  2'187|[[Greyheim]] | 💜 |Chris |
|[[Tiana]]           |   |       45|      118|   halfling 1|  2'035|killed by a giant bat | ☠ |Sam |
|[[Arbogast]]        |   |      260|      682|    fighter 1|  2'035|ambushed by jackalweres | ☠ |Sam |
|[[Marika]]          |   |     1953|     2119| magic-user 2|  5’001|[[Greyheim]] | ⌛ |Sam |
|[[Simed]]           |   |      805|     1699|      dwarf 1|  2'187|[[Greyheim]] | 💜 |Sam |
|[[Neid]]            |   |       58|      694|        elf 1|  4'065|shot by hobgoblins | ☠ |Sam |
|[[Devd]]            |   |      694|      413|    fighter 1|  2'035|shot by hobgoblins | ☠ |Sam |
|[[Pietro]]          |   |       77|       11| pyromancer 1|  2'501|shared space whit a spear  | ☠ |Andre |
|[[Kim]]             |   |     3261|     1835|        elf 1|  4'065|killed by ear seekers | ☠ |Sam |
|[[Tristan]]         |   |        0|        0|   halfling 1|     - |killed by boring beatles | ☠ |Flavio |
|[[Aiza]]            |   |      997|      113|   halfling 1|     - |fell into a concealed pit | ☠ |Luca |
|[[Hiad]]            |   |       17|        1|      dwarf 1|     - |eaten by beatles | ☠ |Miae |
|[[Honey]]           |   |        0|        0|   halfling 1|     - |eaten by kobolds | ☠ |Miae |
|[[Sivan]]           |   |        0|        0|     cleric 1|     - |eaten by kobolds | ☠ |Sam |
|[[Desi]]            |   |     3474|     1908|    fighter 2|  4'065|held under the Freya temple | 🐺 💜 |Flavio |

I used Emacs to distribute gold and experience points because I’m not a big user of spreadsheets. For the longest time, I used a set of functions that created a form within Emacs, made up of widgets.

The code I had turned this into a form like the following:

XP total:   0            
Gold zu XP: 0            
Gold total: 0            
[ ] [[Vangelis]]        Share: [X] 1 [ ] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[Maram]]           Share: [ ] 1 [X] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[Magdalena]]       Share: [ ] 1 [X] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[Delina]]          Share: [ ] 1 [X] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[Eldakkar]]        Share: [X] 1 [ ] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[Ernst Ormott]]    Share: [ ] 1 [X] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[Mia]]             Share: [ ] 1 [X] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[Anouk]]           Share: [X] 1 [ ] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[Strahl]]          Share: [ ] 1 [X] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[Kristina]]        Share: [ ] 1 [X] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[John Greene]]     Share: [ ] 1 [X] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[Dorn Ironfoot]]   Share: [ ] 1 [X] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[Yifan]]           Share: [X] 1 [ ] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[Annica]]          Share: [ ] 1 [X] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[Joana]]           Share: [ ] 1 [X] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[Lila-Marie]]      Share: [ ] 1 [X] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[Sugo]]            Share: [X] 1 [ ] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[Slui]]            Share: [ ] 1 [X] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[Maxim]]           Share: [ ] 1 [X] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[Saray]]           Share: [X] 1 [ ] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[Pringles]]        Share: [X] 1 [ ] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[Maximo]]          Share: [X] 1 [ ] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      
[ ] [[Sascha]]          Share: [X] 1 [ ] ½ [ ] ⅓   Gold spent: 0       Transfer: 0      


You could check those boxes, arrange for money transfers, arrange for gold to be spent (turning it into experience points), you could distribute gold found (distributed according to shares, one share per main player character, half a share for retainers), or experience points gained (based on monsters defeated and distributed equally among characters).

Sadly, there interface was clumsy. Checking the necessary boxes took more time than I was willing to spend.

Later, I tried to write something like a chat interface. I basically wanted a special RPG shell with which to interact. I imagined myself typing parse <url> to read the data from the campaign wiki, filter Flavio Sam Ben to tell the system who was present, distribute 500 gold and distribute 200 xp to distribute gold and experience points, and save to save the result back to the wiki.

I spent a lot of time writing code and did very little distributing of gold and experience points. I was also a bit frustrated. Why was I using rules that required me to use software again? That question remains unanswered.

My latest attempt at writing code involves simply marking numbers using C-=, distribute a certain amount among all the marked numbers using M-C-=, add a certain amount among all the markednumbers using M-C-=, and remembering that C-+ already exists to increment the number at point.

It needs a bunch of convenience functions to quickly mark all the numbers at a particular column for lines matching a particular regular expression, and then we should be good to go!


Add Comment

2019-12-14 Gnus IMAP issues

I’ve started using Gnus again in recent weeks and months. One problem I have is that I enter the INBOX group using C-u RET or issue / o inside the group to see all the mail in my INBOX, read and unread, but all I get are 17 mails. I know some are missing.

When I use the Server Buffer via ^ and enter the INBOX, I get 50 mails. This includes all the missing mails.

I sometimes suspect that it has to do with me reading mails on the phone, too.

Do you understand what’s going on? Many years ago I had decided that the Gnus Agent was a problem and disable it setting gnus-agent to nil. (My entire Gnus config is available online.)

I removed the newsrc files (.newsrc.eld, .newsrc-dribble, their backup files), started Gnus again, and all I seem to have lost was the read marks. As I had all groups “read” that wasn’t a problem, a quick “catch-up” on the groups in questions solved that; then I went into my INBOX and all the mails were there. Let’s see whether it degenerates again.


Comments on 2019-12-14 Gnus IMAP issues

/ w runs the command gnus-summary-pop-limit

– gijs 2019-12-15 08:37 UTC

I don’t think this is a question of limits. When entering a group, read mail is not shown by default. When I then press / w, nothing happens. When I press / o, read mail is shown in the buffer. My problem is that not all read mail is shown in the buffer.

– Alex Schroeder 2019-12-15 10:04 UTC

I find Gnus nnimap is great,it practically runs itself, when imap is used as intended - keep it on the server. There is really no need to download everything. This is great for work email.

The .newsrc* files are not really needed, everything is on the imap server. They just make reading email faster. One can just delete them and start where the left, it will just take longer to sync.

I have a few comments on your gnus config:

  1. For nnimap gnus-secondary-select-methods the group names are formatted as “nnimap+server:Groupname”. The “server” part should be the method label and not the nnimap-address. So for your archive, spam or trash groups, should use for example “nnimap+notifications:Archive”. To my understanding, the “server” string is more of the method label to distinguish from the other methods.
  2. You must have your reasons for setting both the gnus-select-method and the gnus-secondary-select-method “notifications” to the same imap server (imap.migadu.com). This may be a source of confusion to gnus. The issues you are experiencing may come from a bad interaction between the two methods. From your config, it is not clear what distinguishes the two methods. May I suggest keeping only one and see if the issues persist ? I find gnus-select-method to be archaic, as it no longer makes any sense to treat any method as special. Setting gnus-select-method to ’(nnnil nil) and moving all method definition to gnus-secondary-select-methods gives the best experience IMV.

Btw, I’m a big fan of your work. Thank you for all the code contributions, post and of ourse the emacswiki work !! Amazing.

– DEUS MAX 2019-12-15 10:50 UTC

The reason I had done this was that for a while I had two mail accounts on the same server (alex@alexschroeder.ch and notifications@alexschroeder.ch). How do you set that up correctly, without delivering all the mails to a single account?

– Alex Schroeder 2019-12-15 12:07 UTC

No idea why Gnus is so popular! It’s OK for NNTP but not for e-mail. Ditch Gnus and user Wanderlust! 🙂

– zapata 2019-12-15 12:23 UTC

But I’ve been using Gnus for twenty years! I’ve got code in Gnus. I got the mug!

But yeah, perhaps one day I’ll do it.

– Alex Schroeder 2019-12-15 14:40 UTC

Setting up some stuff... starting M-x wl...

condition-case: Wrong type argument: arrayp, nil

This is not a good omen. 😐🔥🔥

M-x toggle-debug-on-error and then:

Debugger entered--Lisp error: (wrong-type-argument arrayp nil)
  signal(wrong-type-argument (arrayp nil))
  (condition-case obj (progn (if check (progn (message "Checking environment...") (wl-check-environment arg) (message "Checking environment...done") (message "Checking type of variables...") (wl-check-variables) (wl-check-variables-2) (message "Checking type of variables...done"))) (let ((inhibit-quit t)) (wl-plugged-init (wl-folder))) (if arg nil (run-hooks 'wl-auto-check-folder-pre-hook) (wl-folder-auto-check) (run-hooks 'wl-auto-check-folder-hook))) (error (if (buffer-live-p demo-buf) (kill-buffer demo-buf)) (signal (car obj) (cdr obj))) (quit))
  (let (demo-buf check) (if wl-init nil (if wl-demo (setq demo-buf (wl-demo))) (setq check t)) (wl-init) (condition-case obj (progn (if check (progn (message "Checking environment...") (wl-check-environment arg) (message "Checking environment...done") (message "Checking type of variables...") (wl-check-variables) (wl-check-variables-2) (message "Checking type of variables...done"))) (let ((inhibit-quit t)) (wl-plugged-init (wl-folder))) (if arg nil (run-hooks 'wl-auto-check-folder-pre-hook) (wl-folder-auto-check) (run-hooks 'wl-auto-check-folder-hook))) (error (if (buffer-live-p demo-buf) (kill-buffer demo-buf)) (signal (car obj) (cdr obj))) (quit)) (if wl-biff-check-folder-list (progn (if arg nil (wl-biff-check-folders)) (wl-biff-start))) (if (buffer-live-p demo-buf) (kill-buffer demo-buf)))

The problem appears to be this, when running edebug on wl-check-environment:

(wl-folder-get-elmo-folder "+draft")

And that’s even though (wl-folder-get-elmo-folder "+queue") returns nil, no error.

That’s because (wl-folder-make-elmo-folder wl-draft-folder) returns nil in wl-draft-get-folder.

I was debugging somewhere in the depths of elmo-make-folder when I decided to give and return to Gnus.

– Alex Schroeder 2019-12-15 19:39 UTC

As DEUX MAX said, you definitely shouldn’t configure the same email account several times.

I’ve switched to setting gnus-select-method to nnnil, and configuring everything in gnus-secondary-select-methods, to avoid confusing myself with the special status of the single account configured in gnus-select-method. I recommend that for everybody.

You can name methods in Gnus, so you can easily have multiple accounts on the same mail server:

(setq gnus-select-method '(nnnil))
(setq gnus-secondary-select-methods
        (nnimap "one" (nnimap-address "your.mailserver.example.org"))
        (nnimap "two" (nnimap-address "your.mailserver.example.org"))

and then in your .authinfo.gpg you’d have something like:

machine one login yourlogin1 password ***** force yes port imaps
machine two login yourlogin2 password ***** force yes port imaps

Or something to that effect.

Your groups will then show up as nnimap+one:blabla, nnimap+two:INBOX etc.

Adam 2019-12-18 19:58 UTC

Thanks! Will try that.

– Alex Schroeder 2019-12-18 21:44 UTC

I agree with Adam. It is best to ditch the gnus-select-method and move everything (configuration wise) in gnus-secondary-select-methods.
Treating an arbitrary method as special (primary) is bad holdover.
So yes, do use the The Empty backend :

(setq gnus-select-method '(nnnil ""))

Alternative configuration, for using two accounts on the same imap server, can be:

(setq gnus-secondary-select-methods
  '((nnimap "one" (nnimap-address "imap.mailserver.org")(nnimap-user "user1")...) 
    (nnimap "two" (nnimap-address "imap.mailserver.org")(nnimap-user "user2")...) 

and the .authinfo.gpg file:

machine imap.mailserver.org login user1 password user1secret ....
machine imap.mailserver.org login user2 password user2secret ....

This way, accounts get selected by the different user-names.
The strings “one” and “two” become just server labels, that can be conveniently chosen to provide for good looking gnus group names (nnimap+serverlabel:Groupname) that display nicely in the Group Buffer.

– DEUS MAX 2019-12-20 01:04 UTC

Thank you both.

– Alex Schroeder 2019-12-20 10:05 UTC

When you’re in the 17-mail inbox, what does C-h v gnus-newsgroup-name say? What does M-: (length gnus-newsgroup-headers) say?

When you’re in the 50-mail inbox, same questions.

– dickmao 2019-12-20 14:28 UTC

Somebody convinced me to simply go ahead and delete the ~/.newsrc* files. As my setup was simple and I didn’t have much marked, it was no problem at all ­– and currently the two look alike again.

I’ll remember to do that, next time this happens though.

– Alex Schroeder 2019-12-20 20:20 UTC

Yes, ~/.newsrc* state more than occasionally gets corrupted when gnus gets confused. Glad you’re back on track.

– dickmao 2019-12-21 16:02 UTC

The problem hast reappeared.

Here are the two last emails in my inbox:

... (16 other mails)
O    2020-02-18 [   7: xxxxxxxxx      ] über amazon data
O    2020-02-19 [   5: xxxxxxxxx      ] BBC - Travel - Japan’s perfectly imperfect garden


(length gnus-newsgroup-headers) → 18 (which is what I see)

When I got to the server buffer, I see the IMAP server:

     {nnimap:migadu} (opened)

When I browse it, it looks just fine:

      89: Archive
       7: Drafts
    1317: INBOX
    9954: Junk
       4: Notes
      75: Sent
    1162: Trash

When I try to enter the INBOX, however (using both RET and C-u RET):

Group nnimap+migadu:INBOX contains no messages
gnus-browse-read-group: Couldn’t enter nnimap+migadu:INBOX

And on the iPhone, the last four messages are:

  • über amazon data
  • Update Februar 2020 – Geheimdienst, E-Voting, E-ID, Julian Assange, Privacy Camp, Jahresbericht, Zmittag
  • BBC - Travel - Japan’s perfectly imperfect garden
  • Re: “Permanent Record”: Ein Hörbuch für Dich!

So, I can see two emails on the phone that Gnus isn’t showing, and this time around the server setup is broken in some way.


Am I going to delete the ~/.newsrc* files again? Probably.

Is this making me distrust Gnus? Definitely.

– Alex Schroeder 2020-02-23 10:45 UTC

Actually, a new development. I entered the group and used Z G to rescan the group, then / o to show the old messages – and now I have more messages in the summary buffer!

– Alex Schroeder 2020-02-24 00:16 CET

Add Comment

2019-08-02 Use of Emacs

Two Years With Emacs as a CEO (and now CTO) is the followup to A CEO's Guide to Emacs. The author talks about life with Emacs.

So many cool quotes in that article!

On using a tool that isn’t designed to do a task (an application) but on using a tool help you do your task. Emacs is a tool, not an app.

Emacs is a portal into the power of the computer itself, and that is a rabbit hole worth descending. Its idioms are paths to discovering and creating your own, and that for me is the definition of creativity. One of the sad things about modern computing is that it is largely made up of black boxes with shiny interfaces that provide momentary gratification rather than real satisfaction. This makes us into consumers rather than creators/makers of technology. I don’t care who you are or what your background is; you can understand your computer, and you can make things with it.

On not using Emacs for shared todo items and calendar stuff:

I gave up on using Org-mode for to dos and the like, as I have to coordinate many meetings and calls every day with dozens of people, and I cannot ask the rest of the world to adapt to my choice of tools, nor do I have the time to transcribe or automate moving things to Org.

On not using Emacs for takin notes during meetings because it’s often better to use a pen (unless the point of the meeting is to write a document).

I also use a plain old pen for note-taking during meetings, as I find laptop/keyboard use in meetings to be rude and limiting to my ability to listen and think.

Ah yes. At work, I usually joke that Emacs is just my IRC client... 🙂


Add Comment

2019-06-21 Gopher Clients for Emacs

“Always two there are...” – Yoda

I’ve been using the Gopher app on my iOS devices for a while, now, as well as VF-1 on the command line. For Emacs, I was using gopher.el. But yesterday, @gcupc mentioned a second Gopher client for Emacs: Elpher. Indeed, there are at least two implementations of everything in Emacs! 😓

The number one thing I’ve thought when I gave Elpher a try was: there’s no browsing history! There’s no way to say “back”, or “next” (if reading a text file in a menu). When I read the History and Caching entry on GitHub, however, it seems that the up command does what I’d think a back command would do.

And something else I’ve noticed: there’s no TLS support. gophers://alexschroeder.ch:7443 can’t be accessed. I’ve added that to gopher.el, I might as well try and add it to Elpher, I guess?

UTF-8 works. 👍


Add Comment

2019-04-07 Using magit and forge

Following @algernon’s suggestion, I’m trying forge for magit.

Install it via M-x package-list-packages.

My setup is this: my origin remote points to my remote git repo. There’s also a cgit running on that server, but what I really care about is the alternative github remote I have installed. I had to set the name of this remote in a git config option via the command line:

git config --add "forge.remote" "github"

I was told to M-x forge-pull when I tried to look at the issues using ' l i. When I did that, it told me that it was going to create a token in ~/.authinfo and if I didn’t want that, I’d have to abort and configure auth-sources. So I did that:

(setq auth-sources '("~/.authinfo.gpg"))

So I tried again. forge-pull said it was going to create a token and save it in ~/.authinfo.gpg and I agreed. Sadly, it didn’t work:

ghub--handle-response-headers: BUG: missing headers
  See https://github.com/magit/ghub/issues/81.
  headers: nil
  status: nil
  buffer: #<buffer  *http api.github.com:443*>
  --- end of buffer-string ---

I wonder why.

I restarted Emacs. Visited my repo. Ran magit-status. Ran forge-pull. And got the error: “transient--layout-member: magit-dispatch is not a transient command”.

I have no idea what this means. Fiddled some more, went through the process again, got the missing headers error again. I’m not happy.

Now I’m following the hints in the Ghub manual about manually creating the personal access token I need. Turns out that the token was created on the site, but the line was missing in my ~/.authinfo.gpg. So no I’m adding it manually.

machine api.github.com login kensanata^forge password *secret*

And I’m still getting the same error.

ghub--handle-response-headers: BUG: missing headers
  See https://github.com/magit/ghub/issues/81.
  headers: nil
  status: nil
  buffer: #<buffer  *http api.github.com:443*>
  --- end of buffer-string ---

Looking at #81 and reading through the entire thread it seems the answer is installing Emacs 27, or using (setq gnutls-log-level 1) but “only because it slows things down slightly,” perhaps.

By now I’m sick and tired of the entire thing. I remember why using special clients written to new APIs is a pain. For the moment, this doesn’t seem to be better than using either the websites directly, or an email based git workflow and keeping track of issues elsewhere.

I’m going to drop this for a while.


Comments on 2019-04-07 Using magit and forge

Fair enough. But some comments.

When I did that, it told me that it was going to create a token in ~/.authinfo and if I didn’t want that, I’d have to abort and configure auth-sources.

Seems reasonable to inform you that the default is not safe. Since I have no control over the default that’s the best I can do.

BUG: missing headers

There is a severe bug in Emacs and once again this is completely beyond my control. This is going to haunt me forever because it will take half a decade for almost everyone to update to the (as of now unreleased) version of Emacs that fixes that bug.

Turns out that the token was created on the site, but the line was missing in my ~/.authinfo.gpg.

The above bug kicked in at a very unfortunate time. There is no way for me to make this change atomic. Telling Github to create a new token succeeded, but then the bug prevented Emacs from receiving the token and storing it locally.

And got the error: “transient--layout-member: magit-dispatch is not a transient command”.

It means you haven’t updated Magit in a long time. The version you have installed is to old to be compatible with Forge. I have now added some safety-nets that should prevent that when installing Forge from Melpa. It will probably take a few hours for them to become active and won’t help if you have already installed Forge. Just make sure to update Ghub, Magit and Forge to the latest snapshots.

By now I’m sick and tired of the entire thing. I remember why using special clients written to new APIs is a pain.

Fair enough. Though I would like to point out that many of these issues are beyond my control.

For the moment, this doesn’t seem to be better than using either the websites directly, or an email based git workflow and keeping track of issues elsewhere.

The setup process was painful but it would be a shame to give up now. You didn’t actually get a change to see whether the current implementation would already be an improvement for you. (Which it might not, many features are still missing.)

Cheers, Jonas

Ps: I wish bug reports came with such a clear description of what the user tried and how things failed.

– Jonas Bernoulli 2019-04-10 11:08 UTC

No worries. I will try again when I get Emacs 27.

– Alex Schroeder 2019-04-10 11:41 UTC

Add Comment

2018-12-16 Importing old Google Plus posts

As Google is planning to sunset Google+ by April 2019, you need to make a backup right now or you’ll forget!

I have written a little tool to help me browse my Google+ archive using Emacs. I posted over 2000 times on Google+, and left even more comments. Browsing speed is essential.

In addition to just browsing, I also want to copy some of these to my blog. They all need some editing before I do that, however: links need to be checked and fixed, tags need to be added, and so on.

Here’s how to get started: get a copy of my Google+ Stream archive from Google Takeout:

  1. select specific data and pick Posts
  2. change the format from HTML to JSON

This is what it should look like:


Download the archive when it’s ready and unpack it.

For Emacs, you need the following:


As you can see, the archive contains my posts and all the comments people left on it.

I’m happy to answer any questions or help you adapt the code to your own platform.

Also, remember that if your target platform is Wordpress or Blogger, you can always use Friends+Me to handle 3000 posts or less, or pay $20...

Anyway, expect to see some old, backdated posts pop up on this wiki as I work through my list.


Add Comment

2018-08-30 Learning to Type

OK, so I want to practice typing using the Workman Keyboard Layout. But how to practice?

Atreus keyboard

Recently, codesections@fosstodon.org had a post about typing lessons for programmers using GNU Typist. I also found that my distro also offers Speedpad, a sort of game. And that reminded me of Typing of the Dead, which inspired The Typing of Emacs, a game I once wrote.

 T h e   T y p i n g   O f   E m a c s . . .
 elt - Wow!
 any - Hit!
 but - Go ahead!
 own - You can do it!
 nil - That's it!
 Done - done? - Desist! - 2 LIVES LEFT!
 such - You can do it!
 sort - Hit!
 made - Amazing!
 used - OK!
 which - yes!
 words - Hit!
 write - Excellent.
 parse - Wow!
 takes - Wow!
 format - Hit!
 Upcase - Updcase? - Nooooo! - 1 LIVES LEFT!
 random - YES!
 giving - gibuing? - Shame on you! - 0 LIVES LEFT!
 You have reached 180 characters per minute in 26 seconds by typing 18 words.

OK, but now I want to start working on the new Workman layout. Let’s see... I need a “ranking” so that I can start with some “easy” keys and make it progressively harder. Let’s take another look at the basic layer.

the basic layer

Here’s the plan:

  1. start with the home row: just words containing ashtgyneoi
  2. add some easy to reach keys, for example the three most easily reachable above the left and the right: adding drwfup
  3. add the three most easily reachable below the left and the right: adding xmcl (ignoring the comma and dot for the moment)
  4. all the letters

OK, so let’s prepare a file! Let’s use -i to ignore case. Use that Shift key!

grep -i '^[ashtgyneoi]*$' < /etc/dictionaries-common/words > workman-1.txt
grep -i '^[ashtgyneoidrwfup]*$' < /etc/dictionaries-common/words > workman-2.txt
grep -i '^[ashtgyneoidrwxmcfupl]*$' < /etc/dictionaries-common/words > workman-3.txt
grep -i '^[a-z]*$' < /etc/dictionaries-common/words > workman-4.txt

And since this is so new, I also need to change something in my setup:

(setq toe-starting-time-per-word 10)

The default is 3s per word and I basically can’t type anything in the time required.

That should give you a quick selection of difficulty levels. Feel free to introduce keys more gradually.

Here’s how to combine two words from the first file:

sort --random-sort workman-one.txt | paste -d ' ' workman-1.txt - > workman-1b.txt

The result:

A gaits
Aegean assigning
Aeneas ah
Ag Se
Agassi ignition
Agatha ginning
Aggie gayest
Agnes hoot
Agni geneses
Aisha ING

Yet another interesting take would be to use the 2000 most common words from the Brown corpus... And so on! :)

Well, back to the workman-1.txt file for me!

T h e   T y p i n g   O f   E m a c s . . .

hie - Wow!
tie - OK!
shy - Amazing!
Noh - You can do it!
GTE - Done!
sags - Wonderful!
goes - OK!
oats - Amazing!
test - You can do it!
heat - Great!
goose - Go ahead!
hoots - That's it!
shoon - Amazing!
gains - Excellent.
tangs - You can do it!
ninths - Hit!
Athena - You can do it!
testis - Hit!
giants - Done!
sanity - Timeout! - Desist! - 2 LIVES LEFT!
hatting - Wonderful!
assigns - Hit!
entente - Timeout! - Nooooo! - 1 LIVES LEFT!
hyaenas - ? - No! - 0 LIVES LEFT!
You have reached 47 characters per minute in 140 seconds by typing 23 words.

Hall Of Fame

  1. Alex Schroeder    45 cpm    157 sec     24 words  2018-08-30 00:43
  2. Alex Schroeder    47 cpm    140 sec     23 words  2018-08-30 14:53
  3. Alex Schroeder    12 cpm     30 sec      2 words  2018-08-30 14:51
  4. Alex Schroeder    13 cpm     26 sec      2 words  2018-08-30 14:50
  5. Alex Schroeder    40 cpm      9 sec      2 words  2018-08-30 00:40


Add Comment



Please make sure you contribute only your own work, or work licensed under the GNU Free Documentation License. Note: in order to facilitate peer review and fight vandalism, we will store your IP number for a number of days. See Privacy Policy for more information. See Info for text formatting rules. You can edit the comment page if you need to fix typos. You can subscribe to new comments by email without leaving a comment.

To save this page you must answer this question:

Just say HELLO

Referrers: Planet Emacslife