When upgrading to Emacs 27 there were quite a few weird things I had to address.
My Emacs is installed via Gentoo Portage. The USE flags I have set (to enable/disable features at build time) essentially configure my Emacs to be like Lucid Emacs builds. Here’s the USE flags:
Xaw3d acl alsa athena cairo dbus dynamic-loading gif gmp gui
imagemagick inotify jpeg lcms libxml2 png source ssl svg threads
tiff toolkit-scroll-bars xft xpm zlib -aqua -games -gconf -gfile
-gpm -gsettings -gtk -gzip-el -harfbuzz -json -kerberos -livecd
-m17n-lib -mailutils -motif -selinux -sound -systemd -wide-int
-xwidgets
Make note that cairo support is enabled. This manifests one of the gotchas.
§Bitmap font support has been removed
In my ~/.Xdefaults
I have the following line:
*font: -*-terminus-bold-*-*-*-*-320-*-*-*-*-*-*
Unfortunately, this causes my Emacs to exit with code 255 after printing the following error:
Font ‘-*-terminus-bold-*-*-*-*-320-*-*-*-*-*-*’ is not defined
Looking in the NEWS file, there is a mention of bitmap support has been removed due to cairo building with pango now.
It turns out setting a catchall Xresources setting to configure font for all
old-style applications can cause problems with Emacs which uses Emacs.font
resource to configure a font. Insofar the other X applications appear to use
*font*
only for old-style bitmap fonts.
In order to keep the *font
setting, override Emacs.font
:
Emacs.font: Mono-12
Now Emacs 27 launches on my workstation.
§Weirdness related to slotted Emacs on Gentoo
Quick background. On my workstation I have Gentoo with OpenRC. To set up
Emacs Daemon, install app-emacs/emacs-daemon
, then create a symbolic link to
“instantiate the service” (i.e. cd /etc/init.d && ln -s emacs.winston emacs
). Then simply run rc-service emacs.winston start
(don’t forget to
rc-update add emacs.winston default
).
Anyway, I’m not sure went on here, but /etc/init.d/emacs.winston start
consistently launched Emacs 26. I did eselect emacs set emacs-27
to
configure the emacs
and emacsclient
programs in my path for Emacs 27. No
luck. I also set EMACS
in /etc/conf.d/emacs.winston
, but that did not work
either. No clue what went on here, but the solution was simple - don’t deal
with the problem - emerge -avc emacs:26
.
§emacsclient: can’t find socket
Now Emacs Daemon for Emacs 27 successfully launched, this caused a new problem
when running emacsclient -c
to create a new frame.
emacsclient: can't find socket; have you started the server?
emacsclient: To start the server in Emacs, type "M-x server-start".
emacsclient: No socket or alternate editor. Please use:
--socket-name
--server-file (or environment variable EMACS_SERVER_FILE)
--alternate-editor (or environment variable ALTERNATE_EDITOR)
After a quick search on the Gentoo bug tracker, this bug looked appropriate: #794649: app-emacs/emacs-daemon fails to set the socket location emacsclient 27 expects by default.
This bug references upstream Emacs bugreport: #33847: 27.0.50; emacsclient does not find server socket.
The TL;DR on Gentoo OpenRC does not have XDG_RUNTIME_DIR
set when the service
is started via rc-service emacs.winston start
. Emacs Daemon then proceeds to
create the socket file under /tmp
. Once I log in to my desktop, elogind
sets XDG_RUNTIME_DIR
and emacsclient
looks there, does not find a socket
file, then gives up. In the bugreport there was a possible solution identified
to do just that - search for the old socket file in /tmp
.
There might be a patch floating around (check Archlinux, Debian, etc), but I
wanted to address this upstream issue without a patch if possible. It’s just
less work and portable to other systems that don’t patch this surprising
behavior. The solution was to create file /etc/profile.d/emacs-daemon.sh
with the following contents:
EMACS_SOCKET_NAME="/tmp/emacs$(id -u)/server"
export EMACS_SOCKET_NAME
Log out and log back in to load the new profile.d
environment in a new
session. emacsclient -c
should now work because it will look for the socket
file in /tmp
.
§Related plug - .emacs.d
bootstrap is now automatic
There was in issue with my Emacs configuration that prevents use-package
from
being installed on first startup. This appears to be caused by
package-refresh-contents
never being called and (package-install 'use-package)
fails to find the package to install.
It would be pretty slow to always execute (package-refresh-contents)
on every
startup, adding tens of seconds to startup time. The workaround is to add a
first-boot functionality:
(defconst winny/initialized-cookie-path
(concat user-emacs-directory "/.w-firstboot-initialized"))
(unless (file-exists-p winny/initialized-cookie-path)
;; Run this body only on first startup.
(message "Detected first boot. Doing initialization steps...")
(package-refresh-contents)
(with-temp-buffer
(write-file winny/initialized-cookie-path))
(message "First boot-only initialization complete."))
On first startup the file ~/.emacs.d/.w-firstboot-initialized
will not exist.
This allows the unless
form’s body to execute. Besides writing messages to
the *Messages*
buffer and running the critical section
((package-refresh-contents)
), the with-temp-buffer
expression writes out an
empty file to ~/.emacs.d/.w-firstboot-initialized
.
Now a git clone --recursive git@github.com:winny-/emacs.d.git .emacs.d && emacs
works without special user intervention. One downside of my
configuration.org
setup with use-package
is the slow initialization. It
takes at least a couple minutes to install all the packages during first
startup. Maybe one day my Emacs startup be fast and instantaneous from git clone
…