Emacs Quick Reference

  • emacs

posted on 25 Jan 2023 under category ref

See

Emacs uses its own multibyte char encoding, a superset of the Unicode standard.

Getting Help

<keys> C-h
C-h
    ?
    C-h             help help
    a <topic>       apropos, match command names to word list, org regexp
                    with (u), also show noninteractive functions
    b               desc bindings
    c               echo cmd name for keys
    C <coding>      desc coding system
    d <topic>       cmds or vars whose doc matches topic
    C-d             help debugging emacs
    e               show echo area msg (*Messages* buffer)
    f <fn>          doc on lisp func
    C-f             faq
    h               "HELLO"
    i               info browser
    k               cmd name and doc for key
    l               show last 200 keystrokes and cmds
    m               desc this modes
    n               what's new (prefix to specify version)
    o <sym>         doc of lisp symbol
    p               list package
    P               desc package
    C-q             "quick help" cheat sheet
    r               manual
    s               show current "syntax table"
    t               tutorial
    v <var>         doc on lisp variable
    w <cmd>         whereis, show keys for cmd
    x <cmd>         docs for cmd
    F <cmd>         enter info, goto node for cmd
    K                                       ..keys
    S <sym>                                 ..symbol
    I <method>      desc input method
    .               special text area

Cmd

apropos-*
    user-option
    [local-]variable
    value

Useful Variable

system-configuration-options

Useful Examples:

C-h a <topic>
C-h i d m emacs <ret> i <topic> <ret>       search by topic in info
C-h i d m emacs <ret> s <topic> <ret>       search in text in info

Help Mode

s                   show source
I                   lookup topic in elisp manual
c                   customize
C-c C-c             help for symbol under cursor

Info Mode

b/e                 node begin/end
<ret>/f             follow
<tab>/S-<tab>       next/prev cross-ref or menu
m                   menu by name
g                   node by name
d                   directory node
L                   show history
n/p                 forward/back in pages
r/l                 forward/back in history
</>                 top/final
[/]                 back/forward, considering all nodes flat
^                   up
s/S                 search info by regex case in/sensitively
T                   TOC
C-s, CM-s           Isearch multiple info
i                   jump by index topic
,                   next i match
M-n                 clone to new window

Basic

C-x                 prefix, typical do with windows, files, buffers, etc.
M-x                 prefix to exec extended cmd
C-g                 get out current cmd, or long running process (frozen)
esc-esc-esc         "all purpose" get out
C-x C-c             exit

Start As Server

  • in existing emacs instance: M-x server-start
  • or add (server-start) to .emacs.
  • emacs --daemon
  • emacsclient --alternate-editor=""
  • systemctl --user enable emacs

Mode

Each “major mode” make few cmd behave differently, they are also the name of a extended cmd, which can be used to switch to that mode.

Mode are auto chosen when first visit the file, you can explicitly select a new mode with M-x <mode>. You can then return to the emacs chosen mode by M-x normal-mode.

To change default mode, use Customization, or by adding line like:

(setq-default major-mode 'text-mode)

Every major mode (except Fundamental) defines a “mode hook”, commonly used to enable minor modes:

(add-hook 'text-mode-hook 'flyspell-mode)

Every buffer can have many “minor modes”, some minor modes are global, affects entire editor.

Command

“X (eXtend) Command” comes in two flavors: C-x for “Char eXtend”, followed by one char; M-x for “named cmd eXtend”, followed by long name.

M-x <cmd>           run cmd
M-X                 run cmd relevant to buffer
C-x z               repeat last cmd
C-x <esc> <esc>     repeat last minibuffer cmd

Each buffer has a “default dir”,

pwd
cd

Minibuffer

Everything you type is saved in “minibuffer history list”. Different type of argument(filename, cmd name, etc.) is saved inside separate list.

You can ignore the prompted default path, just start typing / or ~, like:

# ignore local path
Find file: /u2/emacs/src//etc/termcap       # with /
Find file: /u2/emacs/src/~/.emacs           # with ~
# ignore remote path
Find file: /remote/dir///etc/termcap        # with // to ignore remote

You can be in “Recursive editing” if you issue new commands while the previous is still running, the mode line will show ‘[…]’ for each editing level. Remember to exit when you no longer need it.

Inside Minibuffer:

M-n/p,down/up   next/prev item in history
M-r/s           regex search history
C-o             expand minibuffer with newlines
---------------------------------------------------------
CM-c            resume to outer editing level
C-]             abort this editing level
---------------------------------------------------------
TAB             complete, works also when point is not at the end
SPC             complete up to one word
?               list completions
M-up/down       select prev/next item
M-v             focus completion window, See "Completion Mode"

Cmd

top-level       abort all level

Var

completion-style
completion-auto-help
completion-auto-select
read-file-name-completion-ignore-case
----------------------------------------------------------------
icomplete-mode
fido-mode
---------------------------------------
history-delete-duplicates

Completion

“Icomplete Mode” and “Fido (Fake Ido) Mode” show completion entries in a single line.

Completion Mode

q                   quit window, back to minibuffer
z                   quit window and minibuffer
n/p,<tab>/S-<tab>   next/prev item

ICompletion Mode

C-j                 complete first and exit
RET                 nocompletion exit
C-./,               rotate list
M-<tab>             select first, don't exit (convient for descending a dir)
CM-i                force complete

Fido Mode

C-s/r               rotate list
C-k                 kill buffer/file

Universal/Numeric Argument

Command may use it as repeat count, change default behaviors.

C-u <num>           4* times
M-<num>
CM-<num>
<num>

The reason why these all do the same, is to NOT break your TEMPO.

Motion, Scroll

“pages” are delimited by formfeed (displayed as ^L).

“defun” means top level function definition.

“paren” also mean brac, bracket or other delimiters to match pairs.

“sexp” (borrowed from lisp) means any balanced expresesions in a language.

C-b/f           back/forward by char
M-b/f                        ...word
CM-b/f                       ...sexp
C-p/n                        ...line
CM-p/n                       ...paren
C-a/e           beign/end of line
M-a/e                      ..sentence
M-{/}                      ..paragraph
C-x [/]                    ..page
M-</>                      ..buf
CM-a/e                     ..defun
C/M-v           down/up by screen
C-x </>         left/right screen
M-m             first non-space char of this line
CM-<up>         back up one level of indent
CM-u/d          up/down in paren level
---------------------------------------------------------
C-xn            set goal column (affect where C-n/p move to)
---------------------------------------------------------
[N] M-g         goto
    g               line
    c               char pos in buffer
    <tab>           column
    i               defun ("imenu")
---------------------------------------------------------
C-l             recenter
M-r             reposition cursor
CM-l            smart recenter (try to show comments and definition)

Mode

which-function-mode     show func name now inside
subword-mode            CamelCapsAsSeperateWordsWhenMoving
glasses-mode            display extra _ for CamelCaps

Var

imenu-auto-rescan
imenu-sort-function

Cmd

what-page

Editing

Insert

C-x i           insert from other file
C-x x i         insert from other buffer
C-q <num>       quoted insert, next insert will treat "literally", useful
                for inserting constrol chars
-- key translation -------------------------------------------------------
C-x 8 
    <num>       common unicode char
    <           «
    >           »
    +           ±
    C           ©
    R           ®
    P           ¶
    S           §
    T           ™
    Y           ¥
    [           ‘
    ]           ’
    {           “
    }           ”
    x           ×
    <           «
    >           »
    ~=          ≈
    _<num>      ₁
    _<          ≤
    _>          ≥
    ^<num>      ¹
    //          ÷
    /=          ≠

Mode

electric-pair-mode              auto insert pairing parens

Cmd

insert-file-literally
write-region                    inverset of C-x i, copy region to other file

Emoji

C-x 8e 
    +/-/0	zoom in/out/reset
    d		describe
    e/i     insert
    l		list
    r		recent
    s		search

Kill, Delete, Yank

<del> in emacs means <backspace>.

“Killed” text can be reinserted (“yank”), “deleted” cannot (but can be undo). typical cmds that remove just one char or blank lines or spaces do deletion, like DEL or C-d (but given argument, they kill).

By default, emacs expect “sentence” to be ended with two spaces, but can be changed with sentence-end-double-space.

<del>
C-d             del next char
M-d               ..to word end
M-<del>           ..to word begining
C-k             kill to line end 
M-k                ..to sentence end
C-x <del>          ..to sentence begin
C-x C-o            ..blank lines around, leaving one
M-\                ..spaces around
M-<spc>            ..spaces around, leaving one
CM-k               ..sexp
----------------------------------------------------------------
M-^             join up
----------------------------------------------------------------
C-w             region ("cut")
M-w             save region to kill ring ("copy")
C/M-y           yank last/prev kill
M-z             zap (kill) to char
----------------------------------------------------------------
yank-media

Cases

