Notes about open source software, computers, other stuff.

Tag: Gnome

Using Emacs key bindings in Gnome, Firefox and other applications

As an avid Emacs user, I love to have my Emacs key bindings available in as many places as possible. For example, even though I still regularly use the arrow keys to move the cursor around, I also use Emacs’ Alt-f and Alt-b to move one word forward or back, respectively. Similarly, Ctrl-a to me doesn’t mean “select all”, but rather “go to the beginning of line” (like the Home key). And especially this latter keybinding has a huge potential to mess things up, e.g. when you follow it by typing text, because that will then overwrite the selected text, i.e. all text. And the only thing I really intended to do was to go to the beginning of the line.

Another clash: in Emacs Ctrl-k means “kill to end of line”, i.e. “delete everything from the cursor position up to the end of the current line”, but in Firefox it sends your cursor to the Search box (for those of you who, like me, still use that for searching instead of just typing your query in the address bar). Similarly, Ctrl-n moves one character forward in Emacs, but in Firefox it opens a new window.

Luckily for me, I have managed to tailor the settings of various tools and the Gnome desktop environment to accommodate at least some of the more common Emacs key bindings. Unfortunately, applications built using other frameworks, like the Signal and Mattermost desktop apps, don’t follow these settings.

Below are the settings I’m currently using. Most of them have been with me for several years at this point and have been migrated various Ubuntu Linux upgrades, so I hope they are complete. For the record, I’m currently running the 24.04 Noble Numbat release.

Gnome

Let’s start with the Gnome desktop environment. My Linux desktop of choice for roughly the past twenty years has been Ubuntu, which uses Gnome. There is a gsettings entry that allows you to enable Emacs key bindings in most Gnome/Gtk applications, including Thunderbird. The entry can be set by setting the “Emacs input” toggle in the Keyboard section of the Gnome Tweak tool, or directly on the command line with

gsettings get org.gnome.desktop.interface gtk-key-theme "Emacs"

The current value can be checked like this:

$ gsettings get org.gnome.desktop.interface gtk-key-theme
'Emacs'

The Arch Linux wiki also lists options for GTK-2.0 and GTK-3.0, but I haven’t got those configured (any more).

Gnome terminal

By default, Gnome terminal steals the Alt key and uses e.g. Alt-f to open the file menu. This can be turned off by going to the hamburger menu in the top right corner and under “Global” — “General” uncheck the box for “Enable mnemonics (such as Alt-F to open the File menu)”.

Shells (Bash, Zsh)

As Emacs has been around for so many years, many shells (well, actually, the readline library if I’m not mistaken) support the basic Emacs key bindings for editing the commands you type on the command line. Both Bash and Zsh use the Emacs bindings by default (others might do too, but I don’t have any experience with other shells, except tcsh a long long time ago). In fact, you have to run set -o vi on order to be able to use Vim key bindings.

Byobu & Screen

I often use byobo as a terminal multiplexer. Like screen it likes to “steal” Ctrl-a as “attention” or “escape” key. Luckily, when the user presses Ctrl-a for the first time in Byobu, they are asked whether they’d like to use Emacs key bindings or not. My answer is obvious, and I generally give them Ctrl-o to use instead. This can be done via a menu by pressing F9 and selecting “Change escape sequence”.

Alternatively, this can be changed in the ~/.byoby/keybindings file by adding the following code:

# replace ctrl-A by ctrl-o
escape ^Oo

For screen the same line should be added to ~/.screenrc .

Firefox

My solution for Firefox is to replace the Ctrl key with the Alt key. This way, I can open new tabs with Alt-t, new windows with Alt-n, etc. Together with the Gnome settings for Emacs key bindings (see above), this means I can use Ctrl-a, Ctrl-f, Ctrl-b, etc. for moving the cursor in text fields, Ctrl-d for delete, etc. Interestingly enough, Alt-f and Alt-b — for “move one word forward” and “move one word backward”, respectively — keep working in text fields as well. Note that this also means that “Undo” is handled by Alt-z instead of Ctrl-z, which is fine with me because Ctrl-z is normally used to let applications run in the background (in the shell).

