Bookmarks as Project Management

Home About Codeberg

Time for another article in my Emacs for Professionals series. This time I would like to recommend a method of using Emacs Bookmarks as a form of project management.

In my experience, people tend to believe Emacs Bookmarks should be used in ways similar to web browser bookmarks. Though there is nothing wrong with using bookmarks in this way, I personally do not find it to be useful for this task. I can usually find a piece of documentation, or a file I have written, more quickly using the Info-mode search functionality, or using tools like Dired. When I have tried using Bookmarks for keeping track of files over long periods of time, I find I usually forget about the bookmarks and end up never using them.

In this article I will explain how to use the Emacs Bookmarks feature in a way that is more useful to me. I will also explain some of the limitations of the built-in Bookmarks functionality.

Just one caveat: personally, I use a workflow based on Hyperbole instead of the built-in Bookmarks functionality that I describe in this article, because Hyperbole overcomes the limitations of built-in Emacs Bookmarks. But for this article, I will focus on the features of a vanilla Emacs installation which anyone can use, and talk about Hyperbole in the next article.

Navigating with tab completion

First lets think about how one usually navigates through the information on your computer in Emacs, without using bookmarks, so we can contrast this to how bookmarks could be used more effectively.

Emacs is already well designed to quickly gather a lot of information into various buffers and allow you to switch between these buffers easily. Most Emacs commands which require you to select from a list of elements, such as {M-x switch-to-buffer} (bound to {C-x b}), will prompt you to select an item by name in the minibuffer and provide you with tab completion so you do not need to type the whole buffer name, saving you a lot of time, and preventing some of the stress of avoiding misspelling.

This ability to select a command and then perform tab completion on anything relevant to that command is one of the most useful features of Emacs. It can be made even more useful when you install Emacs extensions that improve upon the tab completion user interface. Icomplete, Vertico, and Helm are all Emacs extensions that improve the tab completion functionality by displaying a list of recommended items that you can browse with the arrow keys. You can also narrow the list of results shown by typing keyword patterns; any items that contain the keyword in them are shown, all other items are not shown.

Note: Icomplete is built-in, you can enable it with {M-x icomplete-mode}, or by writing the code (icomplete-mode 1) into your Emacs configuration file.

Every Emacs command can provide it's own set of tab completions. For example, when want to switch buffers with {C-x b}, tab completion will only let you select from open buffers, as opposed to selecting from unopened files or directories. The M-x find-file (bound to {C-x C-f}) command and the dired (bound to {C-x d}) command will select from files in the current default-directory. The M-x describe-function (bound to {C-h f}) and the M-x describe-variable (bound to {C-h v}) commands will select only from functions or variables (respectively). The {M-x} command itself also provides tab completion on commands.

Notice how every command has it's own set of completions that are presented for you. It would not be useful if you are searching for an Emacs command and were presented with a list of files to select from.

Why use Bookmarks?

What if you need to provide your own set of completions for a list of related files? This is usually the case when you are working on a particular project where the set of completions you want might be spread across multiple project directories, or even multiple servers if you are using TRAMP to edit remote files. This is where Bookmarks become useful. You can create your own arbitrary set of files that you want to access quickly through tab completion.

How to use Bookmarks

1. Create some bookmarks

To begin using Bookmarks, navigate select any buffer using {M-x switch-to-buffer} (bound to {C-x b}), move the cursor to whatever position in the buffer is most convenient, then use the {M-x bookmark-set} command (bound to {C-x r m}). (Mnemonic: R M is for remember/record a mark).

You will be prompted for a label for this bookmark, the default label will include the name of the buffer. Press {M-p} in the minibuffer prompt to edit the default bookmark label.

It is a good idea to also include a keyword indicating the project to which this bookmark should belong. For example, you might have a file table-of-contents.org on a book you are working on about... (let's just say...) owls. If you bookmark the table of contents, the file name table of contents is not all that descriptive. So it is a good idea to prepend the word owls to the label. All of the files you are working on which you bookmark for you owls book project should also have the exact same word owls in the label. If you also happen to be working a programming project, for example a game, you would bookmark the buffers related to your game with the name of the game.

2. Navigate to bookmarks

The {M-x bookmark-jump} command (bound to {C-x r b}) prompts you in the minibuffer for a bookmark to jump to. With a good completion framework like Icomplete, Vertico, or Helm, you can use tab completion to find your bookmark with just a few keystrokes.

This is where the usefulness of Bookmarks really begins to show. Instead of searching through all open buffers, or all files in a directory, or worrying about which directory to search through, you can simply search through your list of bookmarks. If you consciously keep your bookmark list up-to-date, regularly adding to the list buffers that you are working on, and deleting bookmarks you no longer need, it can become a very fast way to context switch between various buffers in which you are doing work.

3. Keep the bookmarks list up-to-date

Use the {M-x list-bookmarks} command (bound to {C-x r l}), this will open a new buffer called *Bookmark List* which has key bindings set for easy search and navigation. If you have already created several bookmarks, your *Bookmark List* would look something like this.

% Bookmark
(emacs) Bookmarks (emacs) Buffers owls: table of contents owls: overview owls: life cycle game: main.el event loop game: main.el customize game: map-builder.el data structures

In the above example, the buffers marked with (emacs) are bookmarks into the Emacs user reference manual, the chapters on Bookmarks and Buffers. I have three bookmarks for my project on owls, and 3 bookmarks on my game project.

Now you can use the following keys for updating the bookmarks in the *Bookmark List* buffer:

Good habits when using bookmarks

The method of using Emacs Bookmarks that I have proposed here is to keep a list of files and directories between which you are often switching in the present moment for the task you are currently working on, and to use the {C-x r b} to switch between buffers instead of the ordinary {C-x b}. To this end, keep the following in mind:

What you cannot bookmark

Bookmarks must be associated with a file path. This excludes several very useful buffer types that you might want to bookmark. You may try to use the {C-x r m} key in one of the following types of buffer, and be dismayed to see an error message Buffer not visiting a file or directory instead of a prompt for a bookmark label:

In the next article, I will talk about how you can use the Hyperbole package as an alternative to the built-in triad of Emacs Bookmarks commands {M-x r m}, {M-x r b}, {M-x r l}, and be able to bookmark nearly any kind of buffer regardless of it's content.

TODO: talk about related bookmarks extensions

(via Matthew Jorgensen)