[-N] M-l/u/c    lower/upper/capitalize [prev]next word
C-x C-l/u       lower/upper region

Comments

[u] M-;         dwim: insert or realgin line (or region), or go to start
[u] C-x C-;     toggle line
[u] C-x ;       set column
CM-j,M-j        <ret> and insert and align comment
C-c C-c         add comment delimiter to lines in region

Cmd

uncomment-region

Var

comment-*
    padding
    start
    end
    multi-line
    indent-function

Blank Lines

C-o             insert newline after point but leave point in front
C-j             insert newline without auto-indentation

Transpose

C-t             char
M-t             words
CM-t            sexp
C-x C-t         line
---------------------
transpose-sentences
transpose-paragraphs
transpose-regions

Indent, Alignment

<tab>           indent (insert whitespace, indent whole line or region) by mode
M-i             indent to next stop
C-u <tab>       indent in paren group rigidly
CM-o            split at pos, indent next
CM-q            reindent lines in sexp
C-cq            reindent all defun
CM-\            indent all lines in region
C-x <tab>       indent rigidly, interactively
C-c .           set indent "style" (like "k&r", "gnu" in C)

Cmd

indent-relative
edit-tab-stops
tabify                      space to tab
untabify                    tab to space
align                       align region by "alignment rules"
[u] align-regexp            align by [complex] regexp
align-highlight-rule
align-unhighlight-rule
electric-indent[-local]-mode

Var

indent-tabs-mode
tab-width
tab-always-indent

When using edit-tab-stops, the resulting stops will be extended forever by repeating.

Completion

CM-i,M-<tab>        complete

Cmd

completion-help-at-point        list available completions

Filling, Wrapping, Truncation

“Filling” mean lines breaked (physically) by EOF char. “Wrapping” (in “Visual Line Mode”) only means for display, when not wrapped, then lines are “truncating”.

The “fill prefix’ feature allows paragraphs to be filled so that each line starts with a special string of characters.

In “Auto Fill Mode”, lines break automatically when you type SPC or RET, inserting “adaptive fill prefix”, which will be deduced from the first and/or second line of current paragraph. Note that it does not refill entire paragrah; it breaks lines but not merge lines, hence editing in middle of paragraph can result not being correctly filled, we can call fill commands to fix this.

C-x .               set prefix (affects M-q, M-^, and C-o)
C-x x t             toggle truncation lines
C-x f               set fill column
M-q                 fill paragraph with prefix
<num> M-q           "justify" (insert spaces between words) and re-fill

Cmd

display-fill-column-indicator-mode
auto-fill-mode
fill-region
fill-region-as-paragraph
center-line/paragraph/region

Var

display-fill-column-indicator-column/charactor
fill-column-indicator

Undo, Redo

There is no redo, but undoes are undoable, too.

If you need to get back to a previous buffer state, simply move the cursor, and press C-/ until you find what you want, notice the Mode Bar, where there is no ‘*’, then the buffer is same as last SAVE.

With “Selective undo”, you can undo only in region.

C-/             undo
C-_
C-x u
---------------------------------------------------------
M-%             query replace

Sorting

sort-*
    lines/paragraphs/pages
    fields/numeric-fields
    columns
reverse-region

Hexl (Binary Files)

Insertion in hexl mode always overwrite.

hexl-find-file              open as hex
hexl-mode                   view this in hex
----------------------------------------------------------------
CM-d/o/x                    insert byte with dec/oct/hex
CM-a/e                      move to begin/end of 512-byte page
CM-[/]                                         ..1k-byte..
M-g/j                       goto address in hex/dec
C-cc                        leave hexl, go back to normal

Search, Replace

  • “Incremental search (isearch)”: search begins as you typing.
  • “Nonincremental”: search begin after you press RET.
  • “Word search”: find sequence of words ignoring punctuation inbetween.

By default, searching:

  • Do “lax space matching”: consecutive spaces are treated as one.
  • Ignore the case (“case folding”), unless the search string contains an uppercase letter.
  • But don’t perform “character folding”.
  • Search in invisible text, too.

But replacement commands do NOT use lax space matching by default.

“Occur Mode” is an interactive search mode, it bring all matches in a buffer with context lines around and let you press e and modify matchs one by one.

Start, Exit

Some of those can also be used to toggle mode when already in search session, Hilight-related cmds can be used when exiting search.

C-s/r [<ret>]   [non]isearch forward/reverse
CM-s/r [<ret>]  regex [non]isearch
M-%             query(one by one) replace
CM-%            regex query replace
---------------------------------------------------------
M-s.            isearch this symbol
M-s _           isearch given symbol
M-s w           isearch given word
[N] M-s o       occur [show N context line]
M-s h           hilight:
    ./r/l/p         symbol at point/regex/line/phrase
    u               unhilight (done)
    f/w             lock find/write ??
---------------------------------------------------------
<ret>           exit, leaving pos there
C-g             abort, return starting pos

When Searching

Motion:
    M-s </>         goto first/last match
Search String Editing:
    M-n/p           next/prev in history
    M-e             focus search string for editing
    C-w             yank next char
    CM-w            yank next symbol
    CM-z            yank until given char
    M-s C-e         yank whole line
    CM-d            del next char
    CM-y            append next char
    M-<tab>         complete
Toggle Search Mode:
    M-s <spc>       lax space
    M-s c, M-c      case sentitivity
    M-s i           text visiblility
    M-s r, M-r      regex
    M-s w           word mode
    M-s '           char folding

RET when search string empty launches “nonincremental search”, it’s necessary only if want type a char next.

When editing search string, other editing cmds works, too. Like yank, undo, etc. To search for newline, use C-j.

Cmd

replace-string                          unconditional replace
replace-regexp
---------------------------------------------------------
multi-isearch-buffers[-files][-regexp]
occur                       			M-s o
multi-occur[-in-matching-buffers]		occur in many buffers [regex]
occur-cease-edit                        out of Occur Edit Mode
---------------------------------------------------------
how-many                search and only show match number
flush-lines             search and delete matched lines
keep-lines                              ..nonmatched lines..
kill/copy-matching-lines

Var

search-highlight[-submatches]
search-default-mode
search-upper-case
case-fold-search
isearch-*
    allow-scroll     			scroll won't exit isearch
    allow-motion     			motion ...
    yank-on-move     			extend search string with motion
    hide-immediately
---------------------------------------------------------
replace-*
    [regexp-]lax-whitespace

Regexp Syntax

NOTE: in elisp, you also have to escape the escape character.

Search

NOTE there is no \d, you have to use [0-9] or [:digit:].

.
*
+
?
*?,+?,??            non-greedy
[…], [^…]           alternative chars
	[:ascii:]
	[:alnum:]
	[:alpha:]
	[:blank:]
	[:cntrl:]
	[:digit:]
	[:graph:]
	[:lower:]
	[:multibyte:]
	[:nonascii:]
	[:print:]
	[:punct:]
	[:space:]
	[:unibyte:]
	[:upper:]
	[:word:]
	[:xdigit:]
