Gaurab Paul

Polyglot software developer & consultant passionate about web development, distributed systems and open source technologies

Support my blog and open-source work

Tags

Getting productive with selection and navigation in Emacs
Posted  6 years ago

This post is intended to primarily benefit people coming from other, so called “modern” editors to Emacs. Emacs veterans are likely to find most of the tips here very elementary.

I have observed that many programmers habituated to newer editors have many implicit assumptions about editing workflows which simply don’t hold true within Emacs environment and this prevents them from being productive to the fullest extent.

This post primarily focusses on how getting familiar with the concept of marks and regions in Emacs can result in productive workflows. These concepts, coupled with a few extensions can enable much more pleasurable code-editing workflows not easily achievable in more prevalent “modern” editors.

Marks and the Mark Ring

Perhaps among the first things which we learn when dipping toes into Emacs is that C-spc is the keybinding used to select region.

We start a selection with C-spc, navigate to the the end of what we want to select, and then trigger a command to do something with the selection eg. Cut using C-w, Copy using M-w etc.[1]

While the above explanation usually suffices to get people started with elementary usage, the concept of marks gets lost in the process.

C-spc (or more accurately set-mark-command which this is key is bound to by default) actually does two things:

Once point has been marked, moving the point by inserting text, navigating etc. changes the active region. This active region, between the point and the mark, is what we see as highlighted. [2].

While this is superficially similar to how selections behave in most other GUI applications, there are some important differences:

Commands can operate on invisible regions

A region is highlighted (visible) when it is active. But commands like kill (cut), kill-ring-save (copy) etc. operate on regions and don’t care whether or not the region is active. This can be surprising and may appear to be a bug when a C-w copies away a large chunk of text even if there is no visible selection on screen.

While it is possible to make Emacs behave like other prevalent editors in this respect, I find the Emacs behavior slightly better.

This is because we can set the mark, continue typing, and then once done use C-w to copy the current region. This is useful when we know beforehand that we are going to need what we are typing later, eg. multiple class/interface names which have partially shared names by conventions. We thereby save on the extra navigation that would otherwise be required after typing.

Lets say we want to write the following (typescript) code:

We see that there is quite a bit of redundancy in the names. We can utilize the above trick when typing to easily having to retype anything.

Marks are useful by themselves: for navigation

This is perhaps the least intuitive part. Typing C-u C-spc jumps to a mark. So frequently it is useful to set a mark without needing a selection. Emacs keeps a buffer local history of marks in a mark ring.

We can use C-spc C-spc to mark a point without activating a region.

I personally prefer a slightly more old-school approach where I have transient-mark-mode disabled by default.

In this configuration, the regions are not visible by default, and C-spc just sets the mark and does not activate a region.

It is occassionally convenient to highlight the region which will be selected, and for these cases we can can press C-spc C-spc. The double invocation temporarily activates the transient mark mode and active regions become visible.

Helm integration

Helm is a sophisticated completion system that vastly overhauls the development workflow in Emacs. This tutorial does not focus on helm, an excellent one has already been written by Tuh Do. Helm requires some getting used to, but once habituated, its somewhat unconventional out-of-order matching system gets the job done a lot faster than other prevalent prefix-based or fuzzy-matching completion systems.

Helm provides a command helm-mark-ring which shows all active marks in current buffer, and makes it easy to quickly jump to them. There is an analogous command helm-all-mark-rings which shows all marks across buffers.

While marks are useful for a small number of recent locations, when we are exploring large projects, it is useful to tag points with a name, which are easy to remember and get back to. This is easily done by bookmarks.

Not surprisingly helm provides a way to browse bookmarks too.

The bookmark will by default take the name from current region (useful for bookmarking definition sites of symbols in code), or if a region is not active, the current file name.

It is also possible to save points to registers and access them later, but I don’t find myself using them much. Unlike registers, bookmarks are persistend over sessions, and can have descriptive names – both of which I find desirable when working with larger projects.

More on regions

Now that we know about marks, let us focus a bit on regions. As we mentioned above, a region is the area between point and a mark.

