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

2017-02-03 Homebrew and Emacs


alex@Megabombus:~$ emacs
dyld: Library not loaded: /usr/local/opt/imagemagick/lib/libMagickWand-6.Q16.3.dylib
  Referenced from: /usr/local/bin/emacs
  Reason: image not found
Abort trap: 6

OK, reinstall…

alex@Megabombus:~$ brew reinstall emacs-mac
==> Reinstalling railwaycat/emacsmacport/emacs-mac --with-xml2 --with-official-icon --with-gnutls --with-imagemagick
==> Downloading https://bitbucket.org/mituharu/emacs-mac/get/emacs-25.1-mac-6.1.tar.gz
Already downloaded: /Users/alex/Library/Caches/Homebrew/emacs-mac-emacs-25.1-z-mac-6.1.tar.gz
==> Downloading https://s3.amazonaws.com/emacs-mac-port/Emacs25.icns
Already downloaded: /Users/alex/Library/Caches/Homebrew/emacs-mac--official-icon-25.icns
==> ./autogen.sh
==> ./configure --enable-locallisppath=/usr/local/share/emacs/site-lisp --infodir=/usr/local/Cellar/emacs-mac/emacs-25.1-z-mac-6.1/shar
==> make
==> Summary
🍺  /usr/local/Cellar/emacs-mac/emacs-25.1-z-mac-6.1: 4,067 files, 109.7M, built in 20 minutes 31 seconds


Add Comment

2016-12-08 Cider Woes

I’m trying to get Cider to work on my laptop running OSX and failing. This makes me unhappy because I managed to do it on a Windows machine with lots of Cygwin so I felt that getting it to work on a Mac should be a breeze.

Basically, what I have set up my little project using lein and can run it from the command line and from eshell, and I use Clojure Mode, but when I run M-x cider-jack-in I see is this in my *Messages* buffer:

Starting nREPL server via /Users/alex/bin/lein update-in :dependencies conj \[org.clojure/tools.nrepl\ \"0.2.12\"\ \:exclusions\ \[org.clojure/clojure\]\] -- update-in :plugins conj \[cider/cider-nrepl\ \"0.15.0-SNAPSHOT\"\] -- repl :headless...
Mark set
nREPL server started on 53929
[nREPL] Establishing direct connection to localhost:53929 ...
error in process filter: nrepl--direct-connect: [nREPL] Direct connection failed
error in process filter: [nREPL] Direct connection failed

But now I have three buffers named *nrepl-server ... with contents such as nREPL server started on port 53872 on host - nrepl://

This reminds me… My Mac keeps deleting my /etc/hosts file which means that localhost is borked:

$ ping localhost
ping: cannot resolve localhost: Unknown host

So I added it back to /etc/hosts. localhost

Then I killed the three nrepl-server buffers and tried C-c M-j again.

And it works. Phew!

Sometimes writing these posts just helps me focus as I’m troubleshooting.


Comments on 2016-12-08 Cider Woes

Your mac deleting /etc/hosts file sounds really bad

– nickf 2016-12-08 22:53 UTC

Yeah. I think it rewrites the file whenever the system updates? So any code that depends on localhost mapping to usually breaks after an update. Gah!

– Alex Schroeder 2016-12-08 22:59 UTC

Hi Alex, that deletion of /etc/hosts sounds vary odd. I use emacs, cider, lein etc almost daily on OSX and have not run itno that issue ever. I do use hombrew for emacs and lein. I am now running macOSSierra, but have been doing clojure et. al. on a Macbook for the past few years and used the last2 or 3 OSX versions.

– Tim X 2016-12-09 08:30 UTC

Strange. I also have OpenVPN installed on the Mac and it puts stuff into the file. Googling for the problem shows that some versions of a Cisco VPN used to do the same. I should just deinstall it and see whether that resolves it.

– AlexSchroeder 2016-12-09 11:47 UTC

Add Comment

2016-12-02 Emacs Avent of Code Day 2

First question of day 2: You start on key 5 on a keypad as shown below. With instructions to go up, down, left or right. Ignore instructions that would take you off the keypad.

1 2 3
4 5 6
7 8 9

The example input provided for the four numbers is shown below. At the end of each line you’ll end up on the key which is part of the answer. In this example the correct answer is 1985.



(let ((pos 5)
      (code nil)
      (instructions '((U L L)
		      (R R D D D)
		      (L U R D L)
		      (U U U U D))))
  (dolist (instruction instructions)
    (dolist (move instruction)
      (case move
	((U) (when (> pos 3) (setq pos (- pos 3))))
	((D) (when (< pos 7) (setq pos (+ pos 3))))
	((L) (when (not (= (mod pos 3) 1)) (setq pos (- pos 1))))
	((R) (when (> (mod pos 3) 0) (setq pos (+ pos 1))))))
    (push pos code))
  (reverse code))