Unfortunately, some sites seem to define their own extra keybindings that interfere with my settings. For example, when creating or commenting on a Github issue, Ctrl-e inserts a backtick (`), instead of going to the end of line. I haven’t yet found out how to disable or overwrite that. I’m glad that I mainly use Gitlab, as it behaves properly.

To change the key, point to about:config in the address bar of the browser and find the entry ui.key.accelKey and change its value to 18. This is the code for the Alt key (see the documentation). You may want to set the entries ui.key.generalAccessKey and ui.key.menuAccessKey to 0 to disable e.g. using Alt for accessing the menus, but I haven’t done so myself.

Additional documentation about Emacs key bindings in Firefox can be found in the Mozilla knowledgebase article.

There are, and have been, various Firefox extensions or other methods that allow(-ed) one to use Emacs for editing text in textfields like those used in forum posts, etc. However, the last one I used, “Emacs Everywhere” unfortunately doesn’t work yet with the Wayland window manager, although work seems to be on the way to fix that.

LibreOffice

Unfortunately I regularly have to edit MS Word documents (or their LibreOffice counterpart). Fortunately, Marcus Nitzschke created a customisation list for LibreOffice Writer that sets a series of basic Emacs movement key bindings! On his site he links to a Zip file that can be imported via Tools — Customize — Keyboard — Load. After that, the following keys should work in LibreOffice Writer (thanks to Marcus for this list):

Binding Function
C-f forward-char
C-b backward-char
C-n next-line
C-p previous-line
M-f forward-word
M-b backward-word
C-v next page
M-v previous page
C-a beginning-of-line
C-e end-of-line
C-k kill-line
M-d kill-word
M-backspace backward-kill-word

Related Images:

Opening Emacs (-client) windows with full screen height

I usually want my Emacs windows, including those opened via emacsclient, to be opened using the full screen height. It turns out that Emacs has a command line option for this:

emacs --fullheight

Now, for emacsclient this option doesn’t exist, so how can we solve this? Looking around the web, I found this answer on Emacs StackExchange that explained how to do this from within Emacs (see also the fullscreen option on the corresponding page in the Emacs manual). Combined with this answer on StackOverflow that shows how to use the -F/--frame-parameters option of emacsclient I managed to open a full-height Emacs client window:

emacsclient --create-frame --frame-parameters="'(fullscreen . fullheight)"

Most of the time I open new Emacs (-client) windows using the button in Ubuntu’s/Gnome shell’s dock. So how do we incorporate the aforementioned options in the relevant .desktop file? Before explaining how I did this, I have to mention that I don’t use a pre-packaged version of Emacs. As of this writing Emacs v27.2 is the latest official release, but I have been compiling Emacs from source for about two years now. About a month ago I compiled Emacs from the emacs-28 branch 1, which contains what will become Emacs v28. In this branch the .desktop files used by Gnome for its list of applications (including the icons/launchers that end up in the Gnome shell dock) have received some love. For example, the emacsclient.desktop file now opens a regular Emacs at first launch, but subsequent clicks on the icon will launch an Emacs client window. Right-clicking on the icon shows an option called “New Instance”, which will do as it says: launch a new Emacs instance. Well done Emacs maintainers! This perfectly fits my workflow, where most of the time I want to open a client window, but sometimes want to open a new Emacs instance (e.g. when I don’t want to clutter my regular workspaces).

So, getting back to the fullheight topic, editing the emacsclient.desktop file seemed like the way to go. Given that I compile Emacs from source and do not install it system-wide (I used the --prefix=/home/$USER/.local option when running ./configure), the .desktop files can be found in ~/.local/share/applications. This is the contents of the emacsclient.desktop file before I edited it:

[Desktop Entry]
Name=Emacs (Client)
GenericName=Text Editor
Comment=Edit text
MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;
Exec=sh -c "if [ -n \\"\\$*\\" ]; then exec emacsclient --alternate-editor= --display=\\"\\$DISPLAY\\" \\"\\$@\\"; else exec emacsclient --alternate-editor= --create-frame; fi" %F
Icon=emacs
Type=Application
Terminal=false
Categories=Development;TextEditor;
StartupNotify=true
StartupWMClass=Emacs
Keywords=emacsclient;
Actions=new-window;new-instance;

[Desktop Action new-window]
Name=New Window
Exec=/home/lennart/.local/bin/emacsclient --alternate-editor= --create-frame %F

[Desktop Action new-instance]
Name=New Instance
Exec=emacs %F

After my edits, this is the contents of the file:

[Desktop Entry]
Name=Emacs (Client)
GenericName=Text Editor
Comment=Edit text
MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;
Exec=sh -c "if [ -n \\"\\$*\\" ]; then exec emacsclient --alternate-editor=  --frame-parameters=\\"'(fullscreen . fullheight)\\" --display=\\"\\$DISPLAY\\" \\"\\$@\\"; else exec emacsclient --alternate-editor= --create-frame --frame-parameters=\\"'(fullscreen . fullheight)\\"; fi" %F
Icon=emacs
Type=Application
Terminal=false
Categories=Development;TextEditor;
StartupNotify=true
StartupWMClass=Emacs
Keywords=emacsclient;
Actions=new-window;new-instance;

[Desktop Action new-window]
Name=New Window
Exec=/home/lennart/.local/bin/emacsclient --alternate-editor= --create-frame --frame-parameters="'(fullscreen . fullheight)" %F

[Desktop Action new-instance]
Name=New Instance
Exec=emacs --fullheight %F

The diff is:

@@ -3,7 +3,7 @@
 GenericName=Text Editor
 Comment=Edit text
 MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++;
-Exec=sh -c "if [ -n \\"\\$*\\" ]; then exec emacsclient --alternate-editor= --display=\\"\\$DISPLAY\\" \\"\\$@\\"; else exec emacsclient --alternate-editor= --create-frame; fi" %F
+Exec=sh -c "if [ -n \\"\\$*\\" ]; then exec emacsclient --alternate-editor=  --frame-parameters=\\"'(fullscreen . fullheight)\\" --display=\\"\\$DISPLAY\\" \\"\\$@\\"; else exec emacsclient --alternate-editor= --create-frame --frame-parameters=\\"'(fullscreen . fullheight)\\"; fi" %F
 Icon=emacs
 Type=Application
 Terminal=false
@@ -15,8 +15,8 @@

 [Desktop Action new-window]
 Name=New Window
-Exec=/home/lennart/.local/bin/emacsclient --alternate-editor= --create-frame %F
+Exec=/home/lennart/.local/bin/emacsclient --alternate-editor= --create-frame --frame-parameters="'(fullscreen . fullheight)" %F

 [Desktop Action new-instance]
 Name=New Instance
-Exec=emacs %F
+Exec=emacs --fullheight %F

One final note: for those who don’t use the Emacs client, there is also the emacs.desktop file, with the same icon. You can find out which one is in your Gnome shell dock by running:

gsettings get org.gnome.shell favorite-apps

which returns a list like this:

['org.gnome.Terminal.desktop', 'thunderbird.desktop', 'firefox.desktop', 'emacsclient.desktop']

If you’d like to edit this variable manually, you can use either dconf-editor to edit org/gnome/shell/favorite-apps, or set it directly:

gsettings set org.gnome.shell favorite-apps "['org.gnome.Terminal.desktop', 'thunderbird.desktop', 'firefox.desktop', 'emacs.desktop']"

Note, the order of the list matters!

Footnotes:

1

The commit I used was d86b2e59c.

Related Images:

Use a script to convert Office files to PDF via Nautilus’ right-click menu

Recently, I bought a reMarkable 2, a tablet-like device with an e-ink screen that allows me to replace real paper with digital note taking, while keeping the hand-written aspect of writing notes. The device also allows me to read and annotate PDFs in a comfortable way. Given that I use RMfuse to ‘mount’ the reMarkable cloud on my computer, I normally drag-n-drop the files I want to read in GNOME Files (formerly Nautilus, GNOME’s file manager) from their location on my computer to the mounted cloud.

This works really well so far. However, I also regularly receive files in the MS Office .docx format. Often I need to make substantial changes in these documents, which I do on my laptop or computer. But sometimes I only need to read them or only put my signature at the bottom. For these cases I would open the .docx file in LibreOffice, convert it to PDF and copy it to my reMarkable. In order to speed this up, I thought it would be nice to have some way where I right-click on a .docx file in GNOME Files/Nautilus and then convert it to PDF automatically, after which I can drag-n-drop the PDF file to the mounted reMarkable cloud.

So the question was: how can I add an item to the right-click menu of Nautilus, which runs a script when I click on it. After looking around on the internet, this turned out to be quite easy. It turns out that scripts placed in ~/.local/share/nautilus/scripts/ end up in the Nautilus right-click menu under the Scripts submenu.

To do the actual conversion to PDF, I created the following script:

#!/bin/bash
# This script converts the selected file to PDF using LibreOffice
# For general instructions on how to use Nautilus scripts, see
# https://help.ubuntu.com/community/NautilusScriptsHowto
#
# Save this script in ~/.local/share/nautilus/scripts/ and make it
# executable.

IFS_BAK=$IFS
IFS="
"

for SelectedFile in ${NAUTILUS_SCRIPT_SELECTED_FILE_PATHS}; do
    soffice \
        --nodefault \
        --nolockcheck \
        --nologo \
        --norestore \
        --nofirststartwizard \
        --convert-to pdf "${SelectedFile}"
done

IFS=$IFS_BAK

Because I wanted to be able to select multiple files, some having spaces in their names, I had to make sure the space character wasn’t used to split the NAUTILUS_SCRIPT_SELECTED_FILE_PATHS variable. That is why I temporarily replace the IFS variable with a newline.

I have only tried this on .docx files so far, but I guess it would work on presentations and spreadsheets as well.

Related Images:

© 2024 Lennart's weblog

Theme by Anders NorénUp ↑