Notes on Mastering Emacs: Chapter 3: First Steps

By Susam Pal on 07 Jan 2023

The following notes were taken while discussing Chapter 3 of the book Mastering Emacs, 2022 edition (written by Mickey Petersen) in book discussion group meetings.

An index of notes for all chapters are available at notes.html.

Contents

Starting Emacs

Here are some frequently used commands to start Emacs:

Emacs Client-Server

The key sequence M-x server-start RET turns the current instance of Emacs into a server. If we kill this instance of Emacs, it kills the server too.

Another way to start an Emacs server is to enter the command emacs --daemon. This too internally invokes server-start to start an Emacs server but this command ensures that Emacs runs in background mode. Therefore, killing any particular instance of Emacs window does not end up killing the Emacs server.

To open files, say foo.txt and bar.txt in an already running Emacs server, enter the command emacsclient foo.txt bar.txt. This command blocks the terminal and waits for us to finish editing the files. While editing the files, we need to type C-x # to tell Emacs that we are done editing the current file. Emacs then switches to the next file we are editing. When we are done editing all the files opened, emacsclient quits and returns control to the terminal.

The book does not mention how to stop an Emacs daemon. One of the several ways to stop an Emacs daemon is the command emacsclient -e '(kill-emacs)'.

Here are some commands to run emacsclient:

The Emacs Interface

The book mentions that many Emacs users disable the menu bar, tool bar, and the splash screen. The following Elisp code shows how these UI elements can be disabled:

(menu-bar-mode 0)
(when (display-graphic-p)
  (tool-bar-mode 0)
  (scroll-bar-mode 0))
(setq inhibit-startup-screen t)

After saving the code in the initialisation file (such as ~/.emacs, ~/.emacs.d/init.el, etc.) and restarting Emacs, these UI elements disappear.

It is worth mentioning here that disabling the menu bar may not be a good idea, especially, for beginners to Emacs. The menu bar contains a lot of helpful shortcuts that could be useful to beginners. Further, the menu bar often displays certain menus that are specific to the current buffer. Therefore, it may be a good idea to leave the menu bar enabled.

Regardless of whether the menu bar is enabled or disabled, the menu bar can accessed easily by typing F10.

Keys

The book mentions the following notation for modifier keys:

Although not mentioned in the book, here is a quick way to test out all of these modifier keys:

(global-set-key (kbd "C-j") (lambda () (interactive) (message "You typed C-j")))
(global-set-key (kbd "M-j") (lambda () (interactive) (message "You typed M-j")))
(global-set-key (kbd "C-S-j") (lambda () (interactive) (message "You typed C-S-j")))
(global-set-key (kbd "s-j") (lambda () (interactive) (message "You typed s-j")))
(global-set-key (kbd "H-j") (lambda () (interactive) (message "You typed H-j")))
(global-set-key (kbd "A-j") (lambda () (interactive) (message "You typed A-j")))

Go to some buffer, say, the scratch buffer with C-x b *scratch* RET, then copy the above code to it, then place the cursor at the end of each line of code and type C-x e to evaluate each line.

Then open a new buffer, say with C-x b foo RET and type ctrl+j, alt+j, and ctrl+shift+j to test the first three key bindings.

The fourth key-binding s-j can usually be invoked by typing command+j or win+j depending on the type of keyboard you have.

The H- and A- modifier keys are generally not mapped to any actual key in modern systems. However, it is possible to invoke the H-j and A-j key bindings with the key sequences C-x @ h j and C-x @ a j, respectively, i.e., ctrl+x @ h j and ctrl+x @ a j, respectively.

In fact, similarly, s-j too can be invoked with C-x @ s j, i.e., ctrl+x @ s j but that is rarely necessary because s- is often bound to a GUI key like the command key on Apple keyboards and the win key on Windows keyboards.

A practical example of a real and useful s- key binding from vanilla Emacs is s-u to invoke the revert-buffer command that reloads a file from the disk.

Terminal Limitations