^
$
\                   escape, also introduce special constructs
-----------------------------------------------------------------------
\|                  alternative expr
\(…\)               grouping
\(?:…\)             shy grouping (dont capture)
\D                  back ref #d
\{m\}               repetition
\{m,n\}
\`                  start of string or buffer
\'                  end of...
\=                  point
\b, \B              word,non-word boundry
\<, \>              start,end of word
\_<, \_>            start,end of symbol (\w or _)
\w,\W               any word,non-word
\scode, \Scode      char whose syntax code is,not code. code can be:
    -                   whitespace
    w                   word(lower,upper,digit,unicode char)
    _                   symbol(word,!,_)
    .                   punct(.,;)
    (,)                 open,close of pairs ((),[],{})
    "                   string block mark(',")
    <,>                 comment boundary
\ccate, \Ccate                 ..catagory is,not cate

Replace

\&                  entire match
\D                  Dth match
\#                  count (from 0) of replements already made
\?                  prompt for manual input
\,                  Lisp expr start, inside it, can use:
    \&                  same as above
    \D                  same, but D can be multiple digits
    \#                  same as \D
    \#&                 reference match as a number
    \#D                 reference match as a number

Examples

Add consecutive numbered strings like ‘ABC00042’ to column 73-80:

M-x replace-regexp <RET> ^.\{0,72\}$ <RET>
\,(format "%-72sABC%05d" \& \#) <RET>

Re Builder

“M-x re-builder” let your construct regex interactively. Best to change reb-re-syntax to string to avoid to much of backslashes, if you use lots of lisp, then better changed it to rx.

C-c
    C-b         change target buffer
    C-c         toggle case
    C-e         enter subexp mode
    <tab>       change syntax
    C-q         quit
    C-r         go prev match
    C-s         go next match
    C-u         force update
    C-w         copy

Cmd

reb-*
    toggle-case
    change-syntax

Occur

Occur Mode

RET         goto occurrence
o           same, in other window
C-o         show this occurrence
e           "occur edit mode"
g           revert buffer, refresh result
n/p         next/prev 
l           recenter
---------------------------------------------------------
M-n/p       goto next/prev (works globally)

Occur-Edit Mode

changes to the *Occur* buffer are applied to origin buffer.

C-c         exit editing and apply changes

Grep

grep                grep regex
lgrep               grep glob pattern
grep-find/find-grep find&grep regex
rgrep               find&grep glob, recursively
zrgrep/rzgrep       find&grep glob, recursively, in gzip file
kill-grep

(An alternative to xref-find-reference and tags-search.)

When greping, use ‘grep’-style regexp (usually single-quoted). You can chain grep together, too.

File

When giving filename, $ can be used to subbstitue env variable, use $$ for literal ‘$’.

If permissioin don’t allow reading the file, we can use ‘su’ or ‘sudo’ methods:

/su::/path/to/file

To prevent special characters in filename, use /: to escape:

/:/foo:/bar                 file bar in dir /foo:
/ssh:baz:/:/foo:/bar        file bar in dir /foo: on host baz

quoting with /: is also a way to enter in minibuffer a filename that contains ‘$’.

The visited file’s buffer named are typicalled the same as file name but with dir name omitted. If specified a dir name, emacs enter “Dired” mode. Emacs can auto uncompress compressed files when visiting, then recompress them when saving. “Tar Mode” is like Dired when visiting archive file like *.tar.

“Revert” a buffer mean reload its content from disk file, but for non-file buffers (such as Dired), reverting means recalculate their contents.

Using “fileset”, we can op on group of files.

“Backup file” are named by appending ‘~’ to filename, there can be many backup files for one file, like eval.c.~1~, eval.c.~2~.

“Auto-save files” are named by wrapping ‘#’ to filename. if auto-save-visited-mode is on, then auto-saving is identical to explicit saving. Upon system crash, you can use M-x recover-file or M-x recover-session to recover from auto-save files.

“Shadow” is a copies of certain files in more than one place – possibly on different machines. “Shadow cluster” is a group of hosts that share directories, so that copying to or from one of them is sufficient to update the file on all of them.

Prefix,keys     desc
-----------------------------------------------------------------------
C-x
    [4/5] C-f   find("visiting") a file [in other window/frame]
                NOTE: can also be used to switch buffers
    C-r         readonly
    C-v         kill this and visit alternate
    C-s         save this, with numarg, also save backup file
    s           save all buffer
    C-q         make writable
    C-w         write file to given path(save as)
    d           list dir (Dired)
    x g         revert
-----------------------------------------------------------------------
[C-u] M-~       mark as not modified, prevent from accidentally saving
C-xs            save buffer

To save buffer to a different file without visiting that file, use C-x h then M-x write-region.

Cmd

find/insert-file-literally              as ASCII without encoding
find-sibling-file
ff-find-related-file
set-file-modes
copy-file/directory
delete-file/directory
rename[-visited]-file
add-name-to-file                        make hard link
make-symbolic-link
move-file-to-trash
set-visited-file-name
---------------------
filesets-add/remove-buffer
filesets-edit
filesets-open/close
filesets-run-cmd

Mode

[global-]auto-revert-[tail]-mode        useful for "tailing" a log file

Var

save-some-buffers-default-predicate
delete-by-moving-to-trash
require-final-newline

Coding System, EOL

C-x RET
    f                   choose for save or revist
    c                   choose for next cmd
    r                   revist this file with

Cmd

recode-region

Dired

Normal dired cmds never consider fiels in hidden subdirectory.

You can select a set of files for display more flexibly by using ‘find’ util.

Listing

(               hide details
g               refresh whole listing
l               refresh subdir listing
i               insert subdir's content
k               kill lines inserted by i
s               toggle alpha/time ordering
$               toggle subdir
C-x q           make editable, into "WDired Mode"
-----------------------------------------------------------------------
find-
    dired       find by given 'find' conditioin
    name-dired  match filename with glob (no quote needed)
    grep-dired  match file content with grep regex
locate
locate-with-filter

Navigate, Search

n/p,C-n/p       next/prev
j               jump
^               parent
-------------------------------------------------------------------------
>/<             next/prev dir
CM-n/p          next/prev dir, ignore level
CM-u/d          up/down
M-G             promt and go
C-u k           remove ...
-------------------------------------------------------------------------
M-s f C-s       isearch only filename
M-s a C-s       isearch
M-s a CS-s      regex isearch

Visit

<ret>/e/f       visit
o               visit in other window and focus
C-o                                     ..no focus
v               view in View Mode

Flagging (for deletion)

d/u             flag/unflag
<del>           move up and unflag
---------------------------------------------------------------------------
#/~/.           all auto-save(#)/backup(~)/numeric backup files
% &             filename matche "dired-garbage-files-regexp"
% d             filename matche regex
---------------------------------------------------------------------------
x               do deletion

Marking. (deletion can also be done with marking)

* m, m          mark
* *             executables
* @             symlinks
* /             dirs (except . and ..)
* s             same subdir level files
* <del>, <del>  move up and unmark
* !, U          unmark all
* ?, M-<del>    unmark by MARKCHAR
* t, t          toggle all
* c
% m, * %        with regex, match filename
% g             with regex, match file's content
----------------------------------------------------------------------------
* n/p, M-{/}    go next/prev marked
* N             show total size

Operate (if prefix arg given, op on next N files; else on marked or signle)

[N] w           copy [relative] filepaths (separated by space)
C               copy
D               delete
R               rename
H               link
S               symlink
Y               relative symlink
M               change perm mod
G                   ...group
O                   ...owner
T                   ...touch
[0] %           [consider absolute path] prompt and do:
    u/l/R           upper/lower/rename
    C               copy
    H               hardlink
    S               symlink
    Y               relative symlink
---------------------------------------------------------
+               create dir
---------------------------------------------------------
P               print
Z               zip, or unzip if already zipped
c               zip to signle archive
:e              encrypt
:d              decrypt
:s              sign
:v              verify
L               load as elisp
B               byte compile
I               info
N               man
=               diff
---------------------------------------------------------
A               regex search in marked files (recur to subdir)
Q                   ..search-replace..

Shell Commands

!/X             run shell
!&/&            run shell async (as if "<cmd>&")

Cmd

dired-compare-directories

Var

dired-listing-switches                      option when listing
dired-isearch-filenames
dired-kill-when-opening-new-dired-buffer

Dired X

Remote File

“TRAMP”: Transparent Remote Access, Multiple Proto.

Remote path syntax:

/method:host:/path/to/file
/method:user@host:/path/to/file
/method:user@host#port:/path/to/file

Buffer

ANY text in emacs window is always part of some buffer.

A “indirect buffer” shares text from its “base buffer”, like symlink between files:

  • It can not visit file, but its base can.
  • It can have different pos, narrowing etc. from base.
  • Kill base kills indirect, too.

One way to use it is to view different views of an outline.

C-x
	C-b             listing
	[4/5] b         switch/create [in other window/frame]
	<left>/<right>  switch prev/next
    C-q             toggle readonly/writable
    x r             change buffer name
    x u             rename uniquely by appending a number
    x i             insert text from another buffer
    k               kill
    4 c             create indirect buffer in other window
C-u M-g g <num>     switch and goto line in other window

In buffer listing like:

CRM Buffer          Size    Mode            File
. * .emacs          3294    Emacs-Lisp      !/.emacs
 %  *Help*           101    Help

’.’ means this is current buffer, “%” means readonly, ‘*’ means modified.

Midnight Mode

Run clean-buffer-list or other funcs in ‘midnight-hook’ once a day.

Cmd

buffer-menu[-other-window]      edit buffer list
ibuffer                         list, Dired like
bs-show                         list, customizable
bs-customize
view-buffer                  	view in View Mode
clean-buffer-list            	kill all unmodified
kill-some-buffers            	ask each for kill
kill-matching-buffers
----------------------------------------------------------------
make-indirect-buffer
clone-indirect-buffer

Var

global-auto-revert-non-file-buffers
uniquify-buffer-name-style

Window, Frame

“Frames” is collection of windows, together with its menus, scroll bars, etc.

When buffer shown in many windows, they can have different regions, but same value for marks.

“Tab line” is per window for showing buffers in window; “Tab Bar” is per frame for switching between window configs.

-- Window ---------------------
C-x
    0           delete this
    1           keep this only
    2           split down
                * with positive numarg, set origin window height
                * with negative numarg, set new window height
    3           split right
    ^/_         taller/shorter
    {/}         narrower/wider
    +           all equal
    o           focus on other
    4 0         del this, kill bf in it
    w 0         del window who showing given buffer
    4           other window:
        b/f/r/d/m/. switch to or create buf/file/readonly/dir/mail/definition
        4           general prefix affect next cmd
        l           general prefix affect next buffer cmd
CM[S]-v         scroll other up[down]
CMS-l           recenter other
-- Frame ---------------------
C-x
    5           frame:
        0           delete
        1           keep only this
        u           undelete
        2/c         create default/as current
        b/f/d/m/./r other frame, see "other window"
        o           select other and raise it
C-z             min("iconify") current frame
M-f10           max
f11             fullscreen

“Speedbar” is a special frame, op on it will act on its associated frame, for managing directories and tags.

Q               delete frame
g               refresh
n/p             next/prev entry
CM-n/p          next/prev list
M-n/p           next/prev restricted
q               close frame
t               toggle updates
C-x b           switch buffer attached frame
CM-n/

Winner Mode

Set winner-dont-bind-my-keys to prevent the following key bindings.

C-c
    left/right          undo last/redo window configuration

Windmove Mode

S-up/down/left/right    select by direction (disable shift selection!)

Cmd

compare-windows
windmove-*
    swap-states*        swap contents with another
speedbar
winner-mode
follow-mode             scroll buf together when it's in many windows
scroll-all-mode         scroll all when scroll one
----------------------------------------------------------------------------
windmove-[delete-]default-keybindings

Var

window-resize-pixelwise
----------------------------------------------------------------------------
winner-boring-buffers[-regexp]  ignore when restore

View

C-x C-+/-/=             incr/decr/reset font size
[N] C-x $               fold ("selective display") [at indent level N]
C-x $                   unfold all
M-=                     show region's lines,sentences,words,char counts
[C-u] C-x =             show char code [describe char]
M-s h
    r <regex>           hilight word with face
    u <regex>           unhilight
    l <regex>           hilight line
    p <phrase>
    .                   hilight sym at pos
    w                   write hilighting regex/face to this point
    f                   extrace from w writen contents
C-x w
    h <regex>
    r <regex>
    l <regex>
    p <phrase>
    .
    b
    i

Mode

scroll-bar-mode
fringe-mode
---------------------
line-number-mode
column-number-mode
hl-line-mode
size-indication-mode

Cmd

what-line
display-line-numbers-mode

Outline, Foldout, Narrowing

“Outline Mode” consider lines begin with * a “heading line”, and other lines “body line”. A heading line with all its following body line is an “entry”, and with all even deeper body an “subtree”.

A common trick is to use indirect buffer to display one outline and one expanded buffer of one file.

The major mode prefix at C-c, minor at C-c @.

<tab>           cycle sub-header visibility
S-<tab>         cycle entire buffer visibility
C-c
    C-c/e       hide/show (expose) entry
    C-d/s       hide/show subtree (not including header)
    C-l/k       hide/show leaves (including subentries)
    C-i         show immediate subheading
    C-t         hide all body
    C-a         show all
    C-q         hide all except top N level of heading lines
    C-o         hide all other
----------------------------------------------------------------
[N] C-c
    C-n/p       goto next/prev visible header
    C-f/b       same, but at the same level
    C-u         up a level

“Narrowing” restrict view to certain region.

C-x nn          to region
C-x nw          widen (visible again)
C-x np          to page
C-x nd          to defun

“Foldout Mode” extends Outline Mode, let you zoom in (show then narrow) and out of subtrees. Since narrowed, global editing actions will only affect text under zoomed-in heading.

[n] C-cz        zoom in this this header's body and [n level of]child 
                subheadings
[-] C-cz              ..body
[0] C-cz              ..whole subtree
----------------------------------------------------------------
[u] C-cx        exit zoom (unfold)

To use this package:

 (with-eval-after-load "outline"
   (require 'foldout))

Cmd

reveal-mode

Var

search-invisible
outline-regexp
outline-default-state

Spell Check

For spell check to work, one of Hunspell, Aspell, Ispell or Enchant must be installed. Spellchecker will look up in standard dictionary and your personal dictionary.

[N] M-$             [continue last] correct
CM-i                complete word
C-.                 same, only in flyspell mode 

When there is “near-misses”, here are valid action:

digit               replace this with option N
SPC                 skip
r                   replace this with given
R                   replace this and do a query-replace
a                   accept, treat it as correct for this session
A                   same, but only for this buffer
i                   insert to private dict file
m                   i, also specify complete info
u                   i, with lowercase
l                   look in dict for other then select one to replace
x                   quit, move point back
q                   quit, kill checker subprocess
C-r                 recursive edit

Cmd

ispell-*
    -buffer/region/message          check and correct
    -comments-and-strings/comment-or-string-at-point
    -change-dictionary
    -kill-ispell                    kill checker subprocess
flyspell-mode                       hilight all misspell (NOTE might slow
                                    down cursor movement)
flyspell-prog-mode                  same, but only for comments and string

Mark, Region

“Mark ring” contains marks per buffer, each buffer has only one mark pos, per buffer marks also are in “global mark ring”. When buffer’s mark is active, we say also the region is active. If “Transient Mark Mode” is enabled (default), region will be hilighted.

Long distance jump cmds(M-<, M->, etc.) will auto set mark.

Region always extends between point and the mark, or pressing “SHIFT” (“shift selection”) when moving.

C-<spc>         point
M-@             end of next word
CM-@            end of next sexp
C-xx            swap point and mark (return to prev pos)
----------------------------------------------------------------
M-h             paragraph
CM-h            defun
C-xp            begin of page, to end
C-x h           all
----------------------------------------------------------------
C-<spc> C-<spc> mark without activating
C-u<spc>        pop and go last mark in buffer
C-x<spc>                           ..in global

Many cmds only operate on active region if there is one, like ‘M-%’.

Var

highlight-nonselected-windows

Rectangles

Useful for editing multicol formate text. Given combination of point and mark can be treated as region or rectangle, depending on the cmd.

killed rectangle is not saved in kill ring, but in special place.

CM-mouse1       drag to create
C-x <spc>       shrink/grow
C-x C-x         cycle point between four corners
C-x r
    k           kill text
    M-w         copy text
    d           delete text
    y           yank last killed text
    o           fill space
    N           insert lineno
    c           clear
    t <str>     replace with str on each line

Cmd

delete-whitespace-rectangle
string-insert-rectangle

Registers, Bookmarks

“Registers” are used to save text, rectangles, positions, etc. for later repeating use. Register has a name made of single char (letter or number).

“Bookmarks” are similar, it record files and pos for jumping. But have long names and persist between sessions.

C-x r
    <spc> R             save pos
    w R                 save window in R
    f R                 save frameset in R
    j R                 jump to R (can be file/buffer/pos/macro/window/frame)
    ---------------------------------------
    s R                 copy region to R
    +                   append to R
    i R                 insert text from R
    ---------------------------------------
    r R                 copy rectangle to R
    r i R               insert rectangle from R
    ---------------------------------------
    n                   store 0
    +                   incr register value by 1
    ---------------------------------------
    m                   set pos as bookmark (prompt for name)
    m BMark             set bookmark named BMark
    M BMark                                 ..., don't overwrite
    b BMark             jump to BMark
    l                   list all
C-u C-x r s R           move region to R (delete from buffer)
C-u C-x r j R           restore window/frame (deleting current)
C-u <num> C-x r n R     save num in R
C-u <step> C-x r + R    incr num in R by step
C-x C-k x R             save last macro in R

Cmd

view/append/prepend-to-register R
---------------------
bookmark-save/load/write/delete/insert-location/insert

Var

register-separator

Fn

set-register

Macro

Macro differ from commands in that they are written in the Emacs command language rather than in Lisp. All macro are saved in a global “macro ring”.

When defining, “current counter (from 0)” can be used to insert a number to buffer that depend on the number of times the macro has been called. There is also a “previous counter” which is the value of the current counter had had last time it was incremented or set.

f3                  start or insert counter (can abort by C-g)
f4                  end or exec
C-g                 quit definition
C-x e               end and exec
C-u f3              re-exec last, then append new keys
C-u C-u f3          append new keys to last without re-exec
[N] C-xk r          exec last on each line in region[or N lines]
[N] C-u C-xka           recounter to last given [N]
C-u C-xka           reset counter to last value
---------------------------------------------------------------------------
C-xkk               call macro at ring head
C-xkn/p             cycle to next(eailer)/prev and show
C-xk d              force redisplay while executing
---------------------------------------------------------------------------
C-xk n              name save last, become command for M-x or key binding
C-xk b              bind last with key
---------------------------------------------------------------------------
C-xke               edit last defined macro
C-xk e              edit given named macro
C-xk l              edit last 300 keystrock lossage as macro
C-xk <spc>          step by step edit while executing

Keybinding C-xk 0 to C-xk 9 and C-xk A to C-xk Z are specically reserved for our macro, so we can use like C-xk b 4 to directly bind to C-xk 4.

To save macros for later session:

  1. Use insert-kbd-macro and save it to file.
  2. In later session, load the file with load-file.

    • If you saved macro in init file, it will be auto loaded.
    • If you specify a prefix arg to insert-kbd-macro, it will also generate key binding code, so the keybinding will be available, too.

When Defining Macros:

C-xki               insert counter to buffer
                    (same as f3, but can be used outside definition)
[N] C-xka           incr counter by given [N]
C-u C-xka           reset counter to last value
C-xkf               set format for inserting counter (default is "%d"),
                    if used outside definition, affect all later definitions
C-x q               query(confirm) at this point when executing
C-u C-x q           enter recursive editing (used both defining and executing)

Examples. Build a number list:

F3 C-a F3 . SPC

Cmd

insert-kbd-macro    insert into buffer a macro definition as lisp code

Var

kmacro-ring-max

Programming

Shell

Shell mode is a derivative of “Comint mode”, a general-purpose mode for communicating with interactive subprocess.

[u] M-!         run sh cmd [output to this buffer]
[u] M-|         run sh cmd with region as input
M-&             run sh cmd async

Cmd

shell       subshell 
term        subshell with full terminal emulation
eshell      run eshell (implemented entirely in Emacs)

Abbrev

“Abbrev Mode” will auto expands an abbrev, after your typed a punctuation. It preserve case: like ‘foo’ to ‘find out otter’, ‘Foo’ to ‘Find out otter’, and ‘FOO’ to ‘Find out otter’.

You can manually disable expand by using C-q.

Beside normal abbrev, which need defition to expand, “dynamic abbrevs (Dabbrev)” can be determined from buffer content, but expansion happens only when you request it.

C-x a
    [N] g       generate new abbr definition for last [N] word (or region)
    [N] l       same, but for major mode
    [N] i g     same, but inversed
    [N] i l     i, but for major mode
    e           expand manually (even when Abbrev Mode not enabled)
M-'             separate prefix from following abbrev to be expaned, like:
                    're|cont' expanded by 'cont' abbrev to 'reconstruction'
                    (the | represent the point you type M-')
----------------------------------------------------------------------------
M-/             expand, "dynamically"
CM-/            complete as dynamic abbrevs

New definition will overwrite (update) old one. To remove, use negative arg.

Another expansion tools is “Hippie Expansion”, which provid variety of completion and expansions. Typically you would bind hippie-expand to M-/, replacing the adbbrev-expand.

Cmd

define-global-abbrev
define-mode-abbrev
kill-all-abbrevs
unexpand-abbrev         undo last expansion
expand-region-abbrevs
list-abbrevs
edit-abbrevs
write-abbrev-file
read-abbrev-file
define-abbrevs
insert-abbrevs
hippie-expand

Var

abbrev-all-caps
abbrev-suggest-hint-threshold
abbrev-suggest-show-report
dabbrev-casee-fold-search
dabbrev-case-replace
dabbrev-abbrev-char-regexp
dabbrev-abbrev-skip-leading-regexp

Skeleton (Snippet) TODO

Skeleton commands take num arg, negative one make it do backward. It can be used with Abbrevs, rather than key binding for every skeleton command. Like:

(define-abbrev c-mode-abbrev-table "ifst" "" 'c-if)

Auto-pairing can be done by binding the first key in pair, like " ( [, to function skeleton-pair-insert-maybe.

Fn

skeleton-pair
skeleton-pair-on-word

AutoInsert

AutoInsert is used to auto insert text every time a empty file is visited, by putting (auto-insert-mode t) to init file, and they are defined with Skeleton Language.

Cmd

auto-insert
copyright
copyright-update
copyright-current-year
executable-insert
executable-query
time-stamp
time-stamp-toggle-active

Var

auto-insert-alist
auto-insert-query
auto-insert-prompt
time-stamp-active
time-stamp-format
time-stamp-time-zone
time-stamp-line-limit
time-stamp-start
time-stamp-end
time-stamp-count
time-stamp-inserts-lines

Tempo

The Tempo package provides simple way to define templates, a template is defined as a list of items to be inserted in the buffer at point.

See doc for ‘tempo-define-template’ and comments in ‘tempo.el’.

Cmd

tempo-backward-mark
tempo-forward-mark

Version Control

All those commands can be prefixed by C-x v ! to edit the shell command line before running.

[u] C-x vv      [prompt for] next logical action
[u] C-x v=      diff last  [given] version
[u] C-x vD      same, but diff entire working tree
C-x
    vi          register under VC
    v~          visit given version in another buffer
    vg          show latest version of each line ("annotated")
    ----------------------------------------------------------------
[u/N] C-x 
    vl          logs of this fileset [starting from revision/show N entries]
    vh             ..of this region
    vL             ..of entire repo
    vbl            ..of other branch
    vI             ..of what incoming will "pull" receive
    vO             ..of what outcoming will "push" sent
    ----------------------------------------------------------------
    vu          revert (undo) to last revision
    vG          ignore file
    vd          enter VC Dir Mode
    ----------------------------------------------------------------
    vbs         switch branch
    vP          push
    v+          pull
    vm          merge from another branch
    ----------------------------------------------------------------
    va          visit 'ChangeLog' file
    ----------------------------------------------------------------
    vs          create tag
    vr          retrieve tag

Mode Line Indicator:

@@              registered but not commit ("added")
-               unmodified
:               modified
!               conflict or removed from VC
?               VCed but missing from working tree

Log Edit Mode (*vc-log* buffer)

To abort a commit, just don’t type C-cc in vc-log buffer, you can just switch buffers and do other editing.

C-c
    C-f         view fileset
    C-d         diff
    C-w         generate ChangeLog entreis
    C-a         read relevant entreis from ChangeLog files
    C-c
M-n/p/s/r       browser commit message history

Git Log View Mode

n/p             next/prev line
a               annotate this lines's revision
e               edit comment (NOT all VC support this)
f               visit this line's revision 
d               diff revision at point and next earlier revision
D               changeset diff..
<ret>           toggle full log

Anotate Mode

n/p             annotate next/prev revision
j               annotate revision indicated by this line
f               same, but show in buffer
a               annotate prev revision indicated by this line
d               diff this line's revision with its prev revision
D               same, but for all files in the changeset
l               show log of this line's revision
v               toggle annotation visibility

VC Dir Mode

* indicate the file has been marked as current VC fileset.

n, <spc>/p      next/prev line
<tab>/S-<tab>   next/prev dir line
<ret>,f         visit file
o               visit in other window
q               quit
x               hide up-to-date or ignored
S               search on fileset
Q               regexp query replace on fileset
M-s a C-s       isearch on fileset
M-s a CM-s      regexp isearch on fileset
d               delete marked (NOT from VC, mostly useful for unregistered)
----------------------------------------------------------------
m               mark in VC fileset
M               mark all with same status
%m, *%          mark by regexp
*r              mark registered
u               unmark
U               unmark all with same status
G               ignore
----------------------------------------------------------------
bc              new branch
bl              show logs for given branch
bs              switch to branch

Cmd

vc-ediff        like v=, but using ediff
vc-log-search   search log history by matching message with pattern
vc-create-branch
vc-delete/rename-file

Var

[vc-[BACKEND-]]diff-switches
[vc-BACKEND-]annotate-switches
vc-annotate-background-mode
vc-revert-show-diff
vc-directory-exclusion-list

Diff

Cmd

diff
diff-backup
diff-buffer-with-file
ediff
ediff-region-linewise/wordwise
[N] compare-windows         compare two windows starts from each's point

Var

diff-switches               options for `diff` util

Diff Mode

n/p,N/P                 next/prev hunk,file start
M-k/K                   kill hunk/file part
C-c
    a                   apply
    b                   break down to see refined changes
    c                   go to source
    e                   start ediff
    n                   narrow view to this hunk
    r                   reverse direction
    s                   splite hunk to two
    d                   convert buffer to "context diff format"
    u                                  to "unified diff format"
    l                   refresh hunk
    w                   refresh hunk, disregard whitespace
C-x 4 A                 generate ChangeLog entry

Emerge

During emerge session, you must NOT try to edit the A and B buffers yourself. You can have any number of merges going at once – just don’t use any one buffer as inputu to more than one merge at once.

emerge-files/buffers[-with-ancestor]

Submodes of Emerge

  • “Fast mode”: only single char basic commands.
  • “Edit mode”: commands starts with C-cc, normal Emacs commands also available.

Project

A directory is a “project” if it’s a VSC repo, or EDE (UNMAINTAINED). this list can be extended in future). The “current project” is determined by ‘default-directory’.

To create new projects, C-x pp then ... (Choose a dir).

C-x p p                 switch project
C-x p                   in project:
    f                   visit a file
    g                   find files whose content match regex
    r                   regexp replace
    ----------------------------------------------------------------
    b                   goto buffer
    C-b                 list buffer
    k                   kill all buffers
    ----------------------------------------------------------------
    v                   run vc-dir
    d                   find dir, into Dired
    D                   Dired to project root
    ----------------------------------------------------------------
    s                   run shell
    e                   run eshell
    c                   run compile
    !                   run a shell cmd
    &                   run a async shell cmd

Cmd

project-search          same as C-x pg, but stop at first match

Var

project-kill-buffer-*
    conditions              which to kill when C-x p k
    display-buffer-list     display before killing
project-list-file           where to save project info
project-forget-project

Imenu

Offers find major definitions in file, also useful in text modes where it treas chapter, section, etc., as definition.

M-g i

Var

imenu-*
    auto-rescan[-maxout]
    max-index-time
    sort-function

Which function mode display current function name in mode bar.

Xref

Xref is a unified interface for tag/symbol finding, it needs a backend to work with:

  • Some major mode provide built-in means for looking up symbols, like Emacs Lisp Mode.
  • If Eglot is on, it can consult lsp server to supply symbol info.
  • etags/ctags can also be used.

“Tags table” can be produced by etags util, Emacs use the tags table as one of the backends for xref.

List of language and what’s considered as tags in their construction:

lang        tags
---------------------------------------------------------------------------
C           function, typedef, struct, #define...
Lisp        defun, defvar, defconst...
Go          package, function, type
HTML        title, headers, anchors, id
PHP         function, class, define, var
Python      def, class
Rust        fn, enum, struct, macro_rules!

Definition, Reference

M-.                 find definition
C-x 4/5 .           ..in other window/frame
M-?                 find reference
CM-.                find identifiers by pattern
----------------------------------------------------------------
M-,                 go back
CM-,                go forward
----------------------------------------------------------------
CM-i                perform completion

In XREF Mode (*ref* buffer):

n/.                 goto next and display in other window
p/,                 goto prev..
N/P                 goto next/prev group
C-o                 show pos in other window ??
----------------------------------------------------------------
r                   query replace this identifier
g                   refresh
M-,                 quit, jump to prev xref stack location
CM-,                go forward again (useful if M-, go back too far)
q                   quit

Cmd

xref-*
    find-definitions-at-mouse
    etags-mode
    find-references-and-replace
visit-tags-table
list-tags
tags-*                          in all file
    search
    tags-query-replace
    next-file
fileloop-continue               restart tags search/replace cmd at this point

Var

xref-*
    auto-jump-to-first-definition
tags-*
    table-list
    case-fold-search   		case sensitivity for find-tag
    apropos-additional-actions

Compilation

The default compile command is make -k, if you’ve done M-x compile before, the command that you specified is auto stored in compile-command. A file can also specify a file-local value.

You can control the env value passed to compilatioin command with compilation-environmentt.

To run two compilations at once, rename the first *compilation* buffer.

C-x `               next error
M-gn/p              next/prev error

