Index RSS

Learning Emacs

I've been learning Emacs in the last two weeks and it has been a blast! I'm normally a die-hard Vim user, but even with a lot of customizing, I have to agree that it keeps being an editor (with Unix being the IDE). While Emacs is also just an editor, its main allure for me is that it is extremely flexible. It is script-able in its own Lisp dialect, which is even more attractive to me. That way, Emacs comes closer to replacing an IDE.

In the past, I have dabbled with Spacemacs for short spans of time. I liked it a lot, but I never really felt home with it. I used it mainly as a Vim implementation with some special features, without understanding what makes Emacs tick. Additionally, I am a purist and did not like having huge amounts of packages installed while I only used a few selected ones (knowingly). These points made me go back to my beloved Vim.

In the last fourteen days, I tried to use Emacs with a vanilla configuration plus whatever I added to it myself. I want to use this article to share some of my first experiences with you in form of a small diary.

Tuesday, 2020-10-20

I installed Emacs on my systems after reading a blog article about it that was interesting enough to make me want to play with it, while being too unspectacular for me to remember what it was that I read. Well, can't remember everything ...

I used this first day to work through the tutorial, which does a great job teaching the most important concepts. For more details, it tells you to read the GNU Info documentation. I have not done so yet, because I only use man pages in my Unix work and just don't know how to navigate info. I believe that knowing the Emacs fundamentals will help me when I try to next time, but still ... I always am kind of salty when I find a man page that just tell me to use info instead. At least that is not a problem when using OpenBSD!

I met with two challenges on the first day: One being that I am using a German keyboard layout, which makes some key combinations difficult to press. The other challenge is that I have to use Windows at work. I installed Scoop.sh, a package manager, to easily install Emacs.

Scoop

Wednesday, 2020-10-21

Starting with this day, I tried to do some of my work in Emacs. As you might imagine, it is quite hard as I am very used to the Vim way. I normally work by using Vim motions to easily do exactly what I want to do: Jump to the next quotation mark, copy the text between the marks, insert a new line above, paste the text ...

One massive productivity multiplicator are macros. They allow you to quickly repeat complex editing steps that you have recorded before. I was nervous whether Emacs wants to me to write Lisp code for use cases where I was using macros in Vim before. Thankfully, Emacs supports "keyboard macros" as well: You can start recording with "C-x (", stop recording with "C-x )" and execute the recorded macro with "C-x e". On top of that, Emacs allows naming these macros and saving them as Lisp functions that you can keep as first-class editor commands. Nice!

On this day, I also worked with dired the first time. This is a functionality that shows the contents of a directory in a text buffer. You can use it to navigate to the files you want to edit, but it also has options to rename, move, copy or delete files. I like it more than ":Explore" in Vim. It just clicks with me.

Vim 8 implemented a feature to open terminals within it. Emacs has multiple features for this. You can use "M-x shell" to run a external shell as a child process, while "M-x eshell" executes a shell that was implemented in Emacs Lisp. The later one has the advantage that it works portably on Unix and Windows. Both seem to have problems with applications that use ANSI escape characters. If you need them, "M-x ansi-term" provides a terminal emulator that is compatible with these applications. That works on OpenBSD, but is not perfect. On Windows, I had some problems that I could not solve yet. I could not run git-bash with Emacs without getting an "inappropriate ioctl" error message. I use only eshell on Windows for that reason.

I also learned on this day to execute shell commands and optionally capture their output or to pipe text from Emacs into them. These are also functionalities that I often use with Vim, and I am pleased to say that I find the Emacs commands "M-x shell-command" and "M-x shell-command-on-region" even easier to work with.

Thursday, 2020-10-22

On Thursday, I used Emacs as a REST client. I know that there are packages that can do this, but I opted for a simpler yet more ad-hoc solution. I wrote some XML in the scratch buffer and used shell-command-on-region to pipe it into curl. This worked well and gave me some opportunities to work with Emacs on a concrete technical problem.

While editing, I noticed that I still feel very clumsy compared to me using Vim. I dearly miss the aforementioned motions and searched for some replacements. I found two packages that seemed to tackle some use cases for Vim motions from a different angle: ace-jump-mode for quickly jumping to a specific portion of the text and expand-region to easily replace text between delimiters. While I did not try them yet, I made a mental note to do so at a later date.

One of the strangest things for me was marking text. With Vim, it always felt very natural for me to use visual mode when I wanted to work with a specific region. But even then, most of the time I did not even need to use visual mode as the motions allow me to quickly execute a change, copy or deletion command on a region described by that motion.

With Emacs, the common case of copying one or more lines feels very cumbersome. You have to move to the front of a line with "C-a", start marking with "C-SPC" and then move to the end of the line with "C-e". This case is so common that I watched myself pressing "C-a" often when I wanted to begin marking - it just was part of the flow and I had to train myself not to do so unless I really wanted to move to the beginning of the line.

On the positive side, I like that Emacs has niceties like "exchange-point-and-mark", which allows me to move my cursor quickly to the other side of the region I am currently marking. I can use this to grow my region from both sides as I see fit. This is not a huge deal, but definitely helps.

Friday, 2020-10-23

Today, I tried to use Emacs inside of my team's Git repository. I often want to quickly search in files (mostly using "git grep") or open a file by name without knowing the exact path to it. While coding, Eclipse does most of the work, but it is horrible slow. For that reason, I do as much as I can (that does not absolutely need Java IDE powers) in Vim ... and now in Emacs.

Starting with the second use case, the normal find-file command needs exact paths. I tried find-name-dired and project-find-file as alternatives, which worked (at least after pointing Emacs at the location of a real "find" executable, not that sad excuse that is the find.exe that comes with Windows). I was not completely satisfied however and made a mental note to try ivy and counsel at a later date. I also quickly tried ido and icomplete that come with Emacs, but both modes were visually far to busy for me.

The first use case had a simple solution without any worries: vc-git-grep works exactly as I want it to. I use it a lot.

Saturday, 2020-10-24

On that Saturday, I wrote my first blog article with Emacs instead of Vim. I met no problems here, quite the opposite: Not only could Emacs replace everything I used from Vim for the articles easily, I also gained fill-paragraph to reflow the words in a paragraph after rewording it multiple times. I never cared enough to seek for a solution for that little "problem", but suddenly having a little tool to solve it is always welcome.

While working on the article, I had the opportunity to work more with eshell. While doing so, I noticed that I tried to start Vim to edit single files multiple times. Muscle memory is amusing - here I am working in a shell inside of a very capable text editor, starting another editor! I did not edit these files with Vim but reopened them in Emacs directly, of course.

I also used more of dired, which is really growing on me. On most of my systems, I never have any urge to install a file manager and instead just manage my files via the shell, but dired is nice and still quite efficient. I also like that together with tramp mode ("transparent remote access, multiple protocols"), I can use my local Emacs instance with all its customizations not only to edit remote files, but also manage files and directories of remote servers via dired.

I accumulated many buffers during this editing session and was delighted to find that with list-buffers, there was not only a nice overview but also a managing tool that works in the same way as dired. Inside a textual buffer, I could find and mark all buffers I was not going to use anymore, and delete them. This is another upside over Vim, where I deleted my buffers by giving numeric ranges to the corresponding command. This always got inconvenient when I wanted to remove multiple ranges.

Monday, 2020-10-26

On Monday, I added two more tools to my Emacs utility belt that help with editing multiple text regions together. My Vim work flow for that where mostly substitution commands, which, when combined with grep and cdo/cfdo, are very productive for making project-wide changes.

The first Emacs tool for that is named "occur", bound to M-s o. You can use it together with a regular expression and it creates a new buffer with all matches it found in your current buffer. The results look like this:

2 matches for "Monday" in buffer: 0012-learning-emacs.blog
162:!S Monday, 2020-10-26
163:On Monday, I added two more tools to my Emacs utility belt that help with

That does not sound very special, does it? Just a normal search that any editor should be capable of, right? But if you press 'e' inside of this buffer, you switch to editing mode. This offers you a way to work with these lines while changing the original document. You can use all your standard editing tools with it.

You can also use occur to extract just specific pieces of information from your buffer, without distracting context information. Together with capturing groups inside of your regular expression, you can even transform the results. This makes occur not only a nice and fast editing tool, but also superb for data extraction.

As an example, when I use this regular expression on my init.el together with occur:

set-key.*(kbd "\([^"]+\)".*'\([^)]+\)

and specify that I want this format as a result:

\2: \1

I get this pretty overview over all my own key bindings:

swiper-isearch: C-c s
counsel-git: C-c f
ace-jump-mode: C-c SPC
er/expand-region: C-c x
er/contract-region: C-c X
magit-status: C-c g

If you are a regex ninja, you will love occur!

While occur is great and everything, it only works on a single buffer. To fill that hole, I installed the wgrep package. This adds an edit mode to any grep result buffer. I can use it with vc-git-grep to search something in my repository (restricting to single file types and subdirectories as needed), switch to wgrep-mode and again edit the results directly inside of the results buffer. When I am finished, the files themselves are also changed. This way, I can do project-wide changes that don't need to be uniform. I can use a simple replace-string on everything, but I don't need to.

I never knew I needed wgrep in my life. But now that I know about it, I have to say that it is a real killer feature.

Tuesday, 2020-10-27

After starting with wgrep, I decided that Tuesday would be a good day to install some other packages I had read about and alluded to on the days before.

The first problem I needed to solve was an easy way to open files inside my repository without knowing the path. Preferably, I want a fuzzy search. I installed counsel for this. The command I wanted from counsel was counsel-git, which uses "git ls-files" to list all files in my repository. I can then narrow down on the file I want by typing parts of the file name.

As a free add-on, I also got ivy and swiper by installing counsel. Ivy is the module that takes the list of possible entries and allows the narrowing down behind counsel. I activated ivy-mode which enables ivy for built in functionality like opening files or switching buffers. This is not essential to me, but nice to have. I use swiper-isearch as a better incremental search. It offers a fuzzy search and also a preview of not only the next one but multiple occurrences of my search term.

The next packages I installed where ace-jump-mode and expand-region. I see them as replacements for the Vim motions I used most often. I can use ace-jump-mode to quickly jump to any character I see, which is even more powerful than the "f" command in Vim. With expand-region, I can mark regions intelligently. When my cursor is inside of a word in a quoted string inside of a HTML tag, it can swiftly select the word, the whole string, the contents of the tag or the whole tag. Your current mode decides which kind of regions expand-region will recognize.

As a last package, I installed magit. I played with it during my Spacemacs experiments and found it likable. My use of git is via the shell most of the time - gitk and git gui are the only GUIs I ever use with it. But magit is a git front-end that is not cumbersome to use and does not take the control from me. Many of my colleagues don't even know about the reflog, even though we have been using git for many years now ...

Conclusion (so far)


Since these first days, I have slowly integrated more Emacs in my daily routine. I watched videos on YouTube about it, read blogs and even an e-Book (Learning GNU Emacs: A Guide to Unix Text Processing) that I bought many years ago but had not read very much. And I am very satisfied with what I have.

I still miss Vim, of course, but learning a new editor is also very rewarding. And to me, it is always fun to play with new toys and learn new stuff. I definitely think that Emacs is more powerful, but it is also heavier than Vim is. I also believe that using Emacs without the GUI is less fun - when I tried, I could not use Alt as my meta key. Vim is easier that way.

At work, I wrote some simple lisp commands that use magit-status, counsel-git or eshell within specific directories, and enjoyed being able to just improve my tool and refactoring my own functions in a real programming language. That reminds me, I should work with lisp more again - it is such a lovely language.

Should you give Emacs a try? Absolutely! Even if you don't like it, it is still very fascinating and eye-opening. If you prefer Vim, that is okay. If you know neither Emacs nor Vim, you should try to work with both for some weeks. No, they are no IDEs, but they are also a game changer when you come from Notepad++ or similar editors.

My .emacs.d/init.el

As a bonus, here is my current (private) init.el.

;; MELPA
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)

;; ivy, swiper, counsel
(ivy-mode 1)
(global-set-key (kbd "C-c s") 'swiper-isearch)
(global-set-key (kbd "C-c f") 'counsel-git)

;; ace-jump-mode
(global-set-key (kbd "C-c SPC") 'ace-jump-mode)

;; expand-region
(global-set-key (kbd "C-c x") 'er/expand-region)
(global-set-key (kbd "C-c X") 'er/contract-region)

;; magit
(global-set-key (kbd "C-c g") 'magit-status)