Motivation: Why doesn’t Emacs
respond to C-.
, C-;
and some other keys?
When you are running Emacs
occasionally you will notice that Emacs
does not respond to some keys. This is because the Desktop
enviornment-—if you are a GNOME
user, the GNOME Desktop
—steals those keys before it even reaches Emacs
.
For example, ever since the embark
package started recommending C-.
key binding for embark-act
, there have been reports of Emacs
users binding the C-.
key, only to find that it doesn’t work on GNOME Desktop
.
If you are one such user, who has his C-.
, C-;
and possibly other keys snatched away from your Emacs
, read on …
Where does one find keyboard shortcuts used by the GNOME Desktop
?
GNOME Control Center
- You can find the keyboard shortcuts used by the
GNOME Desktop
usinggnome-control-center
. The keybindings used by theDesktop
are listed underKeyboard Shortcuts
.gnome-control-center
Dconf Editor
- You can find keyboard shortcuts used by various applications using the
dconf-editor
; just search forkey
in the Search box.dconf-editor
To an experienced Emacs
user, both of these options are as good as looking for a needle in the haystack. What these GUI
tools report is piecemeal and you are left with a vague sense of unease.
gsettings
- You can find the keyboard shortcuts using the
gsettings
shell command. For example, if the stolen key has aControl
in there, you might try the following.~$ gsettings list-recursively | grep -i 'Control' org.freedesktop.ibus.general.hotkey trigger ['Control+space', 'Zenkaku_Hankaku', 'Alt+Kanji', 'Alt+grave', 'Hangul', 'Alt+Release+Alt_R'] org.freedesktop.ibus.panel.emoji hotkey ['<Control>period', '<Control>semicolon'] org.freedesktop.ibus.panel.emoji unicode-hotkey ['<Control><Shift>u'] org.gnome.Terminal.Legacy.Keybindings close-tab '<Control><Shift>w' org.gnome.Terminal.Legacy.Keybindings close-window '<Control><Shift>q' org.gnome.Terminal.Legacy.Keybindings copy '<Control><Shift>c' ...
Is there a better way to hunt for the stolen keys which suits the temperament and outlook of an Emacs user?
As you all know, an Emacs
user is in a class of his own.
He doesn’t work with the best tools for a job at hand; instead he starts with a strongly-held belief-—often a mistaken belief-—that Emacs
is the best tool for the job, whatever the job may be; After exploring existing solutions that could be used within Emacs
, if he discovers that there is no such tool, he goes about creating one such tool.
Given what we know about a typical Emacs
user, there indeed is a solution to for “stolen keys” problem; and it involves use of the gsettings.el — GSettings (Gnome) helpers.1
- Copy the following
Emacs Lisp
snippet to your*scratch*
buffer, and doM-x eval-buffer
.(require 'dash) (require 'rx) (require 'gsettings) (with-current-buffer (generate-new-buffer "*Gsettings*") (pop-to-buffer (current-buffer)) (org-mode) (let ((case-fold-search t)) (save-excursion (->> "list-recursively" gsettings--run gsettings--split-lines (--map (cond ((string-match (rx-to-string '(and (group (one-or-more (not " "))) (one-or-more " ") (group (one-or-more (not " "))) (one-or-more " ") (group (one-or-more any)))) it) (list (match-string 1 it) (match-string 2 it) (match-string 3 it))) (t (user-error "This shouldn't happen")))) (--select (and (let ((parsed (gvariant-parse (nth 2 it)))) (not (and (consp parsed) (eq (car parsed) 'parsec-error)))) (or (string-match-p (rx-to-string '(and "<" (one-or-more any) ">")) (nth 2 it)) (string-match-p (rx-to-string '(and "Keybindings")) (nth 0 it))))) (--map (let* ((bindings (gvariant-parse (nth 2 it)))) (cond ((vectorp bindings) (let ((prefix it)) (--map (append (list it) (butlast prefix)) bindings))) (t (list (append (list bindings) (butlast it))))))) (-flatten-n 1) (--map (cons (format "%s" (car it)) (cdr it))) (--tree-map (format "%s" it)) (--map (format "| %s |\n" (mapconcat #'identity it " | "))) (apply #'insert)))) (org-table-align) (sort-lines nil (point-min) (point-max)) (save-excursion (insert (format "|%s|%s|%s|\n" "Key Binding" "Schema" "Key")) (insert (format "|-\n"))) (org-table-align))
- You will be presented with the following
Org
buffer, …| Key Binding | Schema | Key | |-------------+----------------------------------------------+-----------------------| | | org.gnome.settings-daemon.plugins.media-keys | help | | 30 | org.gnome.gnome-flashback.keybindings | max-screencast-length | | <Alt>0 | org.gnome.Terminal.Legacy.Keybindings | switch-to-tab-10 | | <Alt>1 | org.gnome.Terminal.Legacy.Keybindings | switch-to-tab-1 | | <Alt>2 | org.gnome.Terminal.Legacy.Keybindings | switch-to-tab-2 | | <Alt>3 | org.gnome.Terminal.Legacy.Keybindings | switch-to-tab-3 | | <Alt>4 | org.gnome.Terminal.Legacy.Keybindings | switch-to-tab-4 | | <Alt>5 | org.gnome.Terminal.Legacy.Keybindings | switch-to-tab-5 | | <Alt>6 | org.gnome.Terminal.Legacy.Keybindings | switch-to-tab-6 | | ... | ... | ... |
A simple
M-x occur RET Control RET
in the resulting buffer, followed by some eye-balling will help you identify the GNOME component.For example, if you are looking for the
C-.
, then the entry of interest is| <Control>period | org.freedesktop.ibus.panel.emoji | hotkey |
- Once you have identified the thief-—that is, the specific
Gsettings
key-—that needs to be re-configured, you can either use theGNOME Control Center
, the component-specific GUI or thedconf-editor
to re-configure or reset the keys. In theC-.
andC-;
case , it is theibus
panel, which is the thief, and you could reset the keys as reclaim the stolen keys as shown below.$ ibus-setup
- If you disdain using GUI-—you should be, because you are a pre-historic beast (beest?)-—you can do
$ gsettings set org.freedesktop.ibus.panel.emoji hotkey "@as []"
Bonus TIP: How to save and migrate your GSettings
to some other machine
If you are having multiple work machines, then you can use
$ dconf dump / > dconf-settings.in $ dconf load / < dconf-settings.in
$ dconf reset -f /
Conclusion
To an Emacs
user, keyboard keys are a scarce resource; and having someone steal the already scarce set of keys is well-nigh a nightmare. So, it is good to know what to do in case Emacs
doesn’t respond to some keys. The solution outlined here targets GNOME Desktop
users. I will be happy to hear sob stories, and redemption options available for KDE
, Windows
, or Mac
desktop users.
If you haven’t already noticed, the Emacs Lisp
snippet for probing the GSettings
for keybindings uses some heuristics for locating the keyboard shortcuts. Some heuristics in necessary; this is because the values in a GSettings
database does not have a unique type for values that are keyboard shortcuts; the keyboard shortcuts are just a string or an array of strings. I have a hunch that the heuristic used by Emacs Lisp
snippet could fall short, and fail to report an existing keyboard shortcut. So, be wary before you put full faith in the Emacs Lisp
snippet above to do what it claims to do.