NOTE that M-gn, M-gp don’t just act on compilation error, it works for like error produced by other command, like occur.

Compilation Mode (compilation buffer)

[u] g               [edit and] recompile
[n] M-n/p           next/prev error, without find source line
[n] n/p             ..find and hilight source, stay focused
[n] M-{/}           next/prev file
C-cc                goto error
C-cf                enable "next errorr follow" mode
C-ck                kill compilation

Cmd

compile         	run async a compiler
recompile       	run last compile command
kill-compilation	kill the running subproc

Var

compilation-*
    scroll-output
    always-kill
    skip-threshold      skip when nexting-error
    hidden-output       hide too verbose output
    error-regexp-alist  what's "error" and where's "locus"

Flymake

On-the-fly syntax checking. It’s only useful when a backend provide the buffer-checking service – this is done via flymake-diagnostic-functions. When LSP is enabled (via Eglot or lsp-mode), flymake will use that as backend.

Flymake Mode

Auto check when buffer saved or more than 0.5 seconds after buffer changes.

Mode Line Status

Wait        backends haven't respond for last request
!           all backends has disabled
?           no applicable backends

Extending

By place a func in hook flymake-diagnostic-functions.

Cmd

flymake-*
    mode                                enable mode
    start                               manually invoke checking
    goto-next/prev-error
    show-buffer/project-diagnostics     show errors in one place
    ----------------------------------------------------------------
    reporting/running/disabled-backends
    switch-to-log-buffer

Var

flymake-*
    mode-line-lighter/[counter-]format
    no-changes-timeout
    start-on-flymake-mode
    start-on-save-buffer
    fringe-indicator-position
    wrap-around

Eglot (LSP)

Feature

  • At-point documentation via ElDoc.
  • Diagnostic annotation via Flymake.
  • Definition and reference via Xref.
  • Buffer navigation by func, class, methods etc., via Imenu.
  • Completion at point by ‘completion-at-point’ command.
  • Auto reformat as you type.
  • Code action.

Other LSP Clients

  • lsp-bridge: https://github.com/manateelazycat/lsp-bridge/.
  • lsp-mode: https://github.com/emacs-lsp/lsp-mode/.

Setting Up

  1. If your language is inside eglot-server-programs value, you just need to install its lsp server.
  2. Start Eglot, there are two way:
    • Manually, in your project’s any file-visiting buffer, do M-x eglot.
    • Automatically, hook in major modes, like `(add hook ‘foo-mode-hook ‘eglot-ensure)
  3. Use it with ElDoc, Flymake, Xref, and Imeu. Eglot’s own commands are mainly to perform tasks by lsp server.

For eglot, emacs’s project is what “workspace” for lsp server, and consdiers a buffer’s file who turned eglot on as belonging to a project (even a project of only itself).

In some case, additional info of project layout is needed for lsp server when starting it, eglot-workspace-configuration is for that.

For each buffer in which eglot is active, eglot is “managing” the file visited by it, and communicate with lsp server about its content updates. Variable eglot-managed-p tells whether current buffer is being managed or not.

Cmd

eglot                   figure out lsp server and start it
eglot-*
    show-workspace-configuration
    reconnect
    [u] shutdown        [don't kill buffers used for talking to server]
    [u] shutdown-all    same, but all server
    ----------------------------------------------------------------
    rename              rename symbol
    format              reformat region by server's rules
    format-buffer
    code-actions
    code-action-orgnize-imports
    code-action-quickfix
    code-action-extract
    code-action-inline
    code-action-rewrite
    ----------------------------------------------------------------
    inlay-hints-mode
    ----------------------------------------------------------------
    events-buffer
    stderr-buffer
    forget-pending-continuations
    signal-didChangConfiguration    update server conf 
    clear-status                    clear JSONRPC error of this buffer

Var

eglot-*
    autoreconnect
    connect-timeout
    sync-connect
    events-buffer-size
    autoshutdown
    confirm-server-initiated-edits
    ignored-server-capabilities
    extend-to-xref                  jump definition even outside (liek /lib)
    mode-map
    ----------------------------------------------------------------
    server-programs
    strict-mode
    server-initialized-hook
    connect-hook
    managed-mode-hook
    stay-out-of
    reporot-progress

Config Exmpale

(define-key eglot-mode-map (kbd "C-c r") 'eglot-rename)
(add-hook 'foo-mode-hook 'eglot-ensure)
(with-eval-after-load 'eglot
   (add-to-list 'eglot-server-programs
                '(foo-mode . ("fools" "--stdio"))))

LSP Server Config

  • Project Specific

In LSP spec, project-specific settings is called “workspace configuration”, to do this, use the director-local variable eglot-workspace-configuration in ‘.dir-locals.el’ file. The value of it is a plist:

(:SERVER1 PLIST1 :SERVER2 PLIST2 ...)

The settings take effect when establishing connection, or eglot-signal-didChangeConfiguration.

Here is an example, demo using two lsp server pylsp and gopls in one project, notice how alists are used for associating Emacs mode names with alists associating variable names with variable values. Then notice how plists are used inside the value of ‘eglot-workspace-configuration’:

((nil
  . ((eglot-workspace-configuration
      . (:pylsp (:plugins (:jedi_completion (:include_params t
                                             :fuzzy t)
                           :pylint (:enabled :json-false)))
         :gopls (:usePlaceholders t)))))
 (python-base-mode . ((indent-tabs-mode . nil)))
 (go-mode          . ((indent-tabs-mode . t))))
  • User Specific

Apply to all porject the server is for. One way to pass cmdline options is to use the eglot-server-programs:

(with-eval-after-load 'eglot
  (add-to-list 'eglot-server-programs
               `(c++-mode . ("clangd" "--compile-commands-dir=/tmp"))))

Another way is to give all your projects a cerntain default config:

(setq-default eglot-workspace-configuration
              '(:pylsp (:plugins (:jedi_completion (:include_params t
                                                    :fuzzy t)
                                  :pylint (:enabled :json-false)))
                :gopls (:usePlaceholders t)))

JSONRPC In ELisp

JSON are represented by the following elisp construct:

JSON                    ELisp
----------------------------------------------------------------
true                    t
false                   :json-false
null                    nil
{}                      eglot-{}
array                   vector

For example, the plist:

(:pylsp (:plugins (:jedi_completion (:include_params t
                                     :fuzzy t
                                     :cache_for ["pandas" "numpy"])
                   :pylint (:enabled :json-false)))
 :gopls (:usePlaceholders t))

is serialized by Eglot to JSON:

{
  "pylsp": {
    "plugins": {
      "jedi_completion": {
        "include_params": true,
        "fuzzy": true,
        "cache_for": [ "pandas", "numpy" ]
      },
      "pylint": {
        "enabled": false
      }
    }
  },
  "gopls": {
    "usePlaceholders": true
  }
}

Toubleshooting

Try first using eglot-events/stderr-buffer.

If eglot is working but slow, trying customize eglot-events-buffer-size to 0; else you might try advanced server

GUD, Debugger