For the second star, I was too lazy to figure out how to compute the next position and decided to implement tables instead:

  2 3 4
5 6 7 8 9
  A B C

Given a direction, I just list all the possible positions and the results. It’s crude, but it works.

(let ((pos 5)
      (code nil)
      (instructions '((U L L)
		      (R R D D D)
		      (L U R D L)
		      (U U U U D))))
(dolist (instruction instructions)
    (dolist (move instruction)
      (setq pos (funcall move pos)))
    (push pos code))
  (reverse code))

(defun U (pos)
  (case pos
    ((3) 1)
    ((6) 2)
    ((7) 3)
    ((8) 4)
    ((A) 6)
    ((B) 7)
    ((C) 8)
    ((D) 'B)
    (t pos)))

(defun D (pos)
  (case pos
    ((1) 3)
    ((2) 6)
    ((3) 7)
    ((4) 8)
    ((6) 'A)
    ((7) 'B)
    ((8) 'C)
    ((B) 'D)
    (t pos)))

(defun L (pos)
  (case pos
    ((6) 5)
    ((3) 2)
    ((7) 6)
    ((B) 'A)
    ((4) 3)
    ((8) 7)
    ((C) 'B)
    ((9) 8)
    (t pos)))

(defun R (pos)
  (case pos
    ((5) 6)
    ((2) 3)
    ((6) 7)
    ((A) 'B)
    ((3) 4)
    ((7) 8)
    ((B) 'C)
    ((8) 9)
    (t pos)))


Add Comment

2016-12-01 Emacs Advent of Code

I looked at Advent of Code and foolishly decided to solve the first riddle. Perhaps we’ll learn something about Elisp coding style? Feel free to leave comments regarding the code.

You must follow instructions: R or L means turn left or right, followed by a number of steps to take. What’s the final distance in steps? Example: “R5, L5, R5, R3 leaves you 12 blocks away.”

(let ((instructions (mapcar (lambda (s)
			      (cons (aref s 0)
				    (string-to-number (substring s 1))))
			    (split-string "R5, L5, R5, R3")))
      (direction 0)
      (x 0)
      (y 0))
  (dolist (instruction instructions)
    (destructuring-bind (turn . steps) instruction
      (setq direction (mod (funcall (if (= turn ?R) '1+ '1-) direction) 4))
      (case direction
	(0 (setq y (+ y steps)))
	(1 (setq x (+ x steps)))
	(2 (setq y (- y steps)))
	(3 (setq x (- x steps))))))
  (+ (abs x) (abs y)))

Sadly, for the second star, my solution fails… The question is now: which location was visited twice? The example provided says “if your instructions are R8, R4, R4, R8, the first location you visit twice is 4 blocks away, due East.” The code works for the example given but fails for the data I was provided with in the test.

(let ((instructions (mapcar (lambda (s)
			      (cons (aref s 0)
				    (string-to-number (substring s 1))))
			    (split-string "R8, R4, R4, R8")))
      (direction 0)
      (x 0)
      (y 0)
      (last-x 0)
      (last-y 0)
      (seen nil)
      (final-x nil)
      (final-y nil))
  (or (catch 'twice
	(dolist (instruction instructions)
	  (destructuring-bind (turn . steps) instruction
	    (setq direction (mod (funcall (if (= turn ?R) '1+ '1-) direction) 4))
	    (case direction
	      (0 (setq y (+ y steps)))
	      (1 (setq x (+ x steps)))
	      (2 (setq y (- y steps)))
	      (3 (setq x (- x steps)))))
	  (dolist (line (cdr seen))	; skip the last element
	    (destructuring-bind ((x1 . y1) (x2 . y2)) line
	      (when (or (and (= x last-x) ; last move was vertical 
			     (= y1 y2)	  ; looking at a horizontal
			     (>= x x1)  (<= x x2)
			     (or (and (<= y y1)  (>= last-y y1))
				 (and (>= y y1)  (<= last-y y1)))
			     (setq final-x x
				   final-y y1))
			(and (= y last-y) ; last move was horizontal
			     (= x1 x2)	  ; looking at a vertical
			     (>= y y1)  (<= y y2)
			     (or (and (<= x x1)  (>= last-x x1))
				 (and (>= x x1)  (<= last-x x1)))
			     (setq final-x x1
				   final-y y)))
		;; (error "Moving from %S to %S crosses the line from %S to %S in %S"
		;; 	   (cons last-x last-y) (cons x y)
		;; 	   (cons x1 y1) (cons x2 y2)
		;; 	   seen)
		(throw 'twice (+ (abs final-x) (abs final-y))))))
	  (push (list (cons last-x last-y) (cons x y)) seen)
	  (setq last-x x
		last-y y)))
      (+ (abs x) (abs y))))

Well, I decided to brute force it and remember every point I moved through because my “crossing lines” solution was obviously off by 3. Perhaps I just reported the wrong result, who knows.

(let ((instructions (mapcar (lambda (s)
			      (cons (aref s 0)
				    (string-to-number (substring s 1))))
			    (split-string "R8, R4, R4, R8")))
      (direction 0)
      (x 0)
      (y 0)
      (last-x 0)
      (last-y 0)
      (seen '((0 . 0))))
  (or (catch 'twice
	(dolist (instruction instructions)
	  (destructuring-bind (turn . steps) instruction
	    (setq direction (mod (funcall (if (= turn ?R) '1+ '1-) direction) 4))
	    (case direction
	      (0 (setq y (+ y steps)))
	      (1 (setq x (+ x steps)))
	      (2 (setq y (- y steps)))
	      (3 (setq x (- x steps)))))
	  (while (not (and (= last-x x) (= last-y y)))
	    (if (not (= last-x x))
		(setq last-x (funcall (if (< last-x x) '1+ '1-) last-x))
	      (setq last-y (funcall (if (< last-y y) '1+ '1-) last-y)))
	    (let ((last (cons last-x last-y)))
	      (if (member last seen)
		  (error "Repetition seen: %S in %S" last seen)
		(push last seen))))))
      (error "No repetitions in %S" seen)))


Add Comment

2016-09-21 OSX Emacs

Same procedure as always, one would think. But somehow, it manages to be different every single time.

This is what I want:

alex@Megabombus:~$ brew install railwaycat/emacsmacport/emacs-mac --with-gnutls --with-imagemagick --with-official-icon --with-xml2
==> Installing emacs-mac from railwaycat/emacsmacport

Homebrew also wanted me to do some other stuff, oh well.

alex@Megabombus:~$ sudo chown root:wheel /usr/local
alex@Megabombus:~$ sudo mv /opt/homebrew-cask/Caskroom /usr/local


Comments on 2016-09-21 OSX Emacs


alex@Megabombus:~$ brew update
Checking out v1.0.6 in /usr/local/Homebrew...
To checkout master in /usr/local/Homebrew run:
  'cd /usr/local/Homebrew && git checkout master
Checking out v1.0.6 in /usr/local/Homebrew/Library/Taps/caskroom/homebrew-cask...
To checkout master in /usr/local/Homebrew/Library/Taps/caskroom/homebrew-cask run:
  'cd /usr/local/Homebrew/Library/Taps/caskroom/homebrew-cask && git checkout master
fatal: Cannot update paths and switch to branch 'v1.0.6' at the same time.

And many repeats. WTF!

Google found an answer on Stack Exchange that seemed similar enough for me to try it:

alex@Megabombus:~$ cd $(brew --repo); git fetch; git reset --hard origin/master; brew update
HEAD is now at faebc64 Merge pull request #1216 from reitermarkus/fix-language-audit
Updated 11 taps (caskroom/cask, homebrew/boneyard, homebrew/core, homebrew/dupes, homebrew/fuse, homebrew/games, homebrew/science, homebrew/services, homebrew/tex, homebrew/versions, homebrew/x11).

Looks good!

Also, I learned that now --enable-mac-app is required…

And so:

alex@Megabombus:~$ brew install railwaycat/emacsmacport/emacs-mac --with-gnutls --with-imagemagick --with-official-icon --with-xml2 --enable-mac-app
Warning: railwaycat/emacsmacport/emacs-mac-emacs-25.1-z-mac-6.0 already installed
alex@Megabombus:~$ brew remove railwaycat/emacsmacport/emacs-mac
Uninstalling /usr/local/Cellar/emacs-mac/emacs-25.1-z-mac-6.0... (4,066 files, 109.9M)
emacs-mac emacs-24.5-z-mac-5.17, emacs-24.5-z-mac-5.18 are still installed.
Remove all versions with `brew uninstall --force emacs-mac`.
alex@Megabombus:~$ brew uninstall --force emacs-mac
Uninstalling emacs-mac... (7,874 files, 225.7M)
alex@Megabombus:~$ brew install railwaycat/emacsmacport/emacs-mac --with-gnutls --with-imagemagick --with-official-icon --with-xml2 --enable-mac-app
==> Installing emacs-mac from railwaycat/emacsmacport
==> Installing dependencies for railwaycat/emacsmacport/emacs-mac: nettle, imagemagick
==> Installing railwaycat/emacsmacport/emacs-mac dependency: nettle
==> Caveats
This is YAMAMOTO Mitsuharu's "Mac port" addition to
GNU Emacs 25. This provides a native GUI support for Mac OS X
10.6 - 10.12. After installing, see README-mac and NEWS-mac
in /usr/local/Cellar/emacs-mac/emacs-25.1-z-mac-6.0 for the port details.

Emacs.app was installed to:

To link the application to default Homebrew App location:
  brew linkapps
  ln -s /usr/local/Cellar/emacs-mac/emacs-25.1-z-mac-6.0/Emacs.app /Applications
Other ways please refer:

For an Emacs.app CLI starter, see:

.app bundles were installed.
Run `brew linkapps emacs-mac` to symlink these to /Applications.
==> Summary
🍺  /usr/local/Cellar/emacs-mac/emacs-25.1-z-mac-6.0: 4,067 files, 109.8M, built in 15 minutes 56 seconds
alex@Megabombus:~$ brew linkapps emacs-mac
Linking: /usr/local/opt/emacs-mac/Emacs.app
Linked 1 app to /Applications

– Alex Schroeder 2016-10-06 19:47 UTC

Add Comment

2016-05-28 nginx as a caching proxy

Remember the fiasco at the end of 2014 and the beginning of 2015, when Emacs Wiki was down as I tried to switch to Fast CGI, and it kept staying down as I tried to use mod_perl, when finally Nic Ferrier stepped in and started paying for new hosting. He used nginx as a caching proxy for Apache, which continued to call the wiki as a simply CGI script.

The comments reveal quite a bit of caching issues, though. The problem was that nginx seemed to ignore that two pages with an identical URL but for different language preferences could be different. This in turn meant that a German visitor to a page not in the cache would put the page in the cache but with German menus at the bottom, for example (“Diese Seite bearbeiten” instead of “Edit this page”). And if the next visitor to the same page didn’t understand German, this was annoying.

I thought the answer was that Apache should send the “Vary” header telling the cache that accept-language should be part of the cache key. See this discussion of the Vary header, for example: Understanding the HTTP Vary Header and Caching Proxies. But it just didn’t work.

Recently, I suddenly realized that perhaps nginx doesn’t care about the Vary header Apache is sending. I learned about the proxy_header_key setting in the nginx caching guide. As you can see, the default is inadequate! $scheme$proxy_host$request_uri is not what I’m expecting. I needed to add http_accept_language to that key:

# proxy cache key is $scheme$proxy_host$request_uri by default
proxy_cache_key $scheme$proxy_host$request_uri$http_accept_language;

I get the feeling that things are working, right now! If so, it only took 17Β½ month to find the solution. I’m writing it down in case anybody else stumbles over this problem (and in case I need to remember in the future).

Perhaps the problem is also related to how I compute Etags for my pages: the wiki doesn’t take accept-language into account when computing Etags. Now that I think about it, perhaps that would also have helped solve the problem?


Add Comment

2016-05-18 Renaming Files

I had a bunch of files named like this, from various albums.

Cure - [1984] The top - 01 - Shake dog shake.mp3
Cure - [1984] The top - 02 - Bird mad girl.mp3
Cure - [1984] The top - 03 - Wailing wall.mp3

I wanted to move them into subdirectories, one for each album.

(dolist (file (directory-files "c:/Users/asc/Music/The Cure" t "\\.mp3$"))
  (let* ((name (file-name-nondirectory file))
	 (data (split-string name " - "))
	 (album (nth 1 data)))
    (unless (file-directory-p (concat "c:/Users/asc/Music/The Cure/" album))
      (make-directory (concat "c:/Users/asc/Music/The Cure/" album)))
    (rename-file file (concat "c:/Users/asc/Music/The Cure/" album "/" name))))

Tags: RSS

Comments on 2016-05-18 Renaming Files

If your files have ID3 tags, you can do some thing like this, too:

exiftool '-filename<${Artist;} - ${Year} - ${Album}/${Track;} ${Artist;} - ${Title;}.%e' **.mp3

– Sam 2016-05-18 11:54 UTC

Nice! And using exiftool! :)

– Alex Schroeder 2016-05-18 13:17 UTC

A graphic alternative is exfalso (from quodlibet music player).

– Anonymous 2016-05-19 09:58 UTC

Here is a way to do it combining dired, wdired and multiple-cursors. This approach requires the existence of the album directory which might not make it particularly useful for your exact use case. Still, I find it cool and so should you :-).

Damien Cassou 2016-05-19 18:10 UTC

Very cool. And a nice video on top. Thumbs up!

– Alex Schroeder 2016-05-21 06:33 UTC

Add Comment

2016-05-15 Gmail, Gnus, GPG Guide Update

I updated my Gmail, Gnus, GPG Guide. It now includes all the stuff about setting up the GPG Agent.

The GPG Agent is a service that will remember your passphrase for a short while. If you don’t use it, Gnus will ask you for your passphrase for every backend it uses (because it needs to log in) and for every encrypted mail you read and for every encrypted mail you send. You’ll be typing your passphrase a lot. You want to use it.

Please let me know if you tried to follow the instructions and it didn’t work. I’d like to make the instructions very easy to follow and troubleshoot. So if you missed something and ran into errors, I’d still like to know so that I can start adding typical problems people might have and how to resolve them.

And finally, feel free to test this system by sending me encrypted email! See Contact for more.


Add Comment

2016-04-11 Atreus, Windows, and Emacs

So, I want to define an interesting layout for my Atreus keyboard. On OSX, I used Ukulele to do it. On Windows, I’m using Microsoft Keyboard Layout Creator 1.4.

+---+---+---+---+---+          +---+---+---+---+---+
|Q  |W <|E >|R (|T )|          |Z {|U }|I [|O ]|P €|
|q 6|w 7|e 8|r 9|t 0|          |z 1|u 2|i 3|o 4|p 5|
+---+---+---+---+---+          +---+---+---+---+---+
|A  |S  |D  |F  |G $|          |H ^|J &|K  |L Γ—|: ||
|a  |s  |d  |f  |g @|          |h =|j +|k -|l *|. …|
+---+---+---+---+---+          +---+---+---+---+---+
|Y  |X  |C  |V  |B %|          |N ~|M ο½£|_ β€”|Β΄ ’|` ”|
|y  |x  |c  |v  |b #|          |n Β¨|m ο½’|- –|' β€˜|" β€œ|
+---+---+---+---+---+---+  +---+---+---+---+---+---+
|   |   |   |   |DEL|   |  |   |   |   |; Β»|? \|   |
+---+---+---+---+---+---+  +---+---+---+---+---+---+

When I switch to my new layout, I still have some problems with it:

  • I was able to define my extra stuff using AltGr, which is the equivalent of Alt+Ctrl at the same time, which means that under Windows, I need to press both of them to access @ on g, for example. Is there a way to make this work for both Mac and Windows? Change the Alt key to Right Alt and it’ll work?
  • When using Emacs, I get A-C-g is undefined. Other programs, like Firefox, will correctly interpret A-C-g as AltGr + g and give me the @. What can I do to fix this?
  • When using Emacs, I want to use the windows key as meta. On my keyboard, that’s SUP (Super). But in this case, I get some Windows action. So I start experimenting.
  (setq w32-lwindow-modifier 'meta ; windows is meta
	w32-pass-lwindow-to-system nil
	w32-rwindow-modifier 'meta ; windows is meta
	w32-pass-rwindow-to-system nil
	w32-recognize-altgr t
	w32-pass-alt-to-system t   ; alt is alt
	w32-alt-is-meta nil)
   ;; w32-phantom-key-code??

Perhaps it would be easier if I changed that key to Meta using the keyboard’s firmware and it would work correctly on both OSX and Windows?

And I’m still not sure how to change bindings for simple keys using the Alt key. Perhaps I need a different utility? A good Microsoft Keyboard Layout Creator alternative…

I guess the alternative would be to use Fn together with these extra keys. But then I can’t bind them to something interesting like β€œ…” because in order to that, I would need access to these keys on Microsoft Keyboard Layout Creator, which I do not.


Comments on 2016-04-11 Atreus, Windows, and Emacs

Well, right now I am back at the US standard layout. Perhaps I can do everything else using dead keys? Might be simpler than all this extra fiddling. I’m hating everything about it already. I’m spending too much time worrying about programming the keyboard but as it stands, I won’t ever get a system, where I can just carry my keyboard to another desk and start typing. It just requires too many features by the operating system and the various solutions are incompatible anyway.

Current mood: frustrated.

– Alex Schroeder 2016-04-11 19:40 UTC

I want a keyboard with Super and Hyper that works on both Windows and OS X. I still don’t have a precise answer but this seems good ot know: https://ergodox-ez.com/pages/our-firmware They define a “Hyper” and a “Meh” key. I pre(re)invented that approach using AutoHotKey and duplicated bindings, and decided it was a poor use of my time. If it is built into your keyboard, however, might be nice. I still want to answer “Why can’t we have a GUI key that is separate from the SUPER key?”. Seems possible, and I would like it a lot because we do need a GUI key, too.

Grant Rettke 2016-04-11 21:00 UTC

Oh! Right. Whenever I have to use another computer I usually connect to it with my laptop using, er, Synergy. Synergy is great, but… it is an interesting case of a GPL-ed free software getting crippled so that they can sell it…

So I guess that it is just waiting for a fork to appear. Meanwhile you can get a bit older version from here: http://synergy-project.org/download/free/ (or compile it yourself, though in case of crippled software it is usually not as simple. But who knows). Same version is debian repos (so I haven’t really noticed).

It’s kinda interesting that instead of starting some crowd funding they decided to turn the software into something that I don’t really want to recommend to anybody just because of their β€œmonetizationβ€œ shit. Awful.

But! It allows me to use my laptop (and therefore my own configuration) for any computer I connect with. So, perhaps that’s an option?

– AlexDaniel 2016-04-11 21:09 UTC

Grant, I saw you blog post just now and I’m reminded of what I discovered when I looked at the keycodes available in the firmware:

/* Modifiers */
KC_LCTRL            KC_LCTRL        E0 Keyboard LeftControl
KC_LSHIFT           KC_LSFT         E1 Keyboard LeftShift
KC_LALT                             E2 Keyboard LeftAlt
KC_LGUI                             E3 Keyboard Left GUI(Windows/Apple/Meta key)
KC_RCTRL            KC_RCTL         E4 Keyboard RightControl
KC_RSHIFT           KC_RSFT         E5 Keyboard RightShift
KC_RALT                             E6 Keyboard RightAlt
KC_RGUI                             E7 Keyboard Right GUI(Windows/Apple/Meta key)

No KC_RHYPER or KC_LHYPER! No KC_RSUPER or KC_LSUPER! The comment points to another document: “Keycodes are defined in ‘common/keycode.h’. Range of 00-A4 and E0-E7 are identical with HID Usage.” In the header file mentioned, it says: “Virtual keycodes are defined out of above range to support special actions. Keycodes based on HID Usage Keyboard/Keypad Page(0x07) plus special codes.” As the URLs are no longer pointing anywhere, here’s what I think this refers to the USB HID Usage Tables on page 53ff.

I think this means that there cannot be a USB keyboard with a Hyper key. I think what you therefore need to do is make a key that sends multiple modifiers at the same time, ie. mapping Caps Lock to Shift+Ctrl+Option+Command or something like that. The solution for a Mac involves Karabiner and Seil for OSX. Like the ideas I had myself, this setup is hardly portable to other computers, unfortunately. Apparently, you can do something similar using AutoHotKey.

Xah Lee has collected some info the topic: Emacs: How to Define Super Hyper Keys, AutoHotkey Tutorial.

– Alex Schroeder 2016-04-12 07:31 UTC

How is it going?

– AlexDaniel 2016-04-24 06:23 UTC

I’ve been using the Atreus with my la-top at home, using the US standard layout. I use the Latin Prefix input method to write German. This also meant that I no longer require Alt/Option as AltGr and so I use Alt as Hyper again, but have no keys bound using Hyper. Boooo.

– Alex Schroeder 2016-04-24 16:37 UTC

Alex can you show your keyboard layout (like you did up above) showing your current mappings?

I’m confused by your post: did you get what you wanted when you re-configured left and right GUI?

I guessed that you would place LEFT_ALT and where you wanted it to be META, and RIGHT_ALT wherever you wanted it to be ALT. It would look confusing because the keycaps would have ALT all over, but for Emacs, it would be exactly what you want. Right? I think that I might have understood something wrong here.

Grant Rettke 2016-05-14 19:00 UTC

The end result of all the above is that I am using the default firmware for the keyboard. This means that I’m short one modifier on the Mac: I need the command key to run OSX commands; I need Alt to enter German characters; there’s no key for Meta. Under OSX, the usual solution is to use the Command key as Meta, of possible. So, in order to get that, I would have to swap Alt and Super on the Atreus firmware, assuming I wanted to use my right thumb for Meta. I guess I do?

But the main thing that I wanted to talk about when I replied to your message above was this: All USB keyboards will be limited by the USB standard for keyboards. You can find the necessary information in USB HID Usage Tables on page 53ff. There, on page 59, you’ll note that there is no way a USB keyboard will be able to send the Hyper modifier: There is only Control, Shift, Alt, and “GUI” (Super) for left and right. In order to get Hyper in addition to those present, you’ll have to map your key to something like F13 in the firmware and then you’ll have tell your operating system that F13 should act as Hyper. I think I could figure this out for a GNU/Linux environment, but I’m unwilling to spend the time necessary to figure it out for OSX and Windows.

And so I determined that the two easiest options right now are the following:

  1. don’t use the Atreus keyboard
  2. if I use the Atreus keyboard, use the default firmware, switch to a US layout in OSX, and use something like the following for Emacs:
(defun atreus-layout ()
  "If using the Atreus on a Mac, we want the Alt key to be Meta."
  (setq mac-option-modifier 'meta)
  (setq default-input-method 'german-prefix)
  (set-input-method 'german-prefix))

But, I don’t like any of it and I’m unhappy with the current state of affairs. The sad part is that I don’t see an easy way forward. Maybe during my summer break.

– Alex Schroeder 2016-05-15 00:19 UTC

Gotcha. I am sorry that it isn’t going as planned. Here is what I tried https://www.wisdomandwonder.com/article/10146/every-emacser-can-use-hyper-on-every-usb-hid-keyboard . This is how I came up with “using hyper in Emacs” given that there are only 8 modifiers (left or right, shift control alt gui) in the USB HID spec and there is no xmodmap option for Windows. It seemed happy on my Mac and Windows box; I tried the following on both boxes. The important thing for me was that Windows and OS X had their important modifiers: ALT and GUI so I could switch window focus and use OS actions like inserting special characters and opening the Run dialog in Windows. I read your post like it would work the same way for the Altreus. The way I read your post I figured that you MIGHT modify your default keyboard https://atreus.technomancy.us/ by changing the default layout (by names there): super as RIGHT_GUI (aka option), ctrl as RIGHT_CONTROL, alt as RIGHT_ALT (aka command), and then moving - ‘ , to the Fn layer, so you can redefine - as LEFT_CONTROL (Meta), ‘ as LEFT_ALT (Super), and , as LEFT_GUI (Hyper) only for Emacs using the mac-right-*modifier and mac-left*-modifier settings. I didn’t want the CONTROL-ALT-GUI-SHIFT style hyper key since I only want these modifiers in Emacs. I tried that approach and didn’t like it only because I only wanted the modifiers inside of Emacs. If things work like I am seeing them work on the Mac, then this will work on your Altreus. Otherwise I am wrong and need to revise my post ASAP.

Grant Rettke 2016-05-15 09:31 UTC

Hah, excellent! I’ll give this a try. :)

– Alex Schroeder 2016-05-15 10:44 UTC

Alex, how did it go?

Grant Rettke 2016-07-15 10:58 UTC

My summer break just started at the beginning of the month and I still haven’t used my Atreus keyboard for anything. :(

– Alex Schroeder 2016-07-15 20:19 UTC

First, have a great break. Do what you enjoy!

If you happen to enjoy configuring your Emacs keyboard then know that we are all dying to hear the results!

Grant Rettke 2016-07-18 18:31 UTC

Good afternoon Alex. Have you tried the keyboard with Emacs yet?

Grant Rettke 2016-12-03 21:13 UTC

Right now I’m trying to get used to the US keyboard layout again. This requires some changes in my motor patterns. The Atreus keyboard with standard config is here, next to the laptop, but I rarely use it.

– Alex Schroeder 2016-12-03 23:35 UTC

Add Comment

2016-03-17 GPG Agent and Emacs

I updated Gmail, Gnus and GPG on a Mac, on Emacs Wiki, with the information I discovered below.

In my Gmail Gnus GPG Guide I don’t mention gpg-agent because I never managed to set it up correctly for OSX.

Well, perhaps things will change. I followed the instructions on this blog post, I think, and it works on the command line. I can encrypt a text to myself, when I decrypt it, I’m asked for my passphrase, and when I decrypt it again, I’m not asked for my passphrase because the agent handles it.

This requires my gpg-agent.conf file to contain the line pinentry-program /usr/local/bin/pinentry which is the equivalent to pinentry-curses.

It used to say pinentry-program /usr/local/bin/pinentry-mac, however!

If I use pinentry-mac:

alex@Megabombus:~$ gpg -d test.txt.gpg 

You need a passphrase to unlock the secret key for
user: "Alex Schroeder <kensanata@keybase.io>"
8192-bit RSA key, ID 4529A45C, created 2015-03-01 (main key ID ACECFEAE)

gpg: problem with the agent: No pinentry
gpg: encrypted with 8192-bit RSA key, ID 4529A45C, created 2015-03-01
      "Alex Schroeder <kensanata@keybase.io>"
gpg: public key decryption failed: Operation cancelled
gpg: decryption failed: No secret key

If I use pinentry-curses:

alex@Megabombus:~$ echo RELOADAGENT | gpg-connect-agent 
alex@Megabombus:~$ gpg -d test.txt.gpg 
   β”‚ Please enter the passphrase to unlock the secret key for the OpenPGP  β”‚
   β”‚ certificate:                                                          β”‚
   β”‚ "Alex Schroeder <kensanata@keybase.io>"                               β”‚
   β”‚ 8192-bit RSA key, ID 4529A45C,                                        β”‚
   β”‚ created 2015-03-01 (main key ID ACECFEAE).                            β”‚
   β”‚                                                                       β”‚
   β”‚                                                                       β”‚
   β”‚ Passphrase __________________________________________________________ β”‚
   β”‚                                                                       β”‚
   β”‚          <OK>                                         <Cancel>        β”‚

Within Emacs

Without the agent running, and with pinentry-mac, it would work from within Emacs (which is what I want to get working). When the agent is running, no matter what the pinentry-program line says, it won’t work.

This is what the *Messages* buffer says:

Decrypting /Users/alex/test.txt.gpg...done
epa-file--find-file-not-found-function: Opening input file: Decryption failed, 

I’m guessing this is a pinentry problem. Not exactly the same string, though. So… Any ideas? What’s wrong? Should I be setting GPG_TTY? The problem appears to be that if I don’t use gpg-agent, Emacs using gpg knows how to call pinentry-mac. If I do use the gpg-agent, then the gpg-agent tries to call pinentry-mac and fails.

Currently the environment for my Emacs session has the following, as determined by running printenv in *eshell*:

GPG_TTY=not a tty

That looks wrong… I’m surprised that GPG_TTY is set in the first place. I’m setting it in my .bashrc file! So starting Emacs uses a shell? I don’t know how Emacs does that.

alex@Megabombus:~$ ps -fx|grep emacs
  502 42011     1   0  7:34am ??         0:02.88 /usr/local/Cellar/emacs-mac/emacs-24.5-z-mac-5.15/Emacs.app/Contents/MacOS/Emacs

My Config

In ~/Library/LaunchAgents/org.gnupg.gpg-agent.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" 
<plist version="1.0">

In ~/bin/startup-gpg-agent.sh:

# ${HOME}/.gpg-agent-info is the default filename
if test -f $HOME/.gpg-agent-info && \
	kill -0 `cut -d: -f 2 $HOME/.gpg-agent-info` 2>/dev/null; then
    GPG_AGENT_INFO=`cat $HOME/.gpg-agent-info`
    export GPG_AGENT_INFO
    eval `/usr/local/bin/gpg-agent --daemon --write-env-file`

In ~/.bashrc, which is also sourced from ~/.bash_profile:

if [ -f "${HOME}/.gpg-agent-info" ]; then
    . "${HOME}/.gpg-agent-info"
    export GPG_AGENT_INFO
    export SSH_AUTH_SOCK
export GPG_TTY

In ~/.gnupg/gnu-agent.conf:

pinentry-program /usr/local/bin/pinentry-mac


OK, this is weird.

In a terminal, it works, if I provide --pinentry-program=/usr/local/bin/pinentry-mac as a startup parameter to gpg-agent.

In Emacs, it works, if I use pinentry-program /usr/local/bin/pinentry-mac in my gpg-agent.conf file.

One would think that the two affect the same thing, but not so. I have no idea why that is so. I’ll have to test this.

Log out and log back in. Nope, nothing works. So, at least I know that there is a way to fix this, even if I don’t know what it is!

gpg: problem with the agent: No pinentry

So here’s how I managed to “fix” it again, in a terminal:

  1. use ps aux | grep gpg to determine the process id of gpg-agent
  2. use kill to kill it
  3. run bin/start-gpg-agent.sh again
  4. run source ~/.gpg-agent-info to set the environment variables again
  5. try gpg -d test.txt.gpg to decrypt my test file – and the GUI pinentry opens!

So. What changed? I have no idea.

Within Emacs, I used setenv to set the GPG_AGENT_INFO to the new value, and it worked: I could open my test file, got asked for my passphrase, killed the buffer, reopened it, and was no longer asked for a passphrase.

So now I’m going to revert the addition of --pinentry-program to the start-gpg-agent.sh script, and see whether simply killing and restarting it from a terminal also “fixes” it. And then we’ll start worrying about the difference between all this stuff.

OK, so restarting this Mac apparently “fixed” all the issues I was having.


Comments on 2016-03-17 GPG Agent and Emacs

I recently stumbled over this somewhere: https://github.com/ecraven/pinentry-emacs

Works great for me (especilly when ssh’ing with X-forwarding) - might be worth trying as well.

Adam 2016-03-18 20:08 UTC

Haha, “This is probably totally insecure, and your passphrase may be leaked! Use at your own risk!” Also, what happens when you’re in a terminal and use gpg – does it start Emacs, or the Emacs Client, and thus you need to be running Emacs somewhere?

– Alex Schroeder 2016-03-18 21:32 UTC

There is also an ELPA package called “pinentry”; as the note in the package description says, it works “with GnuPG (2.1.5+) and Pinentry (not yet released, possibly 0.9.5+)”. It works here.

– Sam 2016-03-19 10:21 UTC

Is that the same pinentry-emacs as https://bugs.gnupg.org/gnupg/issue2034 ? I see a pinentry-emacs is installed by pinentry 0.9.7 on my Arch box.

I have the same question about what happens when if using that when outside emacs (would prefer having both possibilities).

– Kevin Unhammer 2016-04-25 07:28 UTC

pinentry.el works for me :) http://unix.stackexchange.com/questions/55638/can-emacs-use-gpg-agent-in-a-terminal-at-all/278875#278875

– Kevin Unhammer 2016-04-25 08:04 UTC

I could not get passphrase entry to work, so I installed MacGPG2 from https://gpgtools.org/ and now I have a graphical prompt on Mac OS X.

– Anonymous 2016-10-25 02:05 UTC

Here are gotchas that can help others (already included in Alex’s instructions)

  1. Uncomment use-agent in ~/.gnupg/gpg.conf
  2. Add enable-ssh-support to ~/.gnupg/gpg-agent.conf
  3. Change your start-script for gpg-agent to gpg-agent --daemon --write-env-file [1] (this will create a ~/.gpg-agent-info file)
  4. Load this file in your emacs init to setenv GPG_AGENT_INFO [2]

– Anonymous 2016-12-30 09:37 UTC

Add Comment



Please make sure you contribute only your own work, or work licensed under the GNU Free Documentation License. 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:

Please say HELLO.