The book mentions that there are some key bindings that we cannot use if we are running Emacs in the terminal. That is because a terminal supports a very limited set of key bindings. An example is C-/ that invokes the undo command in GUI Emacs. The terminal does not recognise that key sequence. However, the undo command is also bound to C-_ and C-x u, so one of these key sequences can be used to undo changes in terminal Emacs.

Definitions for Key Sequences

The book provides a few definitions of key sequences that can be summarised as follows:

Key Examples

The section Keys presents the following examples of key sequences:

C-g: Universal Bail Me Out

The key sequence C-g is used to cancel a partially completed command. For example, normally, the key sequence M-x whitespace-mode RET toggles the visibility of whitespace in the current buffer. However, let us say, we type the partial key sequence M-x white and then we change our mind about it and want to cancel entering the command any further, we can simply type C-g to run keyboard-quit that signals a quit condition and cancels the input.

Similarly, say, we type C-x and then we change our mind about it and want to cancel this partially entered key sequence, we can simply type C-g. The following message appears in the echo area but this is by design:

C-x C-g is undefined

Don't let that message make you feel that you did something wrong by entering an undefined key sequence. Key sequences ending with C-g have been intentionally left undefined, so that it can be used reliably as the universal bail me out key sequence.

Now of course, nothing stops us from binding C-x C-g to a command of our choice. For example, the following Elisp code binds it to a command that prints a message:

(global-set-key (kbd "C-x C-g") (lambda () (interactive) (message "You typed C-x C-g")))

However, a key binding like the above one is a very bad idea because such a key binding flies against Emacs conventions. If we were to create a key binding like the above one, we can longer rely on C-g to be our universal bail out command. Key sequences ending with C-g are best left undefined.

Caps Lock as Control

The book recommends configuring our operating system to make the caps lock key behave like ctrl. Many people do find this type of remapping very convenient. Many discussions can be found online where people have claimed that this remapping has helped with overcoming repetitive strain injury (RSI). However, the article Moving the Ctrl Key on Emacs Wiki claims that for some people this remapping causes RSI.

I use the original ctrl keys as they come with the keyboard. Most keyboards have two ctrl keys on either side of the keyboard which I find very convenient. I touch type while editing text, so the two ctrl keys on either side of the keyboard turn out to be really useful. For example, when I need to type ctrl+a, I can hold down ctrl with the little finger of the right hand and type a with the little finger of the left hand. Similarly, if I need to type ctrl+p, I can hold down ctrl with the little finger of the left hand and type p with the little finger of the right hand. Using the original ctrl keys offers this advantage of distributing the usage of the ctrl to both hands. However, some Apple keyboards provide only a single ctrl key on the left hand side which can be quite annoying to touch typists. In such keyboards, remapping the caps lock key to behave like ctrl key can indeed be more convenient.

M-x: Execute Extended Command

The key sequence M-x is pronounced mex, M x, or meta x. It invokes the command execute-extended-command that brings up a minibuffer to read a command name and execute it.

When M-x key sequences are presented in written form, often they may be written in a precise manner that includes the M-x key sequence, then the command name, and finally the RET key in the end, e.g., M-x lunar-phases RET. But sometimes they may also be written without the RET key, e.g., M-x lunar-phases. The RET key is automatically implied in the latter form.

Interactive Commands

The following function written in Elisp is interactive:

(defun hello ()
  (interactive)
  (message "hello"))

However, the following function is not interactive:

(defun hola ()
  (message "hola"))

The (interactive) expression declares a function as interactive which allows it to be called interactively using M-x.

To see the difference between the two functions, copy both functions to some buffer, say, the scratch buffer, and then put the cursor after the closing parentheses of each function and type C-x C-e to evaluate the defun expressions thus defining the functions. After doing so, M-x hello RET executes the hello function and produces the "hello" message in the echo area. However, typing M-x hola RET produces no match for a function named hola.

M-X: Execute Extended Command for Buffer

Emacs 28 introduces M-X that runs the command execute-extended-command-for-buffer. The book mentions this key binding as M-S-x which is in fact M-X. In these notes, we'll write M-X for consistency with how this key sequence is actually defined and represented in Emacs (for example, note that C-h k M-S-x shows the key as M-X).

