~jman/dotfiles

dotfiles/emacs/guide.md -rw-r--r-- 21.1 KiB
89162fe3jman firefox: enable smooth scrolling 7 days ago

#Index

#First emacs setup

  • Install latest Emacs 28.x
  • Stow my emacs config
  • Start Emacs and run M- package-install-selected-packages to install all packages (I use use-package)

#Emacs general usage

There are 4 keybinding selectors:

M-x (execute-extented-command): run any Emacs command from the minibuffer (also commands that do not have a keybinding)

M-X (execute-extended-command-for-buffer): (from Emacs 29) Like above, but it limits the completions to commands that are relevant to the current buffer.

C-c: reserved for major and minor modes

C-x: global bindings expected to do something regardless of the active modes

src: https://emacs.stackexchange.com/a/68878

#An info docs primer

Emacs Info docs: https://www.gnu.org/software/emacs/manual/html_mono/info.html

To open a specific Info page, eval a code like this (C-x C-e): (info "(org)Org Plot"). To copy the current Info node in the kill ring, type C-0 c in Info-mode, then wrap it with a call to (info "<yank-here>").

Added a few shortcuts (source) to make navigation easier.

Standard Shortcuts My shortcuts Purpose
F1 Info help
C-n / C-p Next / Previous line
M-n / M-p Scroll up / down
p / n Next / Previous paragraph
<SPC> / <BCKSPC> h / l Next / Previous node
n / p h / l Next / Previous node
j / k Next / Previous reference
b go to beginning of node
s / search
} / { next / prev search hit
C-s (2x) next / prev search hit
/ regexp search
? regexp backward search
M-[ History back
M-] History forward
B Set bookmark

#Shortcuts to move around in a buffer

From: https://www.gnu.org/software/emacs/manual/html_node/emacs/Moving-Point.html

Shortcut Purpose
C-f (forward-char) Move forward one character
C-b (backward-char) Move backward one character
 
C-n (next-line) Move down one screen line
C-p (previous-line) Move up one screen line
C-a (move-beginning-of-line) Move to the beginning of the line
C-e (move-end-of-line) Move to the end of the line
 
M-f (forward-word) Move forward one word
M-b (backward-word) Move backward one word
 
C-v (scroll-up-command) Scroll the display one screen upward
M-v (scroll-down-command) Scroll the display one screen downward
M-g g (goto-line) goto line
 
M-< (beginning-of-buffer) top of file
M-> (end-of-buffer) bottom of file
 
C-M-f (sp-forward-sexp) Move forward across one balanced expression

#Indent/Unindent a selected region

C-u 4 + C-x TAB +indent C-u -4, C-x TAB -indent C-x TAB then arrow left/right

#Search and replace

C-s (isearch-forward) to input a search term. C-s C-w insert the next word at point.

M-n and M-p to go to the next/previous match.

M-% string <RET> newstring <RET> (a.k.a. M-x query-replace, y to confirm each entry)

ESC % string <RET> newstring <RET>

M-x replace-string RET / M-x replace-regexp RET

C-c s (rg-menu) Ripgrep menu

C-c s . (jman/rg-dwim-project-dir) search defaulting to include files with the same extension of the file in current buffer (sets :file current)

#Dired: search and replace in multiple files in a directory

M-x dired
M-x dired-mark-files-regexp <RET> .
M-x dired-do-query-replace-regexp <RET> xxx yyy

Type Y to do the replacement on all files without further asking.

#Dired: search and replace in multiple files using a search result set

Run any search with rg-menu (C-c s), then press e for wgrep-change-to-wgrep-mode to change to wgrep mode, apply the changes then save the files.

#Dired: rename multiple files in a directory

M-x dired
C-x C-q (switch to writable dired mode `wdired-change-to-wdired-mode`)
# Edit the file names listing as if it were a normal buffer
C-x C-s or C-c C-c (finish editing `wdired-finish-edit`)

#Misc

M-x ibuffer (C-x C-b) to list all open buffers.

Type S to save all marked files.

Insert a newline in a replace regexp: M-x replace-regexp RET ; RET C-q C-j

Reload a buffer: M-x revert-buffer or the variant revert-buffer-quick (C-x x g) (asks for less confirmation).

Read a file into current buffer: C-x insert-file

#Windows and Frames

When using Emacs GUI a frame is the main container. A window is a subset of a frame. A frame initially contains one window and can be subdivided into multiple windows. One can switch from one window to another. Buffers can be opened in different windows.

Windows documentation: docs

Change Windows: docs

C-x o Select another window (M-x other-window) and that's the letter o, not a zero.

C-x 1 Close all windows but the current one

C-M-v Scroll the next window (M-x scroll-other-window)

C-x 4 f Open a file in a different window in the same frame

C-x 5 f Open a file in a new frame

C-x 3 (M-x split-window-right) Split the selected window into two windows, positioned side by side. The left window is the selected one.

C-x 4 b bufname RET (switch-to-buffer-other-window) Select buffer bufname in another window. More at Displaying in Another Window

Save the current buffer as new file (a.k.a. "Save as ..."): C-x C-w (M-x write-file)

#Rename current file in buffer

C-x C-j (dired-jump to current file)

R to rename the file (or dired-do-rename).

C-x k RET to go back to the (renamed) buffer

#Abbreviations

How to add an abbreviation:

  • write import pdb; pdb.set_trace()"
  • add-mode-abbrev (C-x a +)
  • input name of the abbreviation shortcut (f.e. trace)
  • M-x write-abbrev-file: asks to save abbreviations (default: ~/.config/emacs/abbrev_defs)
  • M-x abbrev-mode: enable abbreviation mode
  • use abbreviation: write trace<space> and ... voilà
  • Now you can extend the abbreviation file directly and reload with: M-x load-file ~user/.config/emacs/abbrev_defs

Note: ensure to enable abbrev_mode and add abbreviations only to specific major modes and not in the global abbrev mode file (see packages-config.el).

#Retrieve from cut&paste stack

C-y: pop M-y: show stack C-y + M-y to walk through the stack entries

#Bookmarks

  • C-x rm Save a bookmark
  • C-x rb Jump to a bookmark
  • M-x bookmark-delete <RET> bookmark <RET> Delete a bookmark

Apropos: C-h a

Select entire buffer (select all): C-x h

#Reindent buffer and remove TABs (e.g. in HTML files generated by evil Adobe IDEs)

  • Select region of entire buffer
  • tab to remove excessive indent
  • M-x untabify to replace evil TABs with virtuous spaces

Go to line number (goto-line: M-g g <num>

Search for a matching line (consult-line): M-g M-g <text>

#Go to the top / bottom of the buffer

ESC < / ESC >

C-Home / C-End

#Themes

M-x customize-themes: enter theme selection

M-x color-theme-...: select a theme

M-x disable-theme: yeah, disable a theme

Join lines: C-^

Line Wrap: M-q (a.k.a. fill-paragraph) or activate Auto Fill Mode

#Registers

C-x r s [a, 1, b, 5, r, ...]: copy region into register [a, 1, b, 5, r, ...] (copy-to-register)

C-x r i [a, 1, b, 5, r, ...]: insert text from register [a, 1, b, 5, r, ...] (insert-register)

Comment/Uncomment a region: M-;

#Update all installed EMACS packages

M-x package-list-packages

Ux

#Close / Clean buffers

M-x kill-some-buffers

C-x # close all buffers

M-x clean-buffer-list close all unmodified buffers

Find command defined by a key binding: C-h k then execute the keycombo

Break a long line into multiple lines: M-q (toggle-truncate-lines)

#Hot reload EMACS config (f.e. to refresh pkg installed)

Open your custom .el config file in a new buffer

M-x eval-buffer

Recursively find and replace in files not already open: see here

Autocomplete based on content from opened buffers: M-x dabbrev-expand

SSH into a remote machine and open a file: C-c f f, C-x C-f (M-x find-file) and then /ssh:user@host:/path/to/file

#undo

In Emacs undo is complicated. Documentation at (info "(Emacs)Undo").

C-/: undo last change. Select a region to revert changes in that region only.

C-g: invert the direction of the undo ring, make it a redo ring.

To execute an undo in a region modified previously (aka "selective undo"), select that region then M-x undo (see this comment on HN).

For more esoteric tips, see this video from Steve Yegge (YT Id: 6ZWp05OW1c0).

#Describe modes and available commands in any buffer

Learn to use the describe-* commands, the most useful feature sets to access documentation for just about everything there is in Emacs. (src).

C-h m (M-x describe-mode): show all major+minor modes enabled in the current buffer and their key bindings available.

C-h c (M-x describe-char): what font is being used for a certain piece of text

C-h x (M-x describe-command): how does a given command work?

C-h v (M-x describe-variable): returns the value of a given variable

C-h f (M-x describe-function): shows documentation for a function

C-h o (M-x describe-object): shows documentation for a object (could be a variable or a function)

C-h k (M-x describe-key): prompt to insert a key combination (example C-c f f), returns the function is bound to (if any)

#Javascript setup

C-c ! s Flyckeck javascript: choose linter (e.g. javascript-standard)

C-c ! v Flyckeck javascript: verify current linter setup

C-c ! x Flycheck javascript: disable a linter

#Rust setup

Today I tend to use Rust Analyzer with eglot (now an Emacs built-in package) and rust-mode. The following is left for historical purposes.

Install racer

$ cargo install racer
$ rustup component add rust-src
$ export RUST_SRC_PATH="$(rustc --print sysroot)/lib/rustlib/src/rust/src"

Configure Flycheck and racer

flycheck-rust
(use-package flycheck-rust
   :init
   (add-hook 'flycheck-mode-hook #'flycheck-rust-setup))

Racer
(use-package racer
 :init
 (add-hook 'rust-mode-hook #'racer-mode)
 (add-hook 'racer-mode-hook #'eldoc-mode)
 (global-set-key (kbd "C-c ?") 'racer-describe)
 (global-set-key (kbd "C-c .") 'racer-find-definition)
 (global-set-key (kbd "C-c ,") 'pop-tag-mark)
 )
  • Install autoformatter: $ cargo install rustfmt

  • Cargo specific commands available

    C-c C-c C-b to run cargo build

    C-c C-c C-r to run cargo run

    C-c C-c C-t to run cargo test

#Org-mode primer

Shortcuts for commands I use often:

Shortcut Purpose
M-<arrows> change heading priority
S-left / S-right rotate TODO state (default: unmarked,TODO,DONE)
S-up / S-down increase/decrease the priority (default: #+PRIORITIES: A C B)
<s <TAB> Create a source code block
(from emacs 27 the module "tempo" must be manually enabled by customizing the variable org-modules)
C-c C-e export a buffer to something else (HTML, markdown, etc.)
C-c C-o (org-open-at-point) open a link at point in default browser
C-c C-l edit a link
C-c C-c to check a checkbox (represented by a [ ])
C-u C-u C-c C-c to set a checkbox to [-]
M-x customize-variable RET org-export-backends modify export modes enabled
C-c ! (org-timestamp-inactive) Prompt for a date and insert a corresponding timestamp

To export to Mediawiki format, use ox-wk. Enable it by adding to your emacs personal init file:

(require 'ox-wk)

And use it with:

ox-wk-export-as-wiki export to temporary buffer

ox-wk-export-to-wiki export to ".txt" file

To create a file from a snippet template using org babel:

  • Create a template in $DOOMDIR/snippets/org-mode/__Cargo.org
  • Create a new file Cargo.org with M-x find-file (-> it's counter-intuitive but the file - if not already existing - will be created using the template!)
  • Run C-c C-v t (org-babel-tangle) and a Cargo.toml is generated from the Cargo.org

Note: Doom Emacs ships with a default Cargo.toml for rust-mode (located in $DOOMDIR/modules/editor/file-templates/templates/rust-mode/__Cargo.toml).

#Tables

Shortcut Purpose
C-c C-x M-w (org-table-copy-region) Copy rectangular region in table to clipboard
C-c C-x C-w (org-table-cut-region) Cut rectangular region in table to clipboard
C-c C-x C-y (org-table-paste-rectangle) Paste a rectangular region into a table
S-Left / S-right Move a field
M-Left / M-right Move a column
M-Up / M-Down Move a row
S-M-Down / S-M-Up Add / Delete a row
S-M-Left Delete current column
S-M-Right Add new column (to the left of current column)
C-c { (org-table-toggle-formula-debugger) Enable/disable step-by-step formula debugger
C-c ! (org-time-stamp-inactive) Insert an inactive time stamp (does not create an agenda item)
C-c C-c Recalculate current row
C-u C-c C-c Recalculate entire table

A longer tutorial of things I am learning.

#org-journal

  • M-x org-journal set journal mode
  • C-c C-s (<= org-journal-search) search term in journal (accepting the org-read-date format such as "-1y" or "-1m")
  • C-f f f search term in all entries (org-journal-search-forever) buffers are opened read-only. C-c view-mode or e to edit.

#calendar-mode

  • M-x calendar open calendar
  • C-j view highlighted journal entry
  • e switch from read-only to edit mode for current journal entry
  • C-u i j edit selected journal entry (org-journal-new-date-entry)
  • C-c C-j edit today's journal (creating a new entry)
  • C-u C-c C-j: edit today's journal (without creating a new entry)

For more, see here

Formatting text (link):

  • *bold*, /italic/, _underlined_, =verbatim=, ~code~ and ‘+strike-through+’

References:

#Issues

Problem: when I use the function org-clock-in, it will automatically open all my Orgmode files.

Reason: the function org-resolve-clocks will open org-agenda-files list, plus all open Org files for any dangling clocks and will not close them.

Solution: I'm writing a patch to either a) close all buffers opened during this check or b) just check in the list of open Orgmode buffers

See mailing list.

#Embedded IRC client

M-x irc enable IRC mode

C-u M-x rcirc setup connection parameters (server, port, nick, channel, etc.)

Reminder on how to register your nickname on IRC:

  • Register a nick: /msg NickServ register <password> <email> then follow the instructions
  • Login with your nick: /msg NickServ identify <pwd>
  • Change your password: /msg NickServ SETPASS <nick> <code_received_by_email> <pwd>

#Projectile

  • M-x projectile-add-known-project: add a directory as a new project
  • M-x projectile-switch-to-buffer (C-c p b): switch to another open buffer in the same project
  • M-x projectile-switch-open-project (C-c p q): switch to another opened project
  • M-x projectile-switch-project (C-c p p): switch to another project
  • M-x projectile-find-file (C-c p f): Jump to a project’s file using completion
  • M-x projectile-kill-buffers (C-c p k): Kill project buffers

#project.el

  • C-x p C-h Discover all commands available

Commands:

  • C-x p ! (project-shell-command)
  • C-x p & (project-async-shell-command)
  • C-x p F (project-or-external-find-file)
  • C-x p G (project-or-external-find-regexp)
  • C-x p b (project-switch-to-buffer)
  • C-x p c (project-compile)
  • C-x p d (project-dired)
  • C-x p e (project-eshell)
  • C-x p f (project-find-file)
  • C-x p g (project-find-regexp)
  • C-x p k (project-kill-buffers)
  • C-x p p (project-switch-project)
  • C-x p r (project-query-replace-regexp)
  • C-x p s (project-shell)
  • C-x p v (project-vc-dir)
  • C-x p x (project-execute-extended-command)

#Macro primer

  • Start recording the macro: C-x ( or M-x kmacro-start-macro
  • Stop recording the macro: C-x ) or M-x kmacro-end-macro
  • Execute the macro C-x e or M-x kmacro-end-and-call-macro
  • Repeat the macro for 5 times: C-u 5 C-x e