C-x
    C-ab        set breakpoint
C-c
    C-l           list source
    C-s           step line
    C-n           next
    C-i           stepi
    C-p           print
    C-r           continue execution
    C-d           del breakpoint
    C-t           temp breakpoint
    C-<           stack up
    C->           stack down
    C-u           run until this line
    C-f           run until frame return
    C-aj          jump

Cmd

gdb
gud-gdb
perldb
jdb
pdb
guiler
dbx
xdb

Customization

Init File

~/.emacs
~/.emacs.el
~/.emacs.d/init.el
~/.config/emacs/init.el

Emacs will set user-emacs-directory to the directory it decides to use.

To know what font is under cursor, use “describe-face”.

To eval expr: either with M-:; or inside the “scratch buffer” (C-j to run).

To save customization in seperate files:

;; in init file
(setq custom-file "~/.config/custom.el")
(load custom-file)

Custom Mode

C-cc        "Set for Current Session"
C-xs        "Save for Future Sessions"

Cmd

customize[-*]
    option
    face
    icon
    ---------------------
    group 
    apropos
    browser
    changed
    saved
    unsaved

Var

custom-
    search-field        show search box?
    buffer-done-kill    kill custom buf when done?

Packages

Installed pkgs are put in package-user-dir (default is ~/.emacs.d/elph/), in addititon, Emacs looks for installed pkgs inside package-directory-list, these dirs are meant to make pkg system-wide.

Package Status

available
avail-obso      obsolote (has new version), hidden by default
built-in
dependency
disabled        by 'package-load-list'
external        not from dir given by 'package-user-dir'
held
incompat        cannot be installed (like depend on uninstallable pkgs)
new             newly available on the pkg archive after last listing
obsolete        newer version installed

Package Menu Mode

i/d             mark for install/delete
~               mark all obsolete for delete
w               open pkg's website
u               unmark all
U               mark all upgradable
g, r            refresh list
H               hide 
(               toggle showing old version pkg
/               filter by:
    a/d/k/N      	archive/desc/keyword/name or desc/
    n/s/u/v/m/u    	name/status/version/marked/upgradable/
//              clear filter
x               execute

Cmd

list-packages           enter "Package Menu Mode"
package-*
    install             by default, don't consider builtin pkgs
    install-file        manually install from file 
    upgrade[-all]       never consider builtin
    recompile[-all]

Var

package-*
    archives            "repo" 
    archive-priorities
    menu-hide-low-priority
    import-keyring
    load-list
    pinned-packages
    install-upgrade-built-in

Use Package

A macro to setup pkg customization in init file in a declarative way, and keep emacs startup fast. It’s NOT a pkg manager, and NOT intended to replace the customize cmd, but to work together with them.

(use-package color-moccur                   ;; load color-moccur
    :commands (isearch-moccur isearch-all)  ;; autoloads these two commands
                                            ;; (when one of these cmds are used,
                                            ;; color-moccur will be loaded.
    :bind (("M-s O" . moccur)               ;; bind keys both globally and in 
          :map isearch-mode-map             ;; isearch-mode-map
          ("M-o" . isearch-moccur)
          ("M-O" . isearch-moccur-all))
    :init
    (setq isearch-lazy-highlight t)
    :config
    (use-package moccur-edit))

Package Loading

:defer [N]      DONT load [until N seconds] (rarely used alone). redundant
                if there already using autoloading keywords, should use in
                cases when use-package isn't creating any autoloads for you.
:demand         force load now (but :defer is higher).
---------------------------------------------------------------------------
:if arg         if arg evaluated to non-nil, then load
:when arg       alias to :if
:unless arg     :if (not arg)
---------------------------------------------------------------------------
:after (:all foo bar)   load after both foo and bar loaded
:after (foo bar)        same
:after (:any foo bar)           ...any of
---------------------------------------------------------------------------
:requires       never load if dependencies not available
---------------------------------------------------------------------------
:load-path      add dir to load path
:commands       autoload an interactive command
:autoload       autoload a non-interactive function

Config Using Lisp

When possible, avoid the below three, prefer autoloading keywords such as ‘:bind’, ‘:hook’, ‘:mode’.

:preface        eval before anything, except :disabled and :ensure
:init           eval just before package is loaded
:config         eval after package loaded

Key Binding

:bind           globally. take either signle cons or list of conses. each
                con has the form '(KEY . CMD)'.
:map            bind within local keymap (only exists after pkg loaded)
:bind-keymap    same as bind, but must be keymaps defined in pkg, not
                interactive functions. 
:repeat-map     bind to repeat-mode map

Hooks, Modes, Interpreters, Magic Handler

:hook HOOKS     add functions to one or more hooks
:mode           deferred binding within `auto-mode-alist`
:interpreter                        ... `interpreter-mode-alist`
:magic
:magic-fallback

User Options

:custom
:custom-faces

Hiding Minor Mode

:diminish
:delight

Examples

;; Rebind fill-paragraph(M-q) to unfill-toggle.
(use-package unfill
  :bind ([remap fill-paragraph] . unfill-toggle))

;; These two are equivalent, the first one save us some typing.
;; 1.
(use-package ace-jump-mode
  :bind ("C-." . ace-jump-mode))
;; 2.
 (use-package ace-jump-mode
   :defer t
   :init
   (autoload 'ace-jump-mode "ace-jump-mode" nil t)
   (bind-key "C-." 'ace-jump-mode))

;; :map binding to local.
(use-package term
  :bind (("C-c t" . term)       ;; any binding before the first :map are global
         :map term-mode-map
         ("M-p" . term-send-up)
         ("M-n" . term-send-down)
         :map term-raw-map
         ("M-o" . other-window)
         ("M-p" . term-send-up)
         ("M-n" . term-send-down)))

;; :bind-keymap
(use-package foo
  :bind-keymap ("C-c p" . foo-command-map))

;; :custom
(use-package comint
  :defer t
  :custom
  (comint-buffer-maximum-size 20000 "Increase comint buffer size.")
  (comint-prompt-read-only t "Make the prompt read only."))

Note that the values customized using :custom are not saved in the standard Emacs custom-file (see Saving Customizations in GNU Emacs Manual). You should therefore set each user option using either the :custom keyword or M-x customize-option command; the latter will save customized values in the Emacs custom-file. Do not use both for the same variable, as this risks having conflicting values in your use-package declaration and your custom-file, which can lead to problems that are both tricky and tedious to debug.

Cmd

describe-personal-keybindings

Var

use-package-always-defer

Variable

Local, Global

“Customizable variable” are also called “user options”, and can be set with set-variable cmd, and it can set only customizable var locally. To set any variable, use setq. To set customizable var in init file, use setopt.

To make customization save into other file other than your init files:

(setq custom-file "~/.config/emacs-custom.el")
(load custom-file)

“Local” variables only has effect to a buffer, some variable cannot be local, they are always local to each display instead. To set the global value of a variable, use setq-default. Lisp can use default-value to see a variable’s default value.

File Variable

File and directory can also specify value when editing the file, file variable will override directory level variable, here is how to set value in file’s first line:

-*- mode: MODENAME; VAR: VALUE; ... -*-

Or by “Local Variables:” to give a variable list:

/* Local Variables:  */
/* mode: c           */
/* comment-column: 0 */
/* End:              */

The following keywords are not really variables, setting them in other context has no meaning:

mode        enable major mode
eval        eval Lisp expr (can be dangerous!)
coding      use coding system
unibyte     load or compile a Lisp file in unibyte mode (if 't')

Per-Directory Variable

Once way is in file .dir-locals.el or .dir-locals-2.el (useful if the former is VCed anad we still want personal customization). These file should hold a list, which maps major mode names to alists:

((nil . ((indent-tabs-mode . t)     ;; nil: for any file in dir
         (fill-column . 80)
         (mode . auto-fill)))           
 (c-mode . ((c-file-style . "BSD")      
            (subdirs . nil)))       ;; only apply to current, not subdir
 ("src/imported"
  . ((nil . ((change-log-default-name
              . "ChangeLog.local"))))))

Another way is to combine the usage of dir-locals-set-class-variables and dir-locals-set-directory-class, these function calls typically go in your init file. This way is useful if you cannot write to directory.

(dir-locals-set-class-variables 'unwritable-directory
   '((nil . ((some-useful-setting . value)))))

(dir-locals-set-directory-class
   "/usr/include/" 'unwritable-directory)

Per-Connection Variable

Cmd

make-local-variable         read and make a var local  
kill-local-variable
make-variable-buffer-local  mark a var to be local when set
----------------------------------------------------------------
add/delete-file-local-variable-prop-line
copy-dir-locals-to-file-locals-prop-line
add/delete-file-local-variable              to/from list
copy-dir-locals-to-file-locals
add/delete-dir-local-variable
copy-file-locals-to-dir-locals
----------------------------------------------------------------
enable-local-variables/eval
safe-local-eval-forms

Key Binding

Menu bar and mouse button events are also represented as fictitious “prefix key”.

Bindings between keys and command functions are stored in “keymaps”, the “global” keymap is always in effect. Some prefix keymaps are stored in variables:

ctl-x-map       for chars that follow C-x
help-map                            ..C-h
esc-map                             ..<esc>
ctl-x-4-map                         ..C-x 4
mode-specific-map                   ..C-c
project-prefix-map                  ..C-x p    

C-c prefix and F5~F9 is reserved for user key bindings. Major modes providing their own key bindings in “local keymaps”. Minor modes do so, too; and override major mode’s when activated. A local keymap can redefine a key as a prefix key by defining it as a prefix keymap. The minibuffer has its own set of local keymaps.

Keys Rebinding

You can rebind keys with commands:

keymap-global/local-set  RET KEY CMD 
keymap-globa/local-unset RET KEY

If you want to retract changes, you need to redefine it to standard key. To find that, go to Fundamental mode in a fresh Emacs and use C-h c.

Another way is to put the rebinding in init files:

;; the most easy way:
(keymap-global-set "C-z" 'shell)

;; lower level functions:
(global-set-key (kbd "C-z") 'shell)

If you want to define your own prefix key as new keymap:

;; change to specific keymap:
(define-prefix-command 'my-prefix-map)
(global-set-key (kbd "`") 'my-prefix-map)
(keymap-set 'my-refix-map (kbd "C-o o") 'my-coo-cmd)
;; to remove, use keymap-unset

Since mode’s keymaps are not constructed until it has been loaded, you must delay binding by putting in mode hook:

(add-hook 'texinfo-mode-hook
          (lambda ()
            (keymap-set texinfo-mode-map "C-c p"
                        'backward-paragraph)
            (keymap-set texinfo-mode-map "C-c n"
                        'forward-paragraph)
            (keymap-set texinfo-mode-map "C-c C-x x" nil)))

Hooks

“Hooks” is a lisp var which holds list of functions, to be called on some occasion:

  • “normal hooks”’s name ends with “-hook”, it calls funcs in turn without arguments.
  • “abnormal hooks”’s name ends with “-functions”.
  • “mode hooks” are normal, to customize modes’ behavior.

If the hook variable is buffer-local, the buffer-local variable will be used instead of the global variable. However, if the bufefr-local variable contains the element t, the global hook variable will be run as well.

It’s better to use function when add-hook, and design your hook functions so that the order in which they are executed does NOT matter.

Call remove-hook to remove your functions from hook.

(setq my-c-style
  '((c-comment-only-line-offset . 4)
    (c-cleanup-list . (scope-operator
                       empty-defun-braces
                       defun-close-semi))))

(add-hook 'c-mode-common-hook
  (lambda () (c-add-style "my-style" my-c-style t)))

Utils

Calendar, Diary, Clocking In Out

“Diary” records events asoociated a date, stored in dairy-file. Every events begin with a date. Then can be viewed in calendar.

Diary files can contain directives to include the contents of other files with diary-list-entries-hook.

[u] calendar        calendar mode

Calendar Mode

[n] C-f/b,n/p,{/},[/]   move by day,week
    M-{/}                     ..month
    C-x [/]                   ..year 
C-a/e                   move to start/end of week
M-a/e,</>                                  ..month,year
g d/D/w                 goto date/day of year/week
o                          ..month
.                          ..today
---------------------------------------------------------------------------
</>                     scroll one month
C-v/M-v                     ..three..
---------------------------------------------------------------------------
M-=                     count days of region (marks keys are available)
p d                     show day in year
C-cl                    redraw
---------------------------------------------------------------------------
h                       show this day's holidy 
x/u                     mark/unmark holidays
a                       list all holidays
S/M                     sunrise/moon phase
---------------------------------------------------------------------------
p/g ...                 show/from this day in calendar system of...
    o                       others
    c                       ISO commercial
    j                       Julian
    a                       Astronomical
    h                       Hebrew
    i                       Islamic
    f                       French
    b                       Baha'i
    C                       Chinese
    k                       Coptic
    e                       Ethiopic
    p                       Persian
    m                       Maya
---------------------------------------------------------------------------
H m/y                   export one-month/year to html file
t ...                   export ... to latex buffer 
    m/M/d
    w 1/2/3/4/W
    f w/W
    y/Y
    fy

Diary

d/s                     show this day/all diary 
m/u                     mark/unmark all days with diary 
---------------------------------------------------------------------------
i ...                   insert entry ...
    d/w/m/y               for day/dow/dom/doy
    a/b/c                 as anniversary/block (of region)/cyclic 

Clocking In Out

timeclock-*
    in/out
    change
    workday-remaining
    when-to-leave

Two Column (2C) Editing

<f2>/C-x 6
    2         	enter 2C mode
	s         	split current buffer to 2C
	b         	2C with other buffer
    <ret>       insert newline in both side
    1           merge (from right to left) and done
    d           dissociate

Table Editing

Cmd

table-*
    insert
    [un]recognize[-region/table/cell]           [de]activate as table
    forward/backward-cell
    span/split-cell[-vertically/horizontally]
    heighten/shorten/widen/narrow-cell
    justify
    insert/delete-row/column
    capture/release                             convert from/to text
    query-dimension
    insert-sequence
    generate-source                             for html/latex/wiki...

Picture

Set Inserting Direction

C-c
    < > ^ .     left right up down
    ` ' / \     nw ne sw se
(u) C-c
    ` ' / \     wnw ene wsw ese

Move Cursor

C-
    n/p
    e/f
    b
C-c
    C-f/b
-- tab stops -------------------------------------------------------
CM-i
<tab>
C-c <tab>

Deletion

C-d
C-c C-d
<del>
C-k
C-o

Rectangle

C-c
    C-k/w/y/x/r
C-x rr                  copy
C-x u                   undo

Artist Mode

Drawing with mouse.

mouse2                  popup menu
[S] mouse1              draw [straight or normalized]
[S] mouse3              erase char[rect]

Calc

Features

  • Arbitrary precisioin int and float.
  • RPN or algebraic.
  • Programmer, Financial, Number tehoretical feature.
  • Graphics with GNUPLOT.
  • Programable with macros, algebraic rewrite rules or Elisp.

Key Bindings

C-x *c          start

Calculator Mode

?               help, repeat it for more
+ - * / ^ %
^               reciprocal
n               change sign

Cmd

calc

Printing

print-buffer/region         print with page headings containing filename
lpr-buffer/region               ..without...
---------------------------------------------------------------------------
ps-print-buffer/region[-with-faces]         convert to PostScript
ps-spoll-buffer/region[-with-faces]         generate and spool a PS image
ps-despoll                                  send spooled PS to printer
handwrite
---------------------------------------------------------------------------
htmlfontify

Var (lpr-*)

  • command
  • switches
  • printer-switch
  • header-switch

With “printing” package:

(require 'printing)

you can also preview PostScript files before printing, with pr-interface.

Feed Reader: Newsticker

Dict

s       search new word
m       search by matching pattern
n/p     next/prev link
D       select default dictionary
M       select default strategy

Image Mode

C-c
    C-c     toggle display
    C-x     toggle hex display
sw          set fit window
sp          set fit percent
ss          set scale
s0          reset to initial
so          reset to original
n/p         next/prev file
m/u         mark/unmark in dired buffer
w           copy file name
---------------------------------------
i
    +/-     incr/decr image size
    r/h/v   rotate, horizon/vert flip
    o       save to file
    c       crop
    x       cut rectangle
---------------------------------------
<RET>       toggle animate
f/b         next/prev frame
F           goto frame
a+/a-/ar/a0 incr/decr/reverse/reset speed

Var

image-*
    auto-resize[-on-window-resize]

Obsolete Features

Remember

(Superceded by org-mode’s Capture.)

By default, notes are captured in ~/.emacs.d/notes. You can save notes to variety of backends, by setting remember-handler-functions, like text file, diary file, mailbox, or integrate with org-mode capture.

Todo Mode