To see how this function works, first open a file, say, foo.el with C-x C-f foo.el RET, then type M-x e RET. A large list of function names beginning with the letter "e" as choices appears. Now type M-X e RET. A much smaller list of choices that are relevant for the current Elisp buffer appears.

Universal Arguments

Universal arguments are also called prefix arguments. The list below presents some examples of complete key sequences where we apply various prefix arguments to the key sequence C-n.

Note that negative arguments (the last three examples above) reverses the direction of operation. The digit arguments of the form C-<digit> can also be entered using M-<digit> or C-M-<digit>. Here are some examples:

While entering multiple digits in a digit argument, we can also mix and match modifier keys as shown below, however doing so would be pointless and unwieldy:

The reason why Emacs supports entering digit arguments or negative arguments with all three modifier combinations C-, M-, C-M-, is so that we can choose a modifier that is convenient. Usually, this would be the modifier we anticipate that we'll use next for the command we are prefixing with the digit or negative argument. For example, if we are going to move forward by 5 words, then M-5 M-f is going to be more convenient than C-5 M-f or C-M-5 M-f. To type M-5 M-f, we can simply press and hold down alt, then type 5 followed by f, and finally release alt. Similarly, if we are going to move forward by 5 expressions, then C-M-5 C-M-f is going to be more convenient than using any other modifier for the digit argument.

Choosing the modifier combination for a universal argument such that it matches the modifier combination for the key sequence coming up next helps maintain good tempo while typing the key sequences. The book often puts emphasis on the subject of tempo in various chapters.

While discussing tempo, the book presents the example of M-- M-d which can be used to kill the previous word. Note that M-d kills one word forward, so M-- M-d reverses the direction of the operation and kills one word backward. The book notes that M-- M-d maintains tempo while C-- M-d which does exactly the same thing disrupts tempo.

Another example that the section Univeral Arguments briefly alludes to but does not provide a concrete example of is changing the case of a word that we just typed. Here are some concrete examples for it:

Discovering and Remembering Keys

To get help for a prefix key, type the prefix key followed by C-h. Here are some examples:

Getting help for a prefix key in this manner shows an automatically generated list of all keys that belong to the key map associated with the prefix key. Note that a key map for a prefix key may itself contain more prefix keys. For example, in the above examples, we see that the key map for C-x 8 contains prefix keys C-x 8 ", C-x 8 ', etc. Such nested prefix keys are clearly marked in the output as "Prefix Command".

True Color

There is a note with the title Supported colors in the section The Customize Interface that introduces the following commands:

Since Emacs 28, we can easily enable 24-bit color in terminal Emacs by setting the environment variable COLORTERM=truecolor. To quickly test it out, first enter the following command in the terminal:

COLORTERM=truecolor emacs -nw

Then type the following in Emacs:

M-x list-color-display RET

The Customize Interface

