Welcome to my literal Emacs config. This document is mostly meant to document itself and keep my configuration sane enough that I myself still understand it years down the road. But feel free to pick and choose whatever is needed. I do however not recommend to just copy the entire config, which would miss the point of building one from scratch entirely.
- https://sqrtminusone.xyz/configs/emacs/#reading-documentation
- https://config.daviwil.com/emacs
- https://so.nwalsh.com/2020/02/29/dot-emacs
Of course, one needs to have Emacs installed. Start it up, and then open this literate config by pressing `M-x` (ALT/Option and x together), followed by typing in `find-file` and confirming with return. Lastly, enter the path to the config file. Again, with `M-x`, run `org-babel-tangle`. Restart emacs. This only has to be done once. After that, any change to this config file will automatically tangle it on save.
Since Emacs 28.0, it allows to have a pre-init before `init.el`. The only thing we want to do here is to disable Emacs’ internal package manager right at the start.
Add the following to `early-init.el`
;;; early-init.el --- Early Init File -*- lexical-binding: t; no-byte-compile: t -*-
(setq package-enable-at-startup nil)
I don’t want to use init.el to configure Emacs. I want to use an org file to config Emacs because I like literate configs with lots of comments. The following code block should be your init.el. This tells init.el to use the source code blocks from this file (config.org).
This is my personal literate emacs config, based losely on doom emacs.
This config uses `straight` instead of `use-package`.
(setq straight-use-package-by-default t)
(setq straight-vc-git-default-clone-depth 1)
(setq straight-recipes-gnu-elpa-use-mirror t)
(setq straight-check-for-modifications nil)
(setq use-package-always-defer t)
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
(bootstrap-version 6))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))
(straight-use-package 'use-package)
(setq comk-deferred-compilation-black-list nil)
(setq make-backup-files nil)
Can’t live without VIM bindings. Luckily emacs has evil mode, which provides these for us.
(use-package evil
:demand
:init
(setq evil-want-integration t)
(setq evil-want-keybinding nil)
(setq evil-vsplit-window-right t)
(setq evil-split-window-below t)
(setq evil-want-C-u-scroll t)
(setq evil-want-C-i-jump nil)
(setq evil-want-Y-yank-to-eol t)
:config
(evil-mode 1))
(use-package evil-collection
:after evil
:demand
:config
;;(setq evil-collection-mode-list '(dashboard dired ibuffer neotree))
(evil-collection-init))
(use-package evil-tutor :demand)
A package allowing to create custom keybindings in a quick and convenient way.
(use-package general
:demand
:config
(general-evil-setup t))
(use-package general
:demand t
:config
(general-evil-setup)
(general-create-definer lc/leader-keys
:states '(normal insert visual emacs)
:keymaps 'override
:prefix "SPC"
:global-prefix "C-SPC")
(general-create-definer lc/local-leader-keys
:states '(normal visual)
:keymaps 'override
:prefix ","
:global-prefix "SPC m")
)
(use-package all-the-icons-dired :demand)
(use-package dired-open :demand)
(use-package peep-dired :demand)
(nvmap :states '(normal visual) :keymaps 'override :prefix "SPC"
"d d" '(dired :which-key "Open dired")
"d j" '(dired-jump :which-key "Dired jump to current")
"d p" '(peep-dired :which-key "Peep-dired"))
(with-eval-after-load 'dired
;;(define-key dired-mode-map (kbd "M-p") 'peep-dired)
(evil-define-key 'normal dired-mode-map (kbd "h") 'dired-up-directory)
(evil-define-key 'normal dired-mode-map (kbd "l") 'dired-open-file) ; use dired-find-file instead if not using dired-open package
(evil-define-key 'normal peep-dired-mode-map (kbd "j") 'peep-dired-next-file)
(evil-define-key 'normal peep-dired-mode-map (kbd "k") 'peep-dired-prev-file))
(add-hook 'peep-dired-hook 'evil-normalize-keymaps)
;; Get file icons in dired
(add-hook 'dired-mode-hook 'all-the-icons-dired-mode)
With dired-open plugin, you can launch external programs for certain extensions For example, I set all .png files to open in ‘sxiv’ and all .mp4 files to open in ‘mpv’
(setq dired-open-extensions '(("gif" . "sxiv")
("jpg" . "sxiv")
("png" . "sxiv")
("mkv" . "mpv")
("mp4" . "mpv")))
These keybindings mimic the default bindings in doom emacs a lot since I got used to them.
(nvmap :states '(normal visual) :keymaps 'override :prefix "SPC"
"." '(find-file :which-key "Find file")
"f f" '(find-file :which-key "Find file")
"f r" '(counsel-recentf :which-key "Recent files")
"f s" '(save-buffer :which-key "Save file")
"f u" '(sudo-edit-find-file :which-key "Sudo find file")
"f y" '(dt/show-and-copy-buffer-path :which-key "Yank file path")
"f C" '(copy-file :which-key "Copy file")
"f D" '(delete-file :which-key "Delete file")
"f R" '(rename-file :which-key "Rename file")
"f S" '(write-file :which-key "Save file as...")
"f U" '(sudo-edit :which-key "Sudo edit file"))
(use-package counsel
:after ivy
:demand
:config (counsel-mode))
(use-package recentf
:demand
:config
(recentf-mode))
(use-package sudo-edit :demand)
Remove things like Menu, toolbar, …
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(global-display-line-numbers-mode 1)
(setq display-line-numbers-type 'relative)
(global-visual-line-mode t)
(use-package doom-modeline
:demand
:init
(doom-modeline-mode 1))
(use-package dashboard
:demand
:init ;; tweak dashboard config before loading it
(setq dashboard-set-heading-icons t)
(setq dashboard-set-file-icons t)
(setq dashboard-banner-logo-title "Emacs Is Org-Mode and Org-Mode is life!")
(setq dashboard-center-content nil) ;; set to 't' for centered content
(setq dashboard-items '((recents . 5)
(agenda . 5 )
(bookmarks . 3)
(projects . 3)
(registers . 3)))
:config
(dashboard-setup-startup-hook)
(dashboard-modify-heading-icons '((recents . "file-text")
(bookmarks . "book"))))
Defining our fonts. Right now I’m using Source Code Pro (SauceCodePro) from the nerd-fonts repository. Installed from the AUR, it does NOT
include all variations of the font (such as italics). You can download the italics Source Code Pro font from the nerd-fonts GitHub though.
(set-face-attribute 'default nil
;:font "PragmataPro Liga"
:font "Roboto Mono"
:height 140
:weight 'medium)
(set-face-attribute 'variable-pitch nil
;:font "PragmataPro Liga"
:font "Roboto Mono"
:height 140
:weight 'medium)
(set-face-attribute 'fixed-pitch nil
;:font "PragmataPro Mono Liga"
:font "Roboto Mono"
:height 140
:weight 'medium)
;; Makes commented text and keywords italics.
;; This is working in emacsclient but not emacs.
;; Your font must have an italic face available.
(set-face-attribute 'font-lock-comment-face nil
:slant 'italic)
(set-face-attribute 'font-lock-keyword-face nil
:slant 'italic)
;; Uncomment the following line if line spacing needs adjusting.
(setq-default line-spacing 0.12)
;; Needed if using emacsclient. Otherwise, your fonts will be smaller than expected.
;;(add-to-list 'default-frame-alist '(font . "PragmataPro Liga-11"))
;; changes certain keywords to symbols, such as lamda!
(setq global-prettify-symbols-mode t)
You can use the bindings CTRL plus =/- for zooming in/out. You can also use CTRL plus the mouse wheel for zooming in/out.
;; zoom in/out like we do everywhere else.
(global-set-key (kbd "C-=") 'text-scale-increase)
(global-set-key (kbd "C--") 'text-scale-decrease)
(global-set-key (kbd "<C-wheel-up>") 'text-scale-increase)
(global-set-key (kbd "<C-wheel-down>") 'text-scale-decrease)
(use-package rainbow-delimiters
:demand
:config
(add-hook 'prog-mode-hook 'rainbow-delimiters-mode))
By default in Emacs, we don’t have ability to select text, and then start typing and our new text replaces the selection. Let’s fix that!
(delete-selection-mode t)
All hail the king of trees!
(use-package neotree
:demand
:config
(setq neo-smart-open t
neo-window-width 30
neo-theme (if (display-graphic-p) 'icons 'arrow)
;;neo-window-fixed-size nil
inhibit-compacting-font-caches t)
;projectile-switch-project-action 'neotree-projectile-action)
;; truncate long file names in neotree
(add-hook 'neo-after-create-hook
#'(lambda (_)
(with-current-buffer (get-buffer neo-buffer-name)
(setq truncate-lines t)
(setq word-wrap nil)
(make-local-variable 'auto-hscroll-mode)
(setq auto-hscroll-mode nil))))
:general
(lc/leader-keys
"t" '(:wk "Toggle")
"t n" '(neotree-toggle :wk "Toggle neotree")
"d n" '(neotree-dir :wk "Open directory in neotree")
))
(use-package dtrt-indent
:demand)
Set up our roam directory and some basic defaults
(require 'org)
(add-hook 'org-mode-hook 'org-indent-mode)
(setq org-directory "~/roam/org"
org-log-done 'time
org-hide-emphasis-markers t)
(setq org-src-preserve-indentation nil
org-src-tab-acts-natively t
org-edit-src-content-indentattion 0)
(setq org-return-follows-link t)
(setq org-todo-keywords
'((sequence "TODO(t!)" "WAIT(@/!)" "|" "DONE(d!)" "CANCELED(c@)")))
(use-package org-contrib :demand)
(setq org-link-frame-setup
'((file . find-file)))
(setq org-startup-with-inline-images t)
(setq org-confirm-babel-evaluate nil)
(require 'ob-shell)
(use-package ob-async :demand)
(defun no-hide-overlays (orig-fun &rest args)
(setq org-babel-hide-result-overlays nil))
(advice-add 'ob-async-org-babel-execute-src-block :before #'no-hide-overlays)
(nvmap :prefix "SPC"
"o a" '(org-agenda :wk "show agenda"))
(require 'ob-lilypond)
(setq org-babel-lilypond-ly-command "lilypond.sh")
(use-package evil-org
:demand
:after org
:init
(add-hook 'org-mode-hook (lambda()
(define-key
evil-normal-state-local-map
(kbd "M-RET")
#'org-meta-return)))
:hook (org-mode . (lambda () evil-org-mode)))
This just helps us make org look a bit more modern than just plain text
(use-package org-modern
:demand
:after org
:config
(setq org-pretty-entities nil)
(global-org-modern-mode))
(use-package org-download
:demand
:after org
:config
(setq org-download-screenshot-method "screencapture -i %s")
(setq-default org-download-image-dir "~/roam/org/attachments/screenshots")
:general
(lc/leader-keys
"s y" '(org-download-screenshot :wk "Capture Screenshot")
"s c" '(org-download-clipboard :wk "Insert image from clipboard")
"s d" '(org-download-image :wk "Download image")))
(use-package org-tree-slide
:config
(global-set-key (kbd "<f8>") 'org-tree-slide-mode)
(global-set-key (kbd "S-<f8>") 'org-tree-slide-skip-done-toggle)
(define-key org-tree-slide-mode-map (kbd "<f9>")
'org-tree-slide-move-previous-tree)
(define-key org-tree-slide-mode-map (kbd "<f10>")
'org-tree-slide-move-next-tree)
(define-key org-tree-slide-mode-map (kbd "<f11>")
'org-tree-slide-content)
(setq org-tree-slide-skip-outline-level 4)
(org-tree-slide-narrowing-control-profile)
(setq org-tree-slide-skip-done nil)
:demand)
The best of the best when it comes to taking comprehensive notes without getting lost in file structures.
(use-package org-roam
:demand
:after org
:init
(setq org-directory (file-truename "~/roam/org"))
(setq org-roam-directory (file-truename "~/roam/org"))
(setq lc-static-directory (file-truename "~/roam/static/generated"))
(setq org-agenda-files (directory-files-recursively org-directory "\\.org$"))
(setq org-roam-v2-ack t)
(setq org-roam-completion-everywhere t)
(setq org-roam-capture-templates
'(("d" "default" plain "%?" :target
(file+head "personal/%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n") :unnarrowed t)
("c" "contact" plain "%?" :target
(file+head "contacts/%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n") :unnarrowed t)
("w" "work" plain "%?" :target
(file+head "work/%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n") :unnarrowed t)))
(setq org-roam-dailies-capture-templates
'(("d" "default" plain
"* %?"
:target (file+head "personal/journal-%<%Y%m%d>.org" "#+title: Journal - %<%Y-%m-%d>\n") :unnarrowed t)
("w" "work" plain " * %?" :target
(file+head "work/work-%<%Y%m%d>.org" "#+title: Work Journal - %<%Y-%m-%d>\n") :unnarrowed t)))
(setq org-roam-mode-sections
(list #'org-roam-backlinks-section
#'org-roam-reflinks-section
#'org-roam-unlinked-references-section
))
(add-to-list 'display-buffer-alist
'("\\*org-roam\\#"
(display-buffer-in-side-window)
(side . right)
(slot . 0)
(window-width . 0.33)
(window-parameters . ((no-other-window . t)
(no-delete-other-windows . t)))))
:general
(lc/leader-keys
"TAB n" '((lambda () (interactive) (persp-switch "notes")) :wk "notes")
"n" '(:wk "roam")
"n f" '(org-roam-node-find :wk "find node")
"n i" '(org-roam-node-insert :wk "insert node")
"n c" '(org-roam-capture :wk "capture")
"n t" '(org-roam-tag-add :wk "add tag")
"n r" '(org-roam-ref-add :wk "add ref")
"n a" '(:wk "add alias")
"n a a" '(org-roam-alias-add :wk "add alias")
"n a r" '(org-roam-alias-remove :wk "add alias")
"n g" '(org-roam-graph :wk "show roam graph")
"n j" '(org-roam-dailies-capture-today :wk "capture today")
"n J" '(org-roam-dailies-goto-today :wk "goto today")
"n d" '(org-roam-dailies-goto-date :wk "goto date")
"t b" '(org-roam-buffer-toggle :wk "roam buffer")
)
:config
(org-roam-setup)
)
(require 'org-roam)
(defun lc/org-roam-filter-by-tag (tag-name)
(lambda (node)
(member tag-name (org-roam-node-tags node))))
(defun lc/org-roam-list-notes-by-tag (tag-name)
(mapcar #'org-roam-node-file
(seq-filter
(lc/org-roam-filter-by-tag tag-name)
(org-roam-node-list))))
(defun lc/org-roam-refresh-agenda-list ()
(interactive)
(setq org-agenda-files (append
(lc/org-roam-list-notes-by-tag "todo")
(lc/org-roam-list-notes-by-tag "project"))))
(lc/org-roam-refresh-agenda-list)
(nvmap :prefix "SPC"
"o r" '(lc/org-roam-refresh-agenda-list :wk "refresh agenda"))
This next section handles cancelled or finished todos for us. Whenever a todo gets cancelled or finished, we make a copy of it into our daily notes. This way the node itself can later be cleaned up, but we keep a record of what was accomplished that day.
(defun lc/org-roam-copy-todo-to-today ()
(interactive)
(let ((org-refile-keep t)
(org-roam-dailies-capture-templates
'(("d" "default" plain
"* %?"
:if-new (file+head+olp "personal/%<%Y%m%d>.org" "#+title: Journal - %<%Y-%m-%d>\n" ("Tasks")))))
(org-after-refile-insert-hook #'save-buffer)
today-file
pos)
(save-window-excursion
(org-roam-dailies--capture (current-time) t)
(setq today-file (buffer-file-name))
(setq pos (point)))
(unless (equal (file-truename today-file)
(file-truename (buffer-file-name)))
(org-refile nil nil (list "Tasks" today-file nil pos)))))
(add-to-list 'org-after-todo-state-change-hook
(lambda ()
(when (or
(equal org-state "DONE")
(equal org-state "CANCELED"))
(lc/org-roam-copy-todo-to-today))))
(use-package org-roam-timestamps
:after org-roam
:config (org-roam-timestamps-mode))
Org Roam UI is a little add-on for org-roam that adds an interactive graph of all roam notes that is viewable in the browser.
(use-package websocket
:after org-roam)
(use-package org-roam-ui
:demand
:config
(setq org-roam-ui-sync-theme t
org-roam-ui-follow t
org-roam-ui-update-on-save t
org-roam-ui-open-on-start t)
:general
(lc/leader-keys
"n s" '(org-roam-ui-open :wk "show ui")))
(use-package ox-hugo
:demand)
(defun clinton/org-roam--extract-note-body (file)
(with-temp-buffer
(insert-file-contents file)
(org-mode)
(car (org-element-map (org-element-parse-buffer) 'paragraph
(lambda (paragraph)
(let ((begin (plist-get (car (cdr paragraph)) :begin))
(end (plist-get (car (cdr paragraph)) :end)))
(buffer-substring begin end)))))))
(defun file-path-to-slug (path)
(let* ((file-name (car (last (split-string path "--"))))
(title (car (split-string file-name "\\."))))
(replace-regexp-in-string (regexp-quote "_") "-" title nil 'literal)))
(defun file-path-to-md-file-name (path)
(let ((file-name (car (last (split-string path "/")))))
(concat (car (split-string file-name "\\.")) ".md")))
(use-package projectile
:demand
:config
(projectile-global-mode 1))
(use-package yasnippet
:demand
:config
(yas-global-mode 1))
(use-package ivy
:defer 0.1
:diminish
:bind
(("C-c C-r" . ivy-resume)
("C-x B" . ivy-switch-buffer-other-window))
:custom
(setq ivy-count-format "(%d/%d) ")
(setq ivy-use-virtual-buffers t)
(setq enable-recursive-minibuffers t)
:config
(ivy-mode))
(use-package corfu
:demand
:straight (corfu :files (:defaults "extensions/*")
:includes (corfu-popupinfo))
:config
(setq corfu-auto t)
(setq corfu-cycle t)
(setq corfu-popupinfo-delay t)
:init
(global-corfu-mode)
(corfu-history-mode t))
(setq tab-always-indent 'complete)
(add-hook 'corfu-mode-hook #'corfu-popupinfo-mode)
(use-package kind-icon
:after corfu
:config
(add-to-list 'corfu-margin-formatters #'kind-icon-margin-formatter)
:demand)
;; overriding image.el function image-type-available-p
(defun image-type-available-p (type)
"Return t if image type TYPE is available.
Image types are symbols like `xbm' or `jpeg'."
(if (eq 'svg type)
nil
(and (fboundp 'init-image-library)
(init-image-library type))))
(use-package orderless
:demand
:init
(setq completion-styles '(orderless basic)
))
(use-package flycheck :demand)
(defun corfu-lsp-setup ()
(setq-local completion-styles '(orderless)
completion-category-defaults nil))
(use-package lsp-mode
:demand
:init
:config
(setq lsp-enable-symbol-highlighting t)
:hook (
(rust-mode . lsp)
(lsp-mode . lsp-enable-which-key-integration))
:commands lsp)
(use-package markdown-mode :demand)
(setq lsp-completion-provider :none)
(add-hook 'lsp-mode-hook #'corfu-lsp-setup)
(use-package lsp-ui :demand :commands lsp-ui-mode
:init
(setq lsp-ui-sideline-enable t
lsp-ui-sideline-show-diagnostics t
lsp-ui-sideline-show-symbol t
lsp-ui-sideline-show-hover t
lsp-ui-sideline-show-actions t
lsp-ui-sideline-delay 0
lsp-ui-peek-enable t
lsp-ui-doc-enhanced-markdown t)
:bind
:general
(lc/leader-keys
"t i" '(lsp-ui-imenu :wk "Show imenu")
"t k" '(lsp-ui-imenu--kill :wk "Hide imenu")
"c" '(:wk "Code actions")
"c r" '(lsp-ui-peek-find-references :wk "Show references")
"c j" '(lsp-ui-peek-find-definitions :wk "Find definitions")
"c i" '(lsp-ui-peek-find-implementation :wk "Find implementation"))
:hook
(lsp-mode . lsp-ui-mode)
)
(use-package lsp-ivy :demand :commands lsp-ivy-workspace-symbol)
(use-package tree-sitter :demand)
(use-package tree-sitter-langs :demand)
(global-tree-sitter-mode)
(use-package ccls
:demand)
(use-package rustic
:config
(setq rustic-lsp-client 'eglot)
:demand)
(use-package haskell-mode
:demand)
(add-hook 'haskell-mode-hook #'lsp)
(use-package lsp-haskell :demand)
(use-package python-mode
:demand)
(use-package scala-mode
:demand
:interpreter
("scala" . scala-mode))
(use-package graphql-mode
:demand)
(use-package ob-graphql
:demand)
(use-package nix-mode
:demand)
(use-package yaml-mode
:demand)
Best Git client, second best feature ofter org mode
(use-package magit
:demand
:general
(lc/leader-keys
"g" '(:wk "Magit")
"g s" '(magit-status :wk "Status")
"g l" '(magit-log-all :wk "Log")
"g C" '(magit-checkout :wk "Checkout")
"g c c" '(magit-commit :wk "Commit")
"g c a" '(magit-commit-amend :wk "Amend")
"g p" '(magit-push-to-remote :wk "Push")
))
(use-package diff-hl
:demand)
(add-hook 'magit-pre-refresh-hook 'diff-hl-magit-pre-refresh)
(add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh)
(winner-mode 1)
(nvmap :prefix "SPC"
;; Window splits
"w" '(:wk "Window Management")
"w c" '(evil-window-delete :which-key "Close window")
"w n" '(evil-window-new :which-key "New window")
"w s" '(evil-window-split :which-key "Horizontal split window")
"w v" '(evil-window-vsplit :which-key "Vertical split window")
;; Window motions
"w h" '(evil-window-left :which-key "Window left")
"w j" '(evil-window-down :which-key "Window down")
"w k" '(evil-window-up :which-key "Window up")
"w l" '(evil-window-right :which-key "Window right")
"w <left>" '(evil-window-left :which-key "Window left")
"w <down>" '(evil-window-down :which-key "Window down")
"w <up>" '(evil-window-up :which-key "Window up")
"w <right>" '(evil-window-right :which-key "Window right")
"w w" '(evil-window-next :which-key "Goto next window")
;; winner mode
"w u" '(winner-undo :which-key "Winner undo")
"w r" '(winner-redo :which-key "Winner redo"))
We need a nice colorscheme. The Doom Emacs guys have a nice collection of themes, so let’s install them!
(use-package doom-themes :demand)
(use-package cyberpunk-theme :demand)
(use-package solo-jazz-theme :demand)
(use-package moe-theme :demand)
(use-package exotica-theme :demand)
(use-package flucui-themes
:demand)
(use-package hemisu-theme
:demand)
(use-package kaolin-themes
:demand
:config
(kaolin-treemacs-theme))
(use-package mindre-theme
:straight (:host github :repo "erikbackman/mindre-theme")
:demand)
(use-package bespoke-themes
:straight (:host github :repo "mclear-tools/bespoke-themes" :branch "main")
:demand)
(setq doom-themes-enable-bold t ; if nil, bold is universally disabled
doom-themes-enable-italic t) ; if nil, italics is universally disabled
(load-theme 'moe-light t)
(defun lc/org-theme ()
(interactive)
(load-theme 'leuven t))
(defun lc/normal-theme ()
(interactive)
(load-theme 'kaolin-aurora))
(nvmap :states '(normal visual) :keymaps 'override :prefix "SPC"
"a l" '(lc/org-theme :which-key "Leuven Theme")
"a n" '(lc/normal-theme :which-key "Aurora Theme"))
Which-key is a minor mode for Emacs that displays the key bindings following your currently entered incomplete command (a prefix) in a popup.
NOTE:
Which-key has an annoying bug that in some fonts and font sizes, the bottom row in which key gets covered up by the modeline.
(use-package which-key
:demand
:init
(setq which-key-side-window-location 'bottom
which-key-sort-order #'which-key-key-order-alpha
which-key-sort-uppercase-first nil
which-key-add-column-padding 1
which-key-max-display-columns nil
which-key-min-display-lines 6
which-key-side-window-slot -10
which-key-side-window-max-height 0.25
which-key-idle-delay 0.8
which-key-max-description-length 25
which-key-allow-imprecise-window-fit t
which-key-separator " → " ))
(which-key-mode)
(push "~/.nix-profile/share/emacs/site-lisp/mu4e" load-path)
(require 'mu4e)
(setq mail-user-agentt 'mu4e-user-agent)
(setq mu4e-maildir-shortcuts
'(
(:maildir "/Gmail/INBOX" :key ?i))
)
(setq mu4e-get-mail-command "offlineimap")
(setq mu4e-sent-messages-behavior 'delete)
(setq
user-email-address "[email protected]"
user-full-name "Simon Wollwage")
(setq message-kill-buffer-on-exit t)
(require 'smtpmail)
(setq message-send-mail-function 'smtpmail-send-it
startttls-use-gnutls t
smtpmail-startttls-credentials '(("smtp.gmail.com" 587 nil nil))
smtpmail-auth-credentials '(("smtp.gmail.com" 587 "[email protected]" nil))
smtpmail-default-smtp-server "smtp.gmail.com"
smtpmail-smtp-server "smtp.gmail.com"
smtpmail-smtp-service 587)
(nvmap :prefix "SPC"
"t m" '(mu4e :wk "MU4E"))
(use-package nov
:demand)
(use-package gh
:straight (
:repo "sigma/gh.el"
:host github
:branch "master")
:demand)
(use-package gist
:straight (
:repo "defunkt/gist.el"
:host github
:branch "master")
:demand)
(use-package hledger-mode
:mode ("\\.journal\\'" "\\.hledger\\'")
:commands hledger-enable-reporting
:demand
:bind (:map hledger-mode-map
("TAB" . completion-at-point))
:preface
(defun popup-balance-at-point ()
"Show balance for account at point in a popup."
(interactive)
(if-let ((account (thing-at-point 'hledger-account)))
(message (hledger-shell-command-to-string (format " balance -N %s "
account)))
(message "No account at point")))
:config
:config
(add-hook 'hledger-view-mode-hook #'hl-line-mode)
(add-hook 'hledger-view-mode-hook #'center-text-for-reading)
(add-hook 'hledger-view-mode-hook
(lambda ()
(run-with-timer 1
nil
(lambda ()
(when (equal hledger-last-run-command
"balancesheet")
;; highlight frequently changing accounts
(highlight-regexp "^.*\\(savings\\|cash\\).*$")
(highlight-regexp "^.*credit-card.*$"
'hledger-warning-face))))))
(add-hook 'hledger-mode-hook
(lambda ()
(make-local-variable 'company-backends)
(add-to-list 'company-backends 'hledger-company)))
(setq hledger-input-buffer-height 20)
(add-hook 'hledger-input-post-commit-hook #'hledger-show-new-balances)
(add-hook 'hledger-input-mode-hook #'auto-fill-mode)
(add-hook 'hledger-input-mode-hook
(lambda ()
(make-local-variable 'company-idle-delay)
(setq-local company-idle-delay 0.1))))
(require 'hledger-input)
# -*- mode: snippet -*-
# contributor: Daniel Hitzel
# name: use-package
# key: up
# --
(use-package ${1:package-name}
:demand)
# -*- mode: snippet -*-
# name: src
# key: <src
# --
$0
#+end_src
# -*- mode: snippet -*-
# name: snippet
# key: <sn
# --
#+begin_src ${1:lang} :mkdirp yes :tangle ~/.emacs.d/snippets/${2:mode}/${3:name}
$0
#+end_src
# -*- mode: snippet -*-
# name: emacs-lisp
# key: <em
# --
$0
#+end_src
# -*- mode: snippet -*-
# name: shell
# key: <sh
# --
#+begin_src sh :results ${1:result}
$0
#+end_src
# -*- mode: snippet -*-
# name: ssh
# key: <ssh
# --
#+begin_src sh :results ${1:result} :dir /ssh:${2:server}:${3:path}
$0
#+end_src
# -*- mode: snippet -*-
# name: docker
# key: <docker
# --
#+begin_src sh :results ${1:result} :dir /docker:${2:container}:${3:path}
$0
#+end_src
# -*- mode: snippet -*-
# name: rust
# key: <rust
# --
#+begin_src rust :results ${1:result} :tangle ${2:no}
$0
#+end_src
# -*- mode: snippet -*-
# name: impl FromStr for Type { fn from_str(...) }
# key: fromstr
# --
impl FromStr for ${1:Type} {
type Err = ${2:Error};
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self{})
}
}
# -*- mode: snippet -*-
# name: impl Display for Type { fn fmt (...) }
# key: display
# --
impl Display for ${1:Type} {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "$0")
}
}
;; Local Variables: ;; eval: (add-hook ‘after-save-hook (lambda ()(if (y-or-n-p “Reload?”)(load-file user-init-file))) nil t) ;; eval: (add-hook ‘after-save-hook (lambda ()(if (y-or-n-p “Tangle?”)(org-babel-tangle))) nil t) ;; End: