This is my attempt to learn to use the glorious GNU program, that is GNU Emacs.
I am a vim enthusiast, so I definitely have a bias towards it and will compare Emacs with vim in my subconscious.
Installation
At the time of writing this document, I'm using macOS Sequoia 15.5 on a Macbook Pro M4 and Emacs version 30.1, so here is some installation step specifically for this machine.
There are several options that we can choose to use Emacs on macOS:
- https://emacsformacosx.com/ - This is the simplest way to install Emacs on macOS system, just regular drag and drop to Applications folder and it's done.
- Homebrew emacs - Install Emacs using homebrew.
- emacs-plus - This is another homebrew package but I noticed a lot of people recommended this if we want a more feature complete Emacs on macOS.
I tried all of them but I don't see any major difference because I'm just getting started and have no idea of what I'm missing or not. So if we're just getting started, I believe it is safe to use any of them.
NOTE: when I install emacs-plus, it builds emacs from source and I noticed the spike of CPU usage on my machine, it was so intense it is the first time (the only time?) since I bought the machine that the fan start to spin real hard I started to worry. The build finished about 30 minutes or so.
Getting Started
Emacs provide a quick guided tutorial similar to vimtutor that we can access by pressing C-h t (that is Control + h then t).
And it has a very extensive built-in user manual that we can access by pressing C-h r.
For a quick reference there is also C-h ?.
Most (all?) of the keybinding on emacs are translated to Emacs Lisp function calls. For example pressing C-f and C-b will invoke forward-char and backward-char function respectively. We can also run the functions manually by using M-x (that is Meta + x or Alt + x) from which we can enter the function name to call.
M-x is different than vim command mode, because we cannot call command/function along with its arguments in one go but instead do it in a more interactive way, i.e. enter function name, then prompt us with arguments if needed.
For example, to change the theme, the expession in Emacs Lisp is (load-theme 'theme-name). Using M-x it is two step, first enter M-x load-theme RET then theme-name RET.
Emacs provide a way to directly evaluate any expression using M-:. Again, this is also different than vim command mode because it is more like a REPL or lisp expression evaluator.
Configuration
Emacs read configuration from multiple places.
Some that I know are ~/.emacs, ~/.emacs.d/init.el, ~/.config/emacs/init.el.
The configuration is written in Emacs Lisp.
To set an option variable we use setq.
; Allow scroll to top/bottom of a buffer
(setq scroll-error-top-bottom t)
To check out help file of a variable we can use C-h v then enter the variable name, or if the cursor is on top of a variable we can press C-h v RET.
Some of the configuration can be set by calling functions.
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(global-hl-line-mode 1)
Similarly, to check out help file of a function we can use C-h f then enter the variable name, or if the cursor is on top of a variable we can press C-h f RET.
Packages
Emacs provide a package manager called package.el. This module provide functions to manage Emacs packages interactively.
By default Emacs will try to download packages from gnu and nongnu repository, specified in package-archives variable.
We can add more repository to download packages from, for example MELPA is a popular one.
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)
We call call package-refresh-contents to re-index available packages.
Installing Package
To install a package, we can browse available packages using list-packages then use the interactive menu from there to install each package.
We can also specify it in our config file by calling the package-install manually. But we also need to check if they're not installed already, using package-installed-p function.
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)
(unless package-archive-contents
(package-refresh-contents))
(dolist (pkg '(spacemacs-theme evil magit))
(unless (package-installed-p pkg)
(package-install pkg)))
;; theme
(load-theme 'spacemacs-dark t)
;; evil mode
(setq evil-want-C-u-scroll t)
(require 'evil)
(evil-mode 1)
;; magit
(require 'magit)
;; org
(require 'org)
(setq org-agenda-files (directory-files-recursively "~/org" "\\.org$"))
(global-set-key (kbd "C-c a") #'org-agenda)
(global-set-key (kbd "C-c c") #'org-capture)
We can also use the use-package macro to make it tidy.
;; setup packages
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(package-initialize)
(unless package-archive-contents
(package-refresh-contents))
;; bootstrap use-package
(unless (package-installed-p 'use-package)
(package-install 'use-package))
(require 'use-package)
(setq use-package-always-ensure t)
;; themes and packages
(use-package spacemacs-theme
:config
(load-theme 'spacemacs-dark t))
(use-package evil
:init
(setq evil-want-C-u-scroll t)
:config
(evil-mode 1))
(use-package magit)
(use-package org
:init
(setq org-agenda-files (directory-files-recursively "~/org" "\\.org$"))
:bind (("C-c a" . org-agenda)
("C-c c" . org-capture)))
Packages Quirks
When we install a package, Emacs will modify and add at the end of config file with some "custom" section.
To avoid this, we can set custom-file variable to let emacs modify that file instead.
(setq custom-file "~/.emacs-custom.el")
Other Package Manager
There are other package manager available but I haven't tried any of them.
Appendix
There are also Emacs distro which configure Emacs for us, only two that I'm aware of (there are others) so far.
I have tried to install spacemacs long time ago, but the only thing I can remember is that it was slow as hell, but I'm sure it has changed since then (or not, who knows?).
I have also recently tried to install doom emacs. While it mostly works, I don't like the fact that I don't get the experience of using Emacs because most of the feature feels like magic. This is of course because my lack of experience, and that is why I want to have the real experience.