This repo has been moved to: https://git.miers.xyz/laurens/emacs
(defvar elpaca-installer-version 0.7)
(defvar elpaca-directory (expand-file-name "elpaca/" user-emacs-directory))
(defvar elpaca-builds-directory (expand-file-name "builds/" elpaca-directory))
(defvar elpaca-repos-directory (expand-file-name "repos/" elpaca-directory))
(defvar elpaca-order '(elpaca :repo "https://github.com/progfolio/elpaca.git"
:ref nil :depth 1
:files (:defaults "elpaca-test.el" (:exclude "extensions"))
:build (:not elpaca--activate-package)))
(let* ((repo (expand-file-name "elpaca/" elpaca-repos-directory))
(build (expand-file-name "elpaca/" elpaca-builds-directory))
(order (cdr elpaca-order))
(default-directory repo))
(add-to-list 'load-path (if (file-exists-p build) build repo))
(unless (file-exists-p repo)
(make-directory repo t)
(when (< emacs-major-version 28) (require 'subr-x))
(condition-case-unless-debug err
(if-let ((buffer (pop-to-buffer-same-window "*elpaca-bootstrap*"))
((zerop (apply #'call-process `("git" nil ,buffer t "clone"
,@(when-let ((depth (plist-get order :depth)))
(list (format "--depth=%d" depth) "--no-single-branch"))
,(plist-get order :repo) ,repo))))
((zerop (call-process "git" nil buffer t "checkout"
(or (plist-get order :ref) "--"))))
(emacs (concat invocation-directory invocation-name))
((zerop (call-process emacs nil buffer nil "-Q" "-L" "." "--batch"
"--eval" "(byte-recompile-directory \".\" 0 'force)")))
((require 'elpaca))
((elpaca-generate-autoloads "elpaca" repo)))
(progn (message "%s" (buffer-string)) (kill-buffer buffer))
(error "%s" (with-current-buffer buffer (buffer-string))))
((error) (warn "%s" err) (delete-directory repo 'recursive))))
(unless (require 'elpaca-autoloads nil t)
(require 'elpaca)
(elpaca-generate-autoloads "elpaca" repo)
(load "./elpaca-autoloads")))
(add-hook 'after-init-hook #'elpaca-process-queues)
(elpaca `(,@elpaca-order))
;; Install use-package support
(elpaca elpaca-use-package
;; Enable use-package :ensure support for Elpaca.
(elpaca-use-package-mode)
)
The audible bell is annoying AF.
(setq visible-bell 1)
(setq column-number-mode 1)
(add-hook 'before-save-hook 'delete-trailing-whitespace)
;; The built-in `savehist-mode' saves minibuffer histories. Vertico
;; can then use that information to put recently selected options at
;; the top.
;;
;; Further reading: https://protesilaos.com/emacs/dotemacs#h:25765797-27a5-431e-8aa4-cc890a6a913a
(savehist-mode 1)
;; The built-in `recentf-mode' keeps track of recently visited files.
;; You can then access those through the `consult-buffer' interface or
;; with `recentf-open'/`recentf-open-files'.
;;
;; I do not use this facility, because the files I care about are
;; either in projects or are bookmarked.
(recentf-mode 1)
(defvar myrmi-backup-directory (concat user-emacs-directory "backups"))
(if (not (file-exists-p myrmi-backup-directory))
(make-directory myrmi-backup-directory t)
)
(setq backup-directory-alist `(("." . ,myrmi-backup-directory)))
(setq make-backup-files t
backup-by-copying t
version-control t
delete-old-versions t
delete-by-moving-to-trash t
kept-old-versions 6
kept-new-versions 9
auto-save-default t
auto-save-timeout 20
auto-save-interval 200
)
Because I’m lazy, important yes-or-no questions can be answered with y-or-n:
(defalias 'yes-or-no-p 'y-or-n-p)
(global-set-key (kbd "M-o") 'other-window)
More info : https://www.emacswiki.org/emacs/FullScreen
(push '(fullscreen . maximized) default-frame-alist)
Use list-buffers bigger brother.
(global-set-key [remap list-buffers] 'ibuffer)
(global-set-key (kbd "M-SPC") 'mark-word)
Display number of matches:
(setq-default isearch-lazy-count t)
Reference that might be interesting for later: https://endlessparentheses.com/leave-the-cursor-at-start-of-match-after-isearch.html
(global-set-key [remap dabbrev-expand] 'hippie-expand)
(global-set-key (kbd "M-S-z") 'zap-up-to-char)
Look into customizing the ‘ispell’ group.
(add-hook 'prog-mode-hook 'flyspell-prog-mode)
(delete-selection-mode t)
Some commands are disabled to protect the user. Narrow-region/page is a really handy feature, enable it:
(put 'narrow-to-page 'disabled nil)
(put 'narrow-to-region 'disabled nil)
(require 'use-package-ensure)
(setq use-package-always-ensure t)
Make cursor the width of the character it is under f.e. full width of a tab.
(setq x-stretch-cursor t)
Minor-mode to easily resize frames (works with EXWM (firefox, …)). Courtesy goes to kuanyui (https://gist.github.com/kuanyui/65a408d393871048771c):
;;; resize-frame.el --- A minor mode to resize frames easily. -*- lexical-binding: t; -*-
;; Copyright (C) 2014 kuanyui
;; Author: kuanyui <azazabc123@gmail.com>
;; Keywords: frames, tools, convenience
;; License: WTFPL 1.0
;;; Commentary:
;; Press "ESC `" and use arrow-keys or i/j/k/l to adjust frames. press any key to done.
;;; Code:
(defvar resize-frame-map
(let ((map (make-keymap)))
(define-key map (kbd "<up>") 'enlarge-window)
(define-key map (kbd "<down>") 'shrink-window)
(define-key map (kbd "<right>") 'enlarge-window-horizontally)
(define-key map (kbd "<left>") 'shrink-window-horizontally)
(set-char-table-range (nth 1 map) t 'resize-frame-done)
(define-key map (kbd "C-p") 'enlarge-window)
(define-key map (kbd "C-n") 'shrink-window)
(define-key map (kbd "C-f") 'enlarge-window-horizontally)
(define-key map (kbd "C-b") 'shrink-window-horizontally)
map))
(define-minor-mode resize-frame
"A simple minor mode to resize-frame.
C-c C-c to apply."
;; The initial value.
:init-value nil
;; The indicator for the mode line.
:lighter " ResizeFrame"
;; The minor mode bindings.
:keymap resize-frame-map
:global t
(if (<= (length (window-list)) 1)
(progn (setq resize-frame nil)
(message "Only root frame exists, abort."))
(message "Use arrow-keys or i/j/k/l to adjust frames.")))
(defun resize-frame-done ()
(interactive)
(setq resize-frame nil)
(message "Done."))
(global-set-key (kbd "C-x C-r") 'resize-frame)
;; Enable vertico
(use-package vertico
;; :custom
;; (vertico-scroll-margin 0) ;; Different scroll margin
;; (vertico-count 20) ;; Show more candidates
;; (vertico-resize t) ;; Grow and shrink the Vertico minibuffer
;; (vertico-cycle t) ;; Enable cycling for `vertico-next/previous'
:init
(vertico-mode))
(use-package consult
;; Replace bindings. Lazily loaded by `use-package'.
:bind (;; C-c bindings in `mode-specific-map'
;; ("C-c M-x" . consult-mode-command)
;; ("C-c h" . consult-history)
;; ("C-c k" . consult-kmacro)
;; ("C-c m" . consult-man)
;; ("C-c i" . consult-info)
([remap Info-search] . consult-info)
;; C-x bindings in `ctl-x-map'
("C-x M-:" . consult-complex-command) ;; orig. repeat-complex-command
("C-x b" . consult-buffer) ;; orig. switch-to-buffer
("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window
("C-x 5 b" . consult-buffer-other-frame) ;; orig. switch-to-buffer-other-frame
("C-x t b" . consult-buffer-other-tab) ;; orig. switch-to-buffer-other-tab
("C-x r b" . consult-bookmark) ;; orig. bookmark-jump
("C-x p b" . consult-project-buffer) ;; orig. project-switch-to-buffer
;; Custom M-# bindings for fast register access
;; ("M-#" . consult-register-load)
("M-'" . consult-register-store) ;; orig. abbrev-prefix-mark (unrelated)
;; ("C-M-#" . consult-register)
;; Other custom bindings
("M-y" . consult-yank-pop) ;; orig. yank-pop
;; M-g bindings in `goto-map'
;; ("M-g e" . consult-compile-error)
;; ("M-g f" . consult-flymake) ;; Alternative: consult-flycheck
("M-g g" . consult-goto-line) ;; orig. goto-line
("M-g M-g" . consult-goto-line) ;; orig. goto-line
;; ("M-g o" . consult-outline) ;; Alternative: consult-org-heading
;; ("M-g m" . consult-mark)
;; ("M-g k" . consult-global-mark)
("M-i" . consult-imenu)
("M-I" . consult-imenu-multi)
;; M-s bindings in `search-map'
;; ("M-s d" . consult-find) ;; Alternative: consult-fd
;; ("M-s c" . consult-locate)
;; ("M-s g" . consult-grep)
;; ("M-s G" . consult-git-grep)
;; ("M-s r" . consult-ripgrep)
("M-s l" . consult-line)
;; ("M-s L" . consult-line-multi)
;; ("M-s k" . consult-keep-lines)
;; ("M-s u" . consult-focus-lines)
;; Isearch integration
("M-s e" . consult-isearch-history)
:map isearch-mode-map
("M-e" . consult-isearch-history) ;; orig. isearch-edit-string
("M-s e" . consult-isearch-history) ;; orig. isearch-edit-string
("M-s l" . consult-line) ;; needed by consult-line to detect isearch
("M-s L" . consult-line-multi) ;; needed by consult-line to detect isearch
;; Minibuffer history
:map minibuffer-local-map
("M-s" . consult-history) ;; orig. next-matching-history-element
("M-r" . consult-history) ;; orig. previous-matching-history-element
)
;; Enable automatic preview at point in the *Completions* buffer. This is
;; relevant when you use the default completion UI.
:hook (completion-list-mode . consult-preview-at-point-mode)
;; The :init configuration is always executed (Not lazy)
:init
;; Optionally configure the register formatting. This improves the register
;; preview for `consult-register', `consult-register-load',
;; `consult-register-store' and the Emacs built-ins.
;; (setq register-preview-delay 0.5
;; register-preview-function #'consult-register-format)
;; Optionally tweak the register preview window.
;; This adds thin lines, sorting and hides the mode line of the window.
;; (advice-add #'register-preview :override #'consult-register-window)
;; Use Consult to select xref locations with preview
(setq xref-show-xrefs-function #'consult-xref
xref-show-definitions-function #'consult-xref)
;; Configure other variables and modes in the :config section,
;; after lazily loading the package.
;; :config
;; Optionally configure preview. The default value
;; is 'any, such that any key triggers the preview.
;; (setq consult-preview-key 'any)
;; (setq consult-preview-key "M-.")
;; (setq consult-preview-key '("S-<down>" "S-<up>"))
;; For some commands and buffer sources it is useful to configure the
;; :preview-key on a per-command basis using the `consult-customize' macro.
;; (consult-customize
;; consult-theme :preview-key '(:debounce 0.2 any)
;; consult-ripgrep consult-git-grep consult-grep
;; consult-bookmark consult-recent-file consult-xref
;; consult--source-bookmark consult--source-file-register
;; consult--source-recent-file consult--source-project-recent-file
;; :preview-key "M-."
;; :preview-key '(:debounce 0.4 any))
;; Optionally configure the narrowing key.
;; Both < and C-+ work reasonably well.
;; (setq consult-narrow-key "<") ;; "C-+"
;; Optionally make narrowing help available in the minibuffer.
;; You may want to use `embark-prefix-help-command' or which-key instead.
;; (keymap-set consult-narrow-map (concat consult-narrow-key " ?") #'consult-narrow-help)
)
(use-package corfu
;; Optional customizations
:custom
(corfu-cycle t) ;; Enable cycling for `corfu-next/previous'
(corfu-auto t) ;; Enable auto completion
;; (corfu-separator ?\s) ;; Orderless field separator
;; (corfu-quit-at-boundary nil) ;; Never quit at completion boundary
;; (corfu-quit-no-match nil) ;; Never quit, even if there is no match
;; (corfu-preview-current nil) ;; Disable current candidate preview
;; (corfu-preselect 'prompt) ;; Preselect the prompt
;; (corfu-on-exact-match nil) ;; Configure handling of exact matches
;; (corfu-scroll-margin 5) ;; Use scroll margin
;; Enable Corfu only for certain modes. See also `global-corfu-modes'.
;; :hook ((prog-mode . corfu-mode)
;; (shell-mode . corfu-mode)
;; (eshell-mode . corfu-mode))
;; Recommended: Enable Corfu globally. This is recommended since Dabbrev can
;; be used globally (M-/). See also the customization variable
;; `global-corfu-modes' to exclude certain modes.
:init
(global-corfu-mode))
(use-package orderless
:demand t
:custom
(completion-styles '(orderless basic))
;; (gnus-completion-styles '(orderless substring basic))
;; (completion-category-overrides '((file (styles basic partial-completion))))
;; Below not necessary if using vertico
;; (completion-category-overrides '(
;; (command (styles orderless basic partial-completion))
;; (file (styles orderless basic partial-completion))
;;;; (buffer (styles orderless basic))
;; (variable (styles orderless basic))
;; (symbol (styles orderless basic))
;; (consult-location (styles orderless))
;; (consult-multi (styles orderless))
;; )
;; )
)
;; Enable rich annotations using the Marginalia package
(use-package marginalia
;; Bind `marginalia-cycle' locally in the minibuffer. To make the binding
;; available in the *Completions* buffer, add it to the
;; `completion-list-mode-map'.
:bind (:map minibuffer-local-map
("M-A" . marginalia-cycle))
;; The :init section is always executed.
:init
;; Marginalia must be activated in the :init section of use-package such that
;; the mode gets enabled right away. Note that this forces loading the
;; package.
(marginalia-mode))
(with-eval-after-load 'dired
(require 'dired-x)
;; Set dired-x global variables here. For example:
;; (setq dired-x-hands-off-my-keys nil)
)
(add-hook 'dired-mode-hook
(lambda ()
;; Set dired-x buffer-local variables here. For example:
;; (dired-omit-mode 1)
))
Source: https://github.com/purcell/whole-line-or-region
Operate on the current line if no region is active.
(use-package whole-line-or-region
:config
(whole-line-or-region-global-mode 1)
)
Plan 9 smart terminal features, for more info: https://www.masteringemacs.org/article/complete-guide-mastering-eshell
(require 'eshell)
(require 'em-smart)
(setq eshell-where-to-jump 'begin)
(setq eshell-review-quick-commands nil)
(setq eshell-smart-space-goes-to-end t)
(add-hook 'eshell-mode-hook 'eshell-smart-initialize)
Courtesy goes to https://joelmccracken.github.io/entries/switching-between-term-mode-and-line-mode-in-emacs-term/
(require 'term)
(defun jnm/term-toggle-mode ()
"Toggles term between line mode and char mode"
(interactive)
(if (term-in-line-mode)
(term-char-mode)
(term-line-mode)))
(define-key term-mode-map (kbd "C-c C-j") 'jnm/term-toggle-mode)
(define-key term-mode-map (kbd "C-c C-k") 'jnm/term-toggle-mode)
(define-key term-raw-map (kbd "C-c C-j") 'jnm/term-toggle-mode)
(define-key term-raw-map (kbd "C-c C-k") 'jnm/term-toggle-mode)
For the keybindings, we have to defien them in both raw and line mode. From the help page of term mode: If you define custom keybindings, make sure to assign them to the correct keymap (or to both): use ‘term-raw-map’ in raw mode and ‘term-mode-map’ in line mode.
(use-package monokai-theme
:init
(load-theme 'monokai t)
)
(use-package dashboard
:config
(add-hook 'elpaca-after-init-hook #'dashboard-insert-startupify-lists)
(add-hook 'elpaca-after-init-hook #'dashboard-initialize)
(dashboard-setup-startup-hook))
Install and wait for hydra to be available since we are using it in this init.el :
(use-package hydra
:ensure (:wait t)
)
(defhydra hydra-zoom (global-map "<f1>")
"zoom"
("g" text-scale-increase "in")
("l" text-scale-decrease "out")
)
Revert C-x 1
by pressing C-x 1
again:
https://github.com/louiskottmann/zygospore.el
FYI: At one point, used this together with sr-speedbar. They did not play well together…
(use-package zygospore
:config
(global-set-key (kbd "C-x 1") 'zygospore-toggle-delete-other-windows)
)
Highlight occurences of symbol and replace them simultanously.
Shortkey: C-;
https://github.com/victorhge/iedit
(use-package iedit)
(defface highlight-angry-faces
'(
(default :background "Yellow" :foreground "Red")
)
"Angry faces highlighting."
:group 'basic-faces
)
(mapc (lambda (mode)
(font-lock-add-keywords
mode
'(
("\\<\\(FIXME\\)" 1 'highlight-angry-faces t)
("\\<\\(TODO\\)" 1 'highlight-angry-faces t)
)))
'(text-mode emacs-lisp-mode rust-mode zig-mode c-ts-mode c-mode prog-mode)
)
(add-hook 'prog-mode-hook 'electric-pair-mode)
(use-package eglot)
(setq eglot-stay-out-of '(xref))
(add-hook 'prog-mode-hook 'eglot-ensure)
(add-hook 'eglot-managed-mode-hook (lambda ()
(if (eglot-managed-p)
(add-hook 'xref-backend-functions 'eglot-xref-backend)
(remove-hook 'xref-backend-functions 'eglot-xref-backend)
)))
(use-package markdown-mode)
(use-package yasnippet
:hook
(prog-mode . yas-minor-mode)
(org-mode . yas-minor-mode)
:config
(yas-reload-all)
)
Magit depends on this and it seems it’s not installed as a dependency, so install it explicitly.
(use-package transient
:ensure (:wait t)
)
(use-package magit
:ensure (:wait t)
)
(transient-define-suffix magit-submodule-update-all ()
"Update all submodules"
:description "Update All git submodule update --init --recursive"
(interactive)
(magit-with-toplevel
(magit-run-git-async "submodule" "update" "--force")))
(transient-append-suffix 'magit-submodule "f"
'("U" magit-submodule-update-all))
(use-package dumb-jump
:init
(add-hook 'xref-backend-functions #'dumb-jump-xref-activate)
)
(add-to-list 'major-mode-remap-alist '(c-mode . c-ts-mode))
Compilation output is almost always bigger than a normal buffer. Move to the end if the compilation finishes.
(defun goto-end-compilation-buffer (comp-buffer msg)
(goto-char (point-max))
)
(add-hook 'compilation-finish-functions #'goto-end-compilation-buffer)
(use-package rust-mode
:init
(setq rust-mode-treesitter-derive t))
(use-package zig-mode)
(use-package python-mode)
(use-package multiple-cursors
:bind
("C-x r a" . mc/edit-beginnings-of-lines)
("C-x r e" . mc/edit-ends-of-lines)
("C->" . mc/mark-next-like-this)
("C-<" . mc/mark-previous-like-this)
("C-c C->" . mc/mark-all-like-this)
)
Show/highlight changes when doing undo/yanks/kills/…
https://github.com/k-talo/volatile-highlights.el
(use-package volatile-highlights
:config
(volatile-highlights-mode t)
)
Replacement for built-in comment-dwim
, more comment features.
https://github.com/remyferre/comment-dwim-2
(use-package comment-dwim-2
:config
(global-set-key (kbd "M-;") 'comment-dwim-2)
)
(use-package projectile
:config
(setq projectile-enable-caching t)
(define-key projectile-mode-map (kbd "C-x p") 'projectile-command-map)
(projectile-mode +1)
(require 'project)
(add-hook 'project-find-functions #'project-projectile)
)
Use {}
for subscripting:
https://orgmode.org/manual/Subscripts-and-superscripts.html
(setq org-use-sub-superscripts '{})
Preserve indentation in SRC blocks
(setq org-src-preserve-indentation t)
(use-package org-bullets
:config
(add-hook 'org-mode-hook (lambda () (org-bullets-mode))))
(use-package elisp-demos
:config
(advice-add 'describe-function-1 :after #'elisp-demos-advice-describe-function-1)
)
(defun myrmi/sudo-current-buffer ()
"Use TRAMP to `sudo' the current buffer."
(interactive)
(when buffer-file-name
(find-alternate-file
(concat "/sudo:root@localhost:"
buffer-file-name)
)
)
)
(defun myrmi/save-symbol-at-point ()
"Make symbol at point the latest kill in the kill ring."
(interactive)
(let ((symbol (thing-at-point 'symbol)))
(when symbol (kill-new symbol))))
(global-set-key (kbd "C-M-w") 'myrmi/save-symbol-at-point)
(defvar ceedling-project-file-name "project.yml")
(defvar ceedling-cmd "ceedling")
(defvar ceedling-project-root ".")
(defun myrmi/run-ceedling-tests (&optional file-name)
(interactive)
(let* (
(file-path (or file-name buffer-file-name))
(root-path (or (locate-dominating-file file-path ceedling-project-file-name) ceedling-project-root))
)
(compile
(concat "cd " root-path " && " ceedling-cmd)
)
)
)
(defun set-exec-path-from-shell-PATH ()
(let ((path-from-shell
(replace-regexp-in-string "[[:space:]\n]*$" ""
(shell-command-to-string "$SHELL -l -c 'echo $PATH'"))))
(setenv "PATH" path-from-shell)
(setq exec-path (split-string path-from-shell path-separator))))
(set-exec-path-from-shell-PATH)
(defun myrmi/reload-dir-locals-for-current-buffer ()
"Reload dir locals for the current buffer"
(interactive)
(let ((enable-local-variables :all))
(hack-dir-local-variables-non-file-buffer)))
(defun myrmi/reload-dir-locals-for-all-buffers-in-this-directory ()
"For every buffer with the same `default-directory` as the
current buffer, reload dir-locals."
(interactive)
(let ((dir default-directory))
(dolist (buffer (buffer-list))
(with-current-buffer buffer
(when (equal default-directory dir)
(myrmi/reload-dir-locals-for-current-buffer))))))
These snippets assume my-config-file variable is set outside this configuration. This should normally be done by the init.el to load this configuration.
(defun myrmi/visit-config ()
"Reloads ~/.emacs.d/config.org at runtime"
(interactive)
(find-file my-config-file))
(defun myrmi/reload-config ()
"Reloads ~/.emacs.d/config.org at runtime"
(interactive)
(org-babel-load-file my-config-file))
Key | Explanation |
---|---|
C-h k <key-sequence> | Lookup key sequencesmartparens wrapping |
C-q <key> | Insert <key> quoted/explicitly. F.e. to insert a tab, … |
M-x untabify/tabify | Convert to spaces/tabs |
M-x describe-bindings | List all mapped keys/commands |
M-q | Fill paragraph |