Regions allow us to perform operations on a selection of text. Like the bookmark-set command described above, many commands have special support for active regions when it makes sense to simplify workflow in the context.

Browsing Emacs documentation every once in a while is guaranteed to be a rewarding experience.

Expanding selections

In modern editors, we usually select a region by mouse or by use shift+arrow keys and if we realize later that the starting of selection was wrong, maybe we left out a character or a word, woops ! We have to start again.

In Emacs this is not the case.

Once we have a region, between a point and mark, we can use C-x C-x to exchange the point and the mark. The relevant command is appropriately called exchange-point-and-mark.

Note that we still effectively have the same region. Exchanging point and mark allows us to grow (or shrink) the region from either ends.

Expanding and narrowing selections

Why navigation and selection usually coupled, navigation is not always the best option to expand selection.

Magnar Sveen has written a very useful package expand-region which allows us to create a region from the point and expand it by semantic units.

So first invocation selects a word, and then the next invocation expands the region to a symbol, further to a string, further to the string wrapped in quotes and so on to encompass the whole line and finally the whole buffer.

Rectangular selections

Emacs also provides a somewhat unique feature for selecting two dimensional rectangles of code. This is useful when working with tabular data, log files etc. as well as when creating ascii art.

CUA bindings come with an enhanced rectangle mode which I prefer over the above.

One great feature here, is the ability to cycle through the corners and expand the rectangles in all directions

Other navigation tips

Jumping to locations of recent changes

It is often useful to jump to the location where a change was recently made. The appropriately named GotoLastChange extension is a very useful one that allows us to travel along the locations of edits.

Incremental search for navigation

Incremental search (C-s) of emacs is really helpful quick navigation. isearch-forward and its regex powered companion isearch-companion-forward quickly become the goto utilities for navigating through large code files.

ISearch and Marks

When you start an incremental search, as you type, your cursor will move to the tail end of the next (best) prefix-match.

When you complete the search with enter, the point where the search started is marked. This makes it possible to quickly jump back to the point from where we originally started entering the isearch query.

A common error is to assume that the isearch match is an active region. It is not. As should be obvious from the statement above, the region at the point of completion of search, is from the point where started the isearch to the point where the search finished.

It is, however, frequently useful to have the matched content as the region, which can be accomplished by marking the head of the current match. This can be done by using C-r to jump to head of current match.

In addition to incremental-search, I have found a few other utilities very helpful for navigating through projects:

Helm-swoop

Helm swoop provides an efficient way to find matches across files. It provides a helm friendly way to rapidly jump to a matching line anywhere in the entire project.

An example from their home page:

Avy

Avy provides a novel approach that requires fewer keystrokes than an isearch for jumping to a specific location that is already visible. Usually within three keystrokes we can jump to any location in the visible area of the buffer.

Navigating to punctuation

In programming contexts it is often useful to navigation to punctuation markers close by. Prolific blogger Xah Lee has shared some snippets of elisp for achieving the same.

Multiple cursors

A feature common now a days in many editors is the support for multiple cursors. It is useful to do things like editing the same text occurring multiple times simultaneously.

If you are really fond of multi-cursor style editing, Magnar once again has you covered with multiple-cursors.

I usually prefer a more conventional approach, where we can record an edit action as a macro, and then quickly apply in multiple positions.

Emacs Wiki has a good overview on usage of macros.

The advantage over the multiple-cursor approach in that it is much more powerful and composable with any of the navigation patterns described above.

For instance, once a macro has been recorded, it is trivial to use avy to jump to the end of the third word starting with a, and then apply the macro there.

The disadvantage of course is that it requires slightly more keystrokes, but often the flexibility is worth it.

Another utility I occasionally use is multi-region which makes it very easy to mark multiple regions of text and then run a command scoped to each region.

Further resources

Of course, Emacs is famously a “self-documenting” editor. So M-x help-with-tutorial and M-x help are the definitive resources for learning Emacs.

In addition, following are some great resources I have frequently found useful:


[1] If this notations is still unfamiliar, refer Emacs key notation.
[2] This assumes that Transient Mark Mode is enabled. This is true in the default configuration of newer versions of emacs.