Emacs Reference
My cheat sheet for emacs covering macOS installation, common keyboard shortcuts, and usage of dired, web-mode, and magit.
Contents
Installation
For MacOS, I download the appropriate build from Emacs For Mac OS X: Releases, Pretests & Nightlies.
General
Note: this document’s key chords are represented in emacs’ short-form style where a modifier key starts and a normal key follows. When a normal key is capitalized it implies using ⇧ Shift.
Modifier key / abbreviations legend:
|
|
C- |
⌃ Control + |
M- |
⌥ Option + |
s- |
⌘ Command + |
S- |
⇧ Shift + |
DOWN |
↓ |
UP |
↑ |
LEFT |
← |
RIGHT |
→ |
DEL |
⌫ Backspace |
ESC |
⎋ Esc |
Commands
|
|
C-f |
forward one character |
C-b |
backward one character |
M-f |
forward one word |
M-b |
backward one word |
M-e |
forward one sentence |
M-a |
backward one sentence |
C-e |
move to end of line |
C-a |
move to beginning of line |
M-m |
back-to-indentation |
C-_ |
undo |
C-d |
delete one character |
M-d |
delete one word |
C-x o |
other-window |
C-x ^ |
enlarge-window (make taller) |
C-x { |
shrink-window-horizontally (make narrower) |
C-x } |
enlarge-window-horizontally (make wider) |
C-x 0 |
delete-window |
C-x 1 |
delete-other-windows |
C-x + |
balance-windows (distribute width and height to fit) |
C-l |
scroll window so that current line is at middle, top, or bottom |
M-r |
position cursor according to recenter-positions |
C-k |
kill-line from point to end of line |
C-S-DEL |
kill-whole-line |
C-y |
yank (aka paste) |
M-y |
yank-pop to select different killed text from kill ring |
M-g g |
goto line |
C-c C-w |
toggle whitespace (web-mode only! web-mode-whitespaces-show ) |
s-=, and then follow prompts |
adjust text scale (zoom in / zoom out / zoom text / increase font size) |
M-; |
comment / uncomment |
M-x load-file |
load file (use to reload configuration) |
C-x C-e |
evaluate expression |
M-| |
execute shell command |
C-g |
quit; toggle undo / redo |
C-h l |
display last lossage-size characters typed ( view-lossage ) |
C-n |
move down one screen line (next-line ) |
C-p |
move up one screen line (previous-line ) |
C-v |
scroll forward; page down |
M-v |
scroll backward; page up |
C-SPC |
set mark and activate region ( set-mark-command ) |
C-u C-SPC |
move to previous mark (jump back to previous position) |
C-x C-x |
exchange-point-and-mark |
M-= |
count-words-region |
C-q C-j |
newline (useful in minibuffer) |
M-x rename-buffer |
rename buffer |
M-x rename-uniquely |
rename buffer uniquely (appends digit) |
s-+ |
zoom in / increase font size |
s-- |
zoom out / increase font size |
C-x C-v |
find alternate file |
M-x toggle-truncate-lines |
toggle truncate lines / toggle line wrap / disable line wrap |
C-u 1 M-x FUNCTION |
add a prefix argument to FUNCTION |
C-q CHARACTER |
quote CHARACTER |
C-o |
insert a blank line after the cursor (open-line ) |
C-x C-o |
delete all but one of many consecutive blank lines (delete-blank-lines ) |
C-x n n |
narrow-to-region |
C-x n w |
widen |
C-s |
isearch-forward |
C-r |
isearch-backward |
C-s C-s / C-r C-r |
repeat last search |
Isearch (Incremental Search)
|
|
C-h C-h |
isearch-help-for-help |
C-g |
isearch-abort ; will back out any failing search string to last matched |
M-n |
isearch-ring-advance |
M-p |
isearch-ring-retreat |
M-e |
isearch-edit-string |
C-w |
isearch-yank-word-or-char appends the next character or word at point to the search string |
C-q |
isearch-quote-char ; useful for non-ascii characters |
Rectangles
|
|
C-x SPC |
rectangle-mark-mode |
C-x r k |
kill-rectangle |
C-x r M-w |
copy-rectangle-as-kill |
C-x r d |
delete-rectangle |
C-x r y |
yank-rectangle |
C-x r o |
open-rectangle (moves contents to the right) |
C-x r c |
clear-rectangle |
C-x C-x |
rectangle-exchange-point-and-mark |
Common Operations
n Column Layout
|
|
C-x 3 |
split vertically (repeat n - 1 times) |
C-x + |
balance-windows (distribute width and height to fit) |
Frame Management
On Mac OS, a new frame will be created using native windowing.
|
|
C-x 5 2 |
create new frame |
C-x 5 0 |
delete selected frame |
Figuring Out What Went Wrong
Sometimes mistyped key combinations result in unexpected behavior. To help figure out what went wrong, consider:
- C-h l, or
view-lossage
, which shows the last 300 characters typed
list-command-history
, which shows every command involving the minibuffer
- an add-on like
command-log-mode
ansi-term
ansi-term
runs in character mode
by default, making the buffer read-only. Switching to line mode
allows copy and pasting to work more naturally.
|
|
C-c C-j |
enter line mode |
C-c C-k |
enter character mode |
C-x x r |
rename-buffer |
Spell Check
Use M-x ispell-buffer
to run a spell check on the selected buffer.
Reload init.el
and apply changes to open buffers
|
|
|
make modifications to init.el |
M-x load-file |
reload file |
M-x ibuffer |
open ibuffer |
/ f |
(optional) filter buffers by filename regexp |
m with cursor on [ Default ] |
(optional) mark all filtered buffers |
V |
revert all buffers (ensure saved!) |
Remove Carriage Returns (^M) / Set file-coding-system
|
|
|
open buffer |
C-x-RET-f |
set-buffer-file-coding-system |
|
select utf-8-unix or other appropriate value |
|
save buffer |
This emacs.stackexchange.com answer explaining line endings is very helpful.
edit file as root
Prepend /sudo::
before a path, like when finding a file.
Record Keyboard Macro / Run Keyboard Macro
|
|
C-x ( |
start recording |
|
perform the keystrokes / operations |
C-x ) |
end recording |
M-0 C-x e |
repeat macro until an error |
C-x C-k n |
name the macro / save the macro |
C-u 3 M-x NAME |
repeatedly execute macro NAME 3 times |
open init.el and run: M-x insert-kbd-macro |
save the macro for the future |
C-x C-k e |
edit macro kbd-edit-macro |
Notes:
- macros are not scoped to a specific buffer—they perform keystrokes just as you would
- error “terminated by a command ringing the bell” likely means a command went wrong during the running of the macro
Byte Recompile / Rebuild Packages for Emacs 28.4
|
|
find . -name "*.elc" -type f -delete |
delete all compiled elisp files |
M-: |
eval |
(byte-recompile-directory package-user-dir 0 'force) |
byte recompile all packages |
Scroll / Advance by Half a Page
|
|
M-r |
position cursor according to recenter-positions |
C-l C-l |
scroll window so that the current line is at the top |
Documentation Lookup / Getting Help
Commands
|
|
C-h k |
describe-key ; displays documentation for the function invoked by the key presses (defaults to current buffer) |
C-h f |
describe-function ; displays documentation for the passed function |
C-h v |
describe-variable ; displays documentation for the passed variable |
C-h e |
view-echo-area-messages ; displays the *Messages* buffer |
C-h a |
apropos-command PATTERN ; shows commands that match PATTERN |
C-h i |
info ; enter Info, the documentation browser |
C-h r |
info-emacs-manual ; displays the Emacs manual in Info |
C-h m |
describe-mode ; displays documentation of current major and minor modes |
C-h b |
describe-bindings ; displays a buffer showing a list of all defined keys, and their definitions |
C-h t |
help-with-tutorial |
C-h C-f |
view-emacs-FAQ |
C-h w COMMAND |
where-is ; show which keys run COMMAND |
C-h o |
describe-symbol ; displays documentation for the passed symbol |
M-x man |
runs the man program, prompting for a topic to search for |
describe-keymap KEYMAP |
describes the key bindings in KEYMAP |
Help Mode
|
|
SPC |
scroll down; navigate to next node if at bottom (regardless of level) |
DEL |
scroll up; navigate to previous node if at top (regardless of level) |
PageDown |
scroll down |
PageUp |
scroll up |
↹ Tab |
move cursor to next cross reference or menu item |
Info
General
|
|
q |
quit |
? |
show Info Help |
h |
invoke the Info tutorial |
Navigating Node Trees
|
|
n |
next node (at level) |
p |
previous node (at level) |
] |
next node (regardless of level) |
[ |
previous node (regardless of level) |
u |
up |
t |
top |
m |
pick menu item |
l |
last node in history (i.e. browser back button) |
r |
revisit node in history (i.e. browser forward button) |
L |
view history |
d |
directory |
f |
follow a cross reference |
↹ Tab |
move cursor to next cross reference or menu item |
1...9 |
navigate to the ith menu item |
g |
go to node by name |
s |
search |
i |
pick index item |
I |
search virtual index item |
M-n |
create a new independent Info buffer |
C-u m or C-u g |
create a new independent Info buffer |
Scrolling Nodes
|
|
SPC |
scroll down; navigate to next node if at bottom (regardless of level) |
DEL |
scroll up; navigate to previous node if at top (regardless of level) |
PageDown |
scroll down |
PageUp |
scroll up |
e |
scroll to end |
b |
scroll to beginning |
Frequently Asked Questions (FAQ)
Why are some asterisks in menu items colored differently than their peers?
These are the 3rd, 6th, and 9th items of a menu list and allow for visual distinction for easy access via their corresponding numeric keys.
From 2.4 ‘1’–‘9’ choose a menu subtopic by its number of the Info manual:
If your display supports multiple fonts, colors or underlining, and you are using Emacs’s Info mode to read Info files, the third, sixth and ninth menu items have a ‘*’ that stands out, either in color or in some other attribute, such as underline; this makes it easy to see at a glance which number to use for an item.
Searching and Replacement
isearch
Commands
|
|
M-c |
toggle case sensitivity |
regexes
For use with replace-regexp
.
Replace blank lines:
^[[:space:]]*^J
Advanced Features
dired
Summary
dired
is a mode for editing directory listings. It takes the output of the system’s GNU ls
command (or, if not available, emulation through ls-lisp.el
) and presents it in a read-only buffer for interaction. Customization is available through hooks listed in its *Help*
buffer.
Commands
|
|
C-x d |
enter dired buffer |
h |
help |
? |
summary |
a |
visit selection, killing the dired buffer; directories are visited in a new dired buffer |
f |
visit selection, keeping the dired buffer; directories are visited in a new dired buffer |
g |
read all currently expanded directories again; refresh |
m |
mark |
u |
unmark |
U |
unmark all |
Q |
dired-do-find-regexp-and-replace |
C |
copy |
R |
rename |
d |
mark for deletion |
D |
delete |
S |
symlink |
Common Operations
Bulk Edit Directoy
|
|
C-x d |
enter dired buffer |
C-x C-q |
enter editing mode |
|
perform edits |
C-c C-c |
apply changes |
C-c ESC |
or cancel |
Find and Replace Text
|
|
C-x d |
enter dired buffer |
m |
mark files to search |
Q |
run find and replace on marked files |
|
entire regexp and replacement |
? |
choose whether to replace / exit / do something else |
Resources
ibuffer
Mode for listing, sorting, filtering, and managing open buffers:
|
|
M-x ibuffer |
enter ibuffer |
? |
display help |
m |
mark buffer at point |
u |
unmark buffer at point |
V |
revert all marked buffers |
U |
unmark all marked buffers |
/ f |
filter buffers by filename regexp |
/ / |
remove all filtering currently in effect (remove all filters) |
ido
Frequently Asked Questions (FAQs)
How do I use ido to open multiple files at once?
I have not found a way to do so. Here is what I have found to work, using helm
and helm-projectile
:
- M-x helm-projectile
- typed some-string-to-match-on
- selected all via M-a
- opened via ↵ Enter
Packages
command-log-mode
command-log-mode is an add-on that makes it easy to show command and event history.
Commands
|
|
C-c o |
toggle the log window |
geiser-guile
|
|
C-c C-z |
start REPL |
M-x geiser-restart-repl |
restart REPL |
,q |
quit REPL |
C-x C-e |
geiser-eval-last-sexp |
C-u C-x C-e |
evaluate last sexp and insert result at point |
C-M-x |
geiser-eval-definition |
C-c M-e |
geiser-eval-definition-and-go |
C-c C-r |
geiser-eval-region |
C-c M-r |
geiser-eval-region-and-go |
C-c C-b |
geiser-eval-buffer |
C-c M-b |
geiser-eval-buffer-and-go |
Helpful links:
helm
Helpful links
js-mode
|
|
M-x js-jsx-enable |
enable JSX support |
More JSX info in this StackExchange answer.
lsp-mode
LSP Mode - LSP support for Emacs
Commands
|
|
s-l r r |
Rename the symbol (and all references to it). |
s-l g g |
Find definitions of the symbol under point. Jump to definition. |
s-l g r |
Find references of the symbol under point. |
s-l r o |
Perform the source.organizeImports code action, if available. |
s-l w r |
lsp-workspace-restart - restart the workspace WORKSPACE and the language server associated with it |
M-x lsp-describe-session |
Describe session; shows project roots |
s-l F r |
lsp-workspace-folders-remove - remove folders from workspace |
M-x lsp-workspace-folders-add |
Add folders to workspace |
Full list of keybindings
Troubleshooting
lsp-mode not reading tsconfig.json
- check if M-x lsp-describe-session makes sense
- remove folders via M-x lsp-workspace-folders-remove
- close all project files
- reopen file and input I to interactively choose project root
gopls errors
Try upgrading to the latest gopls:
go install golang.org/x/tools/gopls@latest
Configuration
GitHub code search results for Go configuration
magit
Official magit documentation
Commands
General
|
|
C-x g |
open magit-popup |
M-x magit-init |
Initialize a new repository |
C-u C-x g |
Choose repository |
Within magit-popup
|
|
b |
branch ( magit-branch ) |
f |
fetch ( magit-fetch ) |
m |
merge ( magit-merge ) |
F |
pull ( magit-pull ) |
P |
push ( magit-push ) |
o |
submodule ( magit-submodule) |
y |
list branches ( magit-show-refs ) |
Common Operations
Add Remote Origin
|
|
C-x g |
open magit-popup |
M |
open magit-remote-popup |
a |
select ‘add’ |
origin |
add name |
git@example.com:path/to/repo.git |
add repository address |
Cloning a Repository
|
|
C-x g |
open magit-popup |
C |
invoke magit-clone |
Commit Message Editing
|
|
C-c C-c |
Finish editing session and create commit |
C-c C-k |
Cancel editing session and cancel commit |
Tagging
|
|
t |
run magit-tag |
t r |
create a new release tag |
P t |
push all tags |
Cloning a Repository at Tag
|
|
|
clone the repository |
|
open a file |
C-x g |
open magit-popup |
b b |
use magit-checkout |
|
enter tag name |
Diffing Between Two Commits
|
|
l l |
get the sha values you wish to diff (e.g. through inspecting the log) |
d |
open magit-diff |
|
specify options, like limiting to specific file |
r |
specify range (e.g. HEAD..8637c28 ) |
Restoring file(s) from a commit
Note: I do not yet know how to restore an entire directory at once—workaround is just to restore each file one by one.
|
|
|
gather the SHA1 or ref you wish to restore from |
X |
open magit-reset |
f |
select a file |
|
enter commit SHA1 or tag, followed by filepath |
Frequently Asked Questions (FAQs)
What is the difference between upstream and pushRemote?
Assuming:
- a local branch topic tracking origin/topic
- topic was branched from origin/main
- topic is planned to be merged into origin/main when work is complete
we use the following terminology:
- upstream is where topic will eventually end up: origin/main
- pushRemote is where in-progress work on topic should go: origin/topic
This is a semantic distinction that helps organize development: if upstream and pushRemote are always the same there is no need to set both. My personal preference is to always configure pushRemote because the keybindings feel more natural.
Read The Two Remotes from the official documentation.
What is a release tag?
I do not exactly know, but reading the tagging docs indicates that it is a normal tag that magit runs through magit-release-tag-regexp to ensure a consistent numbering scheme.
markdown-mode
Commands
|
|
C-s S-DOWN |
insert a row above the current row |
Official Documentation
multiple-cursors.el
|
|
M-x mc/mark-all-in-region |
prompt for a string to match in region |
Org
Resources
prettier-js
Notes
- displays as Prettier despite being named prettier-js
- is a minor-mode
Commands
|
|
M-x prettier-js |
run prettier on current file |
Resources
projectile
Commands
|
|
s-p p |
open project |
s-p q |
switch project |
s-f |
find file in project |
M-x projectile-discover-projects-in-directory |
discover projects in directory |
M-x projectile-discover-projects-in-search-path |
discover projects in search path (path specified via config) |
M-x projectile-cleanup-known-projects |
remove known projects that don’t exist anymore |
M-x projectile-clear-known-projects |
clear known projects |
M-x projectile-invalidate-cache |
clear cache |
M-x projectile-kill-buffers |
close all buffers associated with a project |
Problems and Solutions
problem |
solution |
deleted / removed file still being found |
M-x projectile-invalidate-cache |
grepped-for string not being found |
ensure that all files are tracked by git |
deleted project still showing up in project switcher |
M-x projectile-cleanup-known-projects |
old / irrelevant / no longer needed project still showing up in the project switcher |
option 1: (completely removes all projects and starts again from scratch) M-x projectile-clear-known-projects |
|
option 2: M-x projectile-remove-known-project |
|
option 3: (if you are currently visiting a buffer within the project) M-x projectile-remove-current-project-from-known-projects |
Resources
scheme-mode
|
|
C-x C-e |
evaluate expression |
C-c C-l |
load file |
sqlformat
Official purcell/sqlformat GitHub repo.
Commands
|
|
M-x sqlformat-on-save-mode |
disable / enable automatic format on save |
web-mode
Commands
|
|
C-c C-e i |
insert HTML element |
C-c C-s |
insert snippet |
C-c C-f |
fold or unfold |
M-; |
insert HTML comment |
Resources
yasnippet
Commands
|
|
M-x yas-new-snippet |
create new snippet |
M-x yas-recompile-all |
recompile all snippets |
M-x yas-reload-all |
reload all snippets |
Selected Authoring Functions
Selected Interactive Functions
|
|
yas-reload-all |
reloads all snippets and clears any miscreated snippets |
Examples
A snippet file named now
that returns a double-quoted and formatted time:
# -*- mode: snippet -*-
# name: now
# key: now
# --
"`(format-time-string "%F @ %R %z")`"
Frequently Asked Questions (FAQs)
I restarted emacs and snippets no longer reflect the changes I made last session but are present in the snippet file—what gives?
It is possible emacs is reading a stale compiled snippets file. The fix is to M-x yas-recompile-all and M-x yas-reload-all.
Resources
Package Management
For use with MELPA or others.
Commands
|
|
M-x list-packages |
list packages |
M-x package-refresh-contents |
refresh contents |
Custom Behavior
Specific to my init.el:
|
|
escape-html |
HTML escapes the text in region |
unescape-html |
HTML unescapes the text in region |
M-p |
move line of text up / move text up / move line up |
M-n |
move line of text down / move text down / move line down |
C-c t |
toggle typopunct-mode (for curly quotes and apostrophes) |
Emacs Lisp (elisp)
elisp Formatting
Times and Dates
Format strings, for use with format-time-string
:
|
|
%F |
the ISO 8601 date format: 2006-01-02 |
%R |
synonym for %H:%M : 15:04 |
Examples:
(format-time-string "%F @ %R %z" (date-to-time "02 Jan 06 15:04 MST") "MST")
"2006-01-02 @ 15:04 -0700"
(format-time-string "%Y-W%W %a %b %d" (date-to-time "02 Jan 06 15:04 MST") "MST")
"2006-W01 Mon Jan 02"
Frequently Asked Questions (FAQs)
How do I add emacs to Automation permissions under Privacy & Security?
Use osascript
from within emacs to request the permission:
- M-x shell-command
- osascript -e 'tell application "System Events" to tell appearance preferences to return dark mode'
- allow the permission
- restart emacs
Emacs Terminology
- binding
- mapping a key to a command
- buffer
- the text or other graphics you are editing or viewing
- buffer, current buffer
- buffer displayed in the selected window
- buffer, indirect buffer
- a buffer that shares the contents of another base buffer
- control characters
- definition todo. such as RET, TAB, DEL, ESC, F1, Home, and LEFT
- delete / deleting / deletion
- erasing text and not saving it in the kill ring
- echo area
- (area at the bottom of the frame) where informative messages are displayed and where you enter information when Emacs asks for it
- echoing
- displaying the characters of a multi-character command as you type
- face
- how text is displayed
- follow-mode
- minor mode that makes two windows, both sharing the same buffer, scroll as a single tall virtual window
- font lock mode
- a minor mode which assigns faces to the text in the buffer; the buffer's major mode tells Font Lock mode which text to fontify (e.g. a programming language mode telling which text are comments or function names).
- frame
- a graphical window or terminal screen occupied by Emacs
-
refers to the MacOS window that emacs is running in
- graphic character
- a character that can be typed by pressing the associated key
- input events
- keyboard and mouse presses
- key sequence, key, key chord
- a sequence of input events that is meaningful as a unit
- key, complete key
- a key sequence that invokes a command
- key, prefix key
- a key sequence that does not itself invoke a command
- keymap
- the bindings between keys and commands
- kill / killing
- erasing text and copying it into the kill ring; aka cutting
- minibuffer
- special-purpose buffer where emacs reads compilicated arguments (file names, buffer names, command names, lisp expressions, etc)
- mode line
- the last line of the window ... (that) displays various information about what is going on in the buffer, such as whether there are unsaved changes, the editing modes that are in use, the current line number, and so forth
- modifier keys
- keys like Control and Meta that change the bahvior of other keys
- narrowing
- editing a buffer is restricted to only a portion of its text; focusing in on some portion of the buffer, making the rest temporarily inaccessible
- numeric argument / prefix argument
- typed before a command
- point
- the cursor in the selected window (which) shows the location where most editing commands take effect
- regexp
- regular expression
- region
- the text between point and the mark
- register
- compartments where you can save text, rectangles, positions, and other things for later use
- ring, kill ring
- cyclical area that stores killed text; visualizable as blocks of text arranged into a ring, accessible in cyclic order
- scrollbar
- UI element within the window on graphical displays that allows scrolling of the buffer
- tool bar
- a row of icons (below the menu bar) that perform editing commands when you click on them
- visit
- read a file and prepare a buffer containing a copy of the file's contents
- widening
- canceling narrowing, making the entire buffer once again accessible
- window
- the main area of the frame, below the tool bar (if one exists) and above the echo area
- yank / yanking
- bringing text from the kill ring back into the buffer; aka pasting; reinserting text previously killed
Resources