Install packages by default when configured with use-package.
(setq use-package-always-ensure t)
Macro to use to configure built-in features, rather than packages that do not need to be installed
(defmacro use-feature (name &rest args)
"`use-package' with package installation (`ensure') disabled."
(declare (indent defun))
`(use-package ,name
:ensure nil
,@args))
Don’t worry about lockfiles
(setq create-lockfiles nil)
Do not save customizations in init.el
, instead save them in a temporary file
that will be discarded. As a result, any customizations made in a session will
not be persisted across sessions.
(setq custom-file (expand-file-name
(format "custom-%d-%d.el" (emacs-pid) (random))
temporary-file-directory))
Move all common files typically written to the user-emacs-directory
to the
var
and etc
subdirectories so that they can be included in .gitignore
(use-package no-littering
:ensure (:wait t))
Support opening new minibuffers from inside existing minibuffers.
(setq enable-recursive-minibuffers t)
Do not allow the cursor in the minibuffer prompt.
(setq minibuffer-prompt-properties
'(read-only t cursor-intangible t face minibuffer-prompt))
(add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)
Command and other menu history is saved.
(use-feature savehist
:init
(savehist-mode))
Put backup files and auto-save files in var directory, rather than alongside the original files
(setq backup-directory-alist `(("." . ,(no-littering-expand-var-file-name "backup/"))))
(add-hook 'elpaca-after-init-hook
(lambda ()
(setq auto-save-list-file-prefix (no-littering-expand-var-file-name "auto-save/sessions/")
auto-save-file-name-transforms `((".*" ,(no-littering-expand-var-file-name "auto-save/") t)))))
When paths are too long, there can be errors when auto-save and backup filenames are generated. This uses a consistent hash, rather than the full path to generate the filenames. This is taken from Doom Emacs.
(defun c/make-auto-save-file-name-hashed (fn)
"Compress the auto-save file name so paths don't get too long."
(let ((buffer-file-name
(if (or (null buffer-file-name)
(find-file-name-handler buffer-file-name 'make-auto-save-file-name))
buffer-file-name
(sha1 buffer-file-name))))
(funcall fn)))
(advice-add #'make-auto-save-file-name :around #'c/make-auto-save-file-name-hashed)
(defun c/make-backup-file-name-hashed (fn file)
"A few places use the backup file name so paths don't get too long."
(let ((alist backup-directory-alist)
backup-directory)
(while alist
(let ((elt (car alist)))
(if (string-match (car elt) file)
(setq backup-directory (cdr elt) alist nil)
(setq alist (cdr alist)))))
(let ((file (funcall fn file)))
(if (or (null backup-directory)
(not (file-name-absolute-p backup-directory)))
file
(expand-file-name (sha1 (file-name-nondirectory file))
(file-name-directory file))))))
(advice-add #'make-backup-file-name-1 :around #'c/make-backup-file-name-hashed)
Set default width of fill mode to 80 columns.
(setq-default fill-column 80)
Two space indentation by default.
(setq-default indent-tabs-mode nil
tab-width 2
smie-indent-basic 2)
Start an org file with all headers collapsed
(setq org-startup-folded t)
Which-key is a minor mode for Emacs that displays the key bindings following your currently entered incomplete command (a prefix) in a popup.
(use-feature which-key
:init
(which-key-mode))
Helpful is an alternative to the built-in Emacs help that provides much more contextual information.
(use-package helpful
:bind (
;; Remap standard commands
([remap describe-function] . #'helpful-callable)
([remap describe-command] . #'helpful-command)
([remap describe-variable] . #'helpful-variable)
([remap describe-symbol] . #'helpful-symbol)
([remap describe-key] . #'helpful-key)))
(use-feature emacs
:bind (("s-=" . #'global-text-scale-adjust)
("s--" . #'global-text-scale-adjust)
("s-0" . #'global-text-scale-adjust)
("C-=" . #'text-scale-adjust)
("C--" . #'text-scale-adjust)
("C-0" . #'text-scale-adjust))
:preface
(defvar presentation-mode-font-size 21)
(defun presentation-mode ()
"Increase the font size for presentation."
(interactive)
(let* ((current-font-size (/ (face-attribute 'default :height) 10))
(new-font-size
(if (not (eq current-font-size presentation-mode-font-size))
presentation-mode-font-size
c/monospace-font-size)))
(set-face-attribute 'default nil :height (* new-font-size 10))
(set-face-attribute 'variable-pitch nil :height (* new-font-size 10))
(redisplay 'force))))
(use-feature tab-bar
:bind (("s-t" . #'tab-new)
("s-w" . #'tab-close)
("s-T" . #'tab-undo))
:config
(setq tab-bar-show t
tab-bar-new-tab-choice t
tab-bar-new-button nil
tab-bar-close-button-show nil
tab-bar-new-tab-to 'rightmost
;; If this is the default (t) the name format function below causes
;; emacs to hang on boot since commit ca3763af5cc2758ec71700029558e6ecc4379ea9
tab-bar-auto-width nil))
(use-package modern-tab-bar
:after tab-bar
:ensure (modern-tab-bar :host github :repo "aaronjensen/emacs-modern-tab-bar" :protocol ssh)
:init
(modern-tab-bar-mode))
Vertico provides a performant and minimalistic vertical completion UI based on the default completion system.
(use-package vertico
:init
(vertico-mode))
Marginalia adds annotations to minibuffer completions.
(use-package marginalia
:bind (:map minibuffer-local-map ("M-A" . marginalia-cycle))
:init
(marginalia-mode))
Consult provides search and navigation commands based on the Emacs completion function completing-read.
(use-package consult
:bind (("C-x b" . consult-buffer)))
The orderless completion style allows typing parts of what is being matched, separated by spaces. For example, “som thi” will match “this-is-some-thing”.
(use-package orderless
:init
(setq completion-styles '(orderless basic)
completion-category-defaults nil
completion-category-overrides '((file (styles partial-completion)))))
Add :capf
and :compdef
to use-package
(use-package compdef
:ensure (:wait t))
(use-package corfu
:bind
(:map corfu-map
("TAB" . corfu-next)
([tab] . corfu-next)
("S-TAB" . corfu-previous)
([backtab] . corfu-previous)
("C-n" . nil)
("C-p" . nil)
([remap next-line] . nil)
([remap previous-line] . nil)
([remap move-end-of-line] . nil)
([remap move-beginning-of-line] . nil)
("\r" . nil)
("<escape>" . corfu-quit))
:init
;; Tab will trigger completion if it does not need to indent
(setq tab-always-indent 'complete)
;; Disable text-mode ispell completion at point function
(setq text-mode-ispell-word-completion nil)
;; TAB-and-Go customizations
(setq
;; Enable cycling for `corfu-next/previous'
corfu-cycle t
corfu-preselect 'prompt)
;; Auto completion
(setq
corfu-auto t
corfu-auto-prefix 2
corfu-auto-delay 0.1)
:config
(corfu-history-mode))
(use-package cape
:config
(setq cape-dabbrev-check-other-buffers nil))
(use-package ripgrep-capf
:after cape
:ensure (:host github :repo "aaronjensen/ripgrep-capf" :protocol ssh)
:init
(defalias 'capf-dabbrev-ripgrep (cape-capf-super #'cape-dabbrev #'ripgrep-capf)))
(use-package embark
:bind (:map
vertico-map
("C-c C-o" . #'embark-export)
("C-c C-c" . #'embark-act)
("C-c C-e" . #'c/embark-export-wgrep))
:preface
(defvar c/embark-export-wgrep nil)
(defun c/embark-export-wgrep ()
"Embark export then wgrep"
(interactive)
(setq c/embark-export-wgrep t)
(command-execute #'embark-export)))
(use-package embark-consult
:config
(declare-function wgrep-change-to-wgrep-mode "ext:wgrep")
(defun c/embark-export-grep-wgrep (&rest _)
"Start wgrep when indicated"
(when c/embark-export-wgrep
(setq c/embark-export-wgrep nil)
(when (eq major-mode 'grep-mode)
(wgrep-change-to-wgrep-mode))))
(advice-add #'embark-consult-export-grep :after #'c/embark-export-grep-wgrep))
(use-feature flyspell
:hook ((org-mode git-commit-mode markdown-mode) . flyspell-mode)
:config
(setq flyspell-issue-message-flag nil
flyspell-issue-welcome-flag nil))
Edit the grep buffer and store in the file buffer
(use-package wgrep
:config
(setq wgrep-auto-save-buffer t))
Tree layout file explorer
(use-package treemacs
:bind ("s-b" . #'treemacs)
:config
(treemacs-follow-mode))
Allow Treemacs buffers to be unique inside the active tab instead of the default frame-based buffer scope
(use-package treemacs-tab-bar
:after (treemacs)
:demand t
:config
(treemacs-set-scope-type 'Tabs))
(use-package tabspaces
:after consult
:init
(setq tabspaces-session-file (no-littering-expand-var-file-name "tabsession.el")
tabspaces-project-switch-commands #'project-find-file)
(tabspaces-mode)
:config
(consult-customize consult--source-buffer :hidden t :default nil)
;; set consult-workspace buffer list
(defvar consult--source-workspace
(list :name "Workspace Buffers"
:narrow ?w
:history 'buffer-name-history
:category 'buffer
:state #'consult--buffer-state
:default t
:items (lambda () (consult--buffer-query
:predicate #'tabspaces--local-buffer-p
:sort 'visibility
:as #'buffer-name)))
"Set workspace buffer list for consult-buffer.")
(add-to-list 'consult-buffer-sources 'consult--source-workspace))
(use-feature shell
:config
(setq sh-basic-offset 2))
(use-package markdown-mode
:config
(add-hook 'markdown-mode #'visual-line-mode)
(add-hook 'markdown-mode #'visual-wrap-prefix-mode)
(setq markdown-list-indent-width 2))
(use-feature ruby-mode
:hook (ruby-mode . corfu-mode)
:capf capf-dabbrev-ripgrep
:config
(setq ruby-block-indent nil
ruby-method-call-indent nil
ruby-method-params-indent nil
ruby-after-operator-indent nil
ruby-bracketed-args-indent nil))
Find potential definitions of a function of variable under point
(use-package dumb-jump
:init
(add-hook 'xref-backend-functions #'dumb-jump-xref-activate)
(setq xref-show-definitions-function #'xref-show-definitions-completing-read)
(setq dumb-jump-force-searcher 'rg))
(use-package magit)
Install latest version of transient, as the version included in Emacs is not recent enough.
(use-package transient)
(use-package vterm
:init
(setq vterm-always-compile-module t
;; Defaults to 0.1. Decreasing this greatly impacts performance of
;; rendering large batches of text.
vterm-timer-delay 0.06))
(use-package vterm-toggle
:bind (("s-i" . vterm-toggle)))
(add-hook 'after-init-hook
(lambda ()
(let ((inhibit-message t))
(message "Emacs init time: %s" (emacs-init-time)))))