The customize interface allows us to customize two things: faces and options. Here are some steps to get started with the customize interface:

  1. Type C-x 2 to split the current window into two.

  2. Type C-x C-f foo.el RET to open a new Elisp file.

  3. Type some code into the file such that it contains at least one string, for example:

    (message "hello")
  4. Type C-x o to go to the other window.

  5. Type M-x customize RET.

  6. Move the cursor to the editable text area. This can be done with motion key sequences or with the mouse.

  7. Then type font-lock-string-face and press enter. The customization interface for the chosen face now appears in the buffer. The message next to the "State" button shows "STANDARD." which indicates that the face is set to its default value.

  8. Then move the cursor to the editable text area next to the "Foreground:" label, type blue. At this point, a preview of blue text is shown next to the "Choose" button. However, the string in the Elisp buffer still appears in its previous colour. The message next to the "State" button shows "EDITED, shown value does not take effect until you set or save it."

  9. Now click the "Apply" button to apply the new string colour. Alternatively, move the cursor over to "Apply" and press enter. As soon as this button is clicked, the string in the Elisp buffer appears blue. The message next to the "State" button says "Set for current session only."

  10. Now click the "Revert..." button and then click "Revert This Session's Customizations" to revert the customization.

  11. Now change the string color to blue again and click "Apply and Save". The message next to the "State" button now changes to "SAVED and set." Then check Emacs initialisation file (such as ~/.emacs, ~/.emacs.d/init.el, etc.) and there should be a custom-set-faces call added to the initialisation file to set the string colour to blue.

  12. To erase the customization from the initialisation file, click "Revert ..." and then click "Erase Customizations". At this point, the customization is no longer present in the initialisation file. However, the customize interface shows a confusing message next to the "State" button, "EDITED, shown value does not take effect until you set or save it." Further, the face is set to "-- Empty face --" in the customization interface. To add to the confusion, the "Apply and Save" button is enabled! Beware though! If "Apply and Save" is clicked now, it will set nil as the value for the face which will cause the face to appear black or white (not the default colour).

  13. To get rid of the confusing state of the customization buffer discussed in the previous point and restore the customization buffer to a sane state, click "Revert ..." and then click either "Undo Edits in Customization Buffer" or click "Revert This Session's Customizations". Doing so would end up showing the default colour of the face in the customize interface. The message next to the "State" button shows "STANDARD." again.

Customize Commands

Here are some examples of complete key sequences that invoke various customize commands:

One thing worth keeping in mind is that when we apply, save, or revert customizations, only the customizations shown in the current buffer are applied, saved, or reverted. Here is an experiment that demonstrates what this means:

  1. Type C-x 2 followed by C-x C-f foo.el RET to split the current window into two and load an Elisp file in one window. Then insert the following code:

    (defun foo () (message "hello")) ;; Demo
  2. Type M-x customize RET, search for font-lock-keyword-face, set its colour to red and click "Apply".

  3. Then search for font-lock-function-name-face, set its colour to green and click "Apply". At this point the macro name defun is coloured red and the function name foo is coloured green in the Elisp buffer.

  4. Now click "Revert ..." and then click "Revert This Sessions's Customizations". Only the colour of the function name reverts to the default colour. The colour of the macro name remains red in the Elisp buffer. This confirms that the revert operation takes only the customizations in the buffer into account.

  5. Search for font-lock-string-face, set its colour to blue and click "Apply and Save".

  6. Search for font-lock-comment-face, set its colour to magenta and click "Apply and Save". Inspecting the Emacs initialisation file shows that only the customizations for the string and comment faces have been saved to the file. This confirms that only the customizations shown in the current buffer are saved.

  7. Type M-x customize-customized RET. A new buffer appears and shows the customization for keyword because it was customized and applied but not saved.

  8. Type M-x customize-saved RET. A new buffer appears and shows the customizations for string and comment because they were customized and saved.

  9. Now search for font-lock-comment-face so that the customize buffer contains only the customization entry for comment. Click "Revert ..." and then click "Erase customizations". Inspecting the Emacs initialisation file shows that the customization for comment is removed but the customization for string is still intact. This confirms that only the customization shown in the current buffer is erased.

Evaluating Elisp Code

The chapter introduces two commands:

Here are some additional key sequences that I find very useful:

Info

Info, also known as the Info Reader, is the documentation browser of Emacs. Type M-x info RET or C-h i to enter Info.

The following points explain the navigation commands of Info:

To summarise, the commands [ and ] are great for browsing every node. The command SPC and DEL are good for reading everything paragraph by paragraph and page by page.

There are several ways to reach a specific node of a specific manual. The following points describe some of them:

Apropos

The following key sequences demonstrate how to use the apropos system:

By default, the apropos commands show the results in alphabetical order. To sort them by scores, evaluate the following Elisp expression:

(setq apropos-sort-by-scores t)

To sort the matches by score as well as show the scores within parentheses next to the matches, evaluate the following Elisp expression:

(setq apropos-sort-by-scores 'verbose)

Note that sorting by score does not work for C-h d (apropos-documentation).

Describe

The following key sequences demonstrate the describe system:

The following list includes some links that were discussed during the book discussion group meetings: