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.
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)