Iβve declared configuration bankruptcy many times before this. Hereβs to hoping a literate configuration sticks.
With native comp enabled there tends to be a lot of annoying warnings. To not go insane Iβll turn this off.
(defvar native-comp-deferred-compilation-deny-list nil)
(setq comp-async-report-warnings-errors nil)Start the emacs server so emacsclient can connect to it.
(server-start)I use straight.el to manage my packages.
Enable straight to use use-package by default before bootstrapping.
(setq straight-use-package-by-default t)We bootstrap straight.el with the following.
(defvar bootstrap-version)
(let ((bootstrap-file
(expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
(bootstrap-version 5))
(unless (file-exists-p bootstrap-file)
(with-current-buffer
(url-retrieve-synchronously
"https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
'silent 'inhibit-cookies)
(goto-char (point-max))
(eval-print-last-sexp)))
(load bootstrap-file nil 'nomessage))I use the use-package straight integration to make switching back to use-package easier. First we install use-package with straight.el.
(straight-use-package 'use-package)(use-package exec-path-from-shell
:config
(setq exec-path-from-shell-variables '("PATH" "SHELL"))
(exec-path-from-shell-initialize))Disable startup message.
(setq inhibit-startup-message t)Disable the scrollbar
(scroll-bar-mode -1)Disable the toolbar
(tool-bar-mode -1)Disable the menu bar.
(menu-bar-mode -1)(set-face-attribute 'default nil :font "JetbrainsMono Nerd Font" :height 180)I like Doom Themes because they offer the best integration with various syntaxes.
;; (use-package doom-themes
;; :config
;; ;; Global settings (defaults)
;; (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 'doom-gruvbox t)
;; ;; Enable flashing mode-line on errors
;; (doom-themes-visual-bell-config)
;; ;; Corrects (and improves) org-mode's native fontification.
;; (doom-themes-org-config))The GOAT.
;; (use-package zenburn-theme
;; :config
;; (setq zenburn-use-variable-pitch t)
;; ;; scale headings in org-mode
;; (setq zenburn-scale-org-headlines t)
;; ;; scale headings in outline-mode
;; (setq zenburn-scale-outline-headlines t)
;; ;; enable theme
;; (load-theme 'zenburn t));; (use-package poet-theme
;; :config
;; ;; enable theme
;; (load-theme 'poet t))See here.
(use-package ef-themes
:config
(setq ef-themes-to-toggle '(ef-summer ef-winter))
(setq ef-themes-headings ; read the manual's entry or the doc string
'((0 . (variable-pitch light 1.9))
(1 . (variable-pitch light 1.8))
(2 . (variable-pitch regular 1.7))
(3 . (variable-pitch regular 1.6))
(4 . (variable-pitch regular 1.5))
(5 . (variable-pitch 1.4)) ; absence of weight means `bold'
(6 . (variable-pitch 1.3))
(7 . (variable-pitch 1.2))
(t . (variable-pitch 1.1))))
(setq ef-themes-mixed-fonts t
ef-themes-variable-pitch-ui t)
(mapc #'disable-theme custom-enabled-themes)
(load-theme 'ef-winter :no-confirm))(use-package doom-modeline
:config
(doom-modeline-mode 1))which-key is great for getting an overview of what keybindings are available.
(use-package which-key
:init (which-key-mode)
:diminish which-key-mode
:config
(setq which-key-idle-delay 0.3))(use-package page-break-lines)
(use-package dashboard
:ensure t
:config
(dashboard-setup-startup-hook))For undo/redo to work nicely with Evil mode we use undo-tree.
(use-package undo-tree
:ensure t
:after evil
:diminish
:config
(evil-set-undo-system 'undo-tree)
(global-undo-tree-mode 1)) I grew up on Vim keybindings, so Evil at heart.
(use-package evil
:init
(setq evil-want-integration t)
(setq evil-want-keybinding nil)
:config
(evil-mode t)
(with-eval-after-load 'evil-maps
(define-key evil-motion-state-map (kbd "RET") nil))
(fset 'evil-visual-update-x-selection 'ignore))We also install evil-collection so other modes in Emacs work too. These include magit, calendar etc.
(use-package evil-collection
:after evil
:config
(evil-collection-init))evil-commentary provides a simular gcc keybinding as in Vim.
(use-package evil-commentary
:config
(evil-commentary-mode))Get a Vim surround equivalent.
(use-package evil-surround
:after (evil)
:config
(global-evil-surround-mode 1))Use Evil in org-mode and org-mode agenda. For keybindings see here.
(use-package evil-org
:ensure t
:after org
:hook (org-mode . (lambda () evil-org-mode))
:config
(require 'evil-org-agenda)
(evil-org-agenda-set-keys))I use general to define various keymaps based on different modes. I also define a handy function to define various leader key mappings.
(use-package general
:config
(general-evil-setup t)
(general-create-definer rkn/keymap-define-global
:keymaps '(normal insert visual emacs)
:prefix "SPC"
:global-prefix "M-SPC")
(general-create-definer rkn/keymap-define-map
:states '(normal)
:prefix "SPC"
:global-prefix "M-SPC"
:major-modes t))Set ispell to use the aspell binary.
(setq ispell-program-name "aspell")(use-package flycheck
:ensure t
:init (global-flycheck-mode))For jumping between git projects quickly.
(use-package projectile
:diminish projectile-mode
:config
(projectile-mode))Use a lightweight completion engine such as vertico.
(use-package vertico
:init
(vertico-mode)
;; Wrap around list
(setq vertico-cycle t)
)Combine vertico with orderless for better completion typing. Typing a SPC after a completion narrows down a list some more.
(use-package orderless
:init
(setq completion-styles '(orderless)
completion-category-defaults nil
completion-category-overrides '((file (styles . (partial-completion))))))This puts your last used command/completion to the top of the list.
(use-package savehist
:init
(savehist-mode))Consult provides some extra completion for built-in emacs functions.
(use-package consult
:init
(setq consult-project-root-function #'projectile-project-root)
:config
(setq consult-find-args (concat "find . "
"-not ( -wholename */.git/* -prune ) "
"-not ( -wholename */.venv/* -prune ) ")))Provides helpful annotations to commands/functions. For files it also displays file permissions etc.
(use-package marginalia
:init
(marginalia-mode))For some pretty eye candy.
After installation you need to install icon fonts with:
M-x all-the-icons-install-fonts
(use-package all-the-icons
:if (display-graphic-p))
(use-package all-the-icons-completion
:init
(all-the-icons-completion-mode)
(add-hook 'marginalia-mode-hook #'all-the-icons-completion-marginalia-setup))Company is a text completion framework for Emacs. It stands for βCOMplete ANYthingβ.
(use-package company
:config
(global-company-mode))(use-package lsp-mode
:init
;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l")
(setq lsp-keymap-prefix "C-c l")
:hook ((lsp-mode . lsp-enable-which-key-integration))
:commands lsp)(use-package lsp-ui :commands lsp-ui-mode)(use-package magit)Allow emacs to ask for GPG password.
(use-package pinentry
:config
(setq epa-pinentry-mode 'loopback)
(pinentry-start))I use org-mode for managing this config and for tending to my Digital Garden.
(use-package org)This fixes the strange indentation in src blocks after hitting the return key in org files.
(setq org-edit-src-content-indentation 0
org-src-tab-acts-natively t
org-src-preserve-indentation t)Enable word and line wrapping in org-mode using visual mode
(add-hook 'org-mode-hook 'visual-line-mode)(setq org-todo-keywords
'((sequence "TODO" "BLOCKED" "DONE")))
(setq org-todo-keyword-faces
'(("TODO" . org-warning)
("BLOCKED" . "red")))(setq current-journal-file (expand-file-name (format-time-string "~/Dropbox/DigitalGarden/journals/%Y-%m-%b.org")))
(setq org-capture-templates
'(("p" "Day Planning" entry (file+olp+datetree current-journal-file)
"* Day Planning %U
** Thoughts / diary / fleeting notes
** Tasks for today [/]
*** TODO %?
** Tasks that will satisfy end-of-the-day me [/]
** Focus Blocks
** Habits [/]
- [ ] Are you satisfied with the number of pomodori?
- [ ] Did you tend to your Digital Garden?")))I use org-superstar to make a bullets and sections look less ugly.
(use-package org-superstar
:after (org)
:config
(setq org-superstar-leading-bullet ?\s
org-superstar-leading-fallback ?\s
org-hide-leading-stars nil
org-superstar-todo-bullet-alist
'(("TODO" . 9744)
("[ ]" . 9744)
("DONE" . 9745)
("[X]" . 9745)))
:hook
(org-mode . (lambda () (org-superstar-mode 1))))(use-package org-autolist
:config
(add-hook 'org-mode-hook (lambda () (org-autolist-mode)))) Sometimes my org file are too long and Iβd like to open them with headings collapsed.
(setq org-startup-folded t)Enable spell checking in org-mode.
(add-hook 'org-mode-hook 'flyspell-mode)Sometimes my org-captureβs would have an ugly coloring.
(setq bookmark-fontify nil)I use Olivetti for this
(use-package olivetti)The below variable needs to be in order to allow for RET to follow a link. If you are using Evil (like I am) you also need to unbind RET from Evil. This shouldnβt matter since RET is not bound to anything useful anyway.
(setq org-return-follows-link t)(setq org-startup-indented t)In order to tangle certain languages we code blocks we need to define the following:
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)
(python . t)))To enable auto-tangling on save we define a custom function.
(defun rkn/org-babel-tangle-dont-ask ()
(when (string-equal (buffer-file-name) (expand-file-name "~/.config/dotfiles/modules/editors/emacs/config/emacs.org"))
(let ((org-confirm-babel-evaluate nil))
(org-babel-tangle))))We then invoke this function as an org-mode-hook.
(add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook #'rkn/org-babel-tangle-dont-ask
'run-at-end 'only-in-org-mode)))(use-package org-pomodoro)Helpful to see what Iβve been working on or plan to work on.
(setq org-agenda-custom-commands
'(
("c" . "My Custom Agendas")
("cu" "Unscheduled TODO"
((todo ""
((org-agenda-overriding-header "\nUnscheduled TODO")
(org-agenda-skip-function '(org-agenda-skip-entry-if 'timestamp)))))
nil
nil)
("cw" "Weekly Review"
((agenda ""
((org-agenda-start-day "-7d")
(org-agenda-span 14)
(org-agenda-start-on-weekday 1)
(org-agenda-archives-mode t)))
(alltodo "")))
("n" "Agenda and all TODOs"
((agenda #1="")
(alltodo #1#)))))(use-package clojure-mode
:after (flycheck-clj-kondo)
:ensure t
:config
(require 'flycheck-clj-kondo)
(add-hook 'clojure-mode-hook 'enable-paredit-mode)
(add-hook 'clojure-mode-hook 'lsp)
(add-hook 'clojurescript-mode-hook 'enable-paredit-mode)
(add-hook 'clojurescript-mode-hook 'lsp)
(add-hook 'clojurec-mode-hook 'lsp)
(setq clojure-indent-style 'align-arguments)
(setq clojure-align-forms-automatically t)
(setq gc-cons-threshold (* 100 1024 1024)
read-process-output-max (* 1024 1024)
treemacs-space-between-root-nodes nil
company-minimum-prefix-length 1
lsp-lens-enable t
lsp-signature-auto-activate nil
; lsp-enable-indentation nil ; uncomment to use cider indentation instead of lsp
; lsp-enable-completion-at-point nil ; uncomment to use cider completion instead of lsp
))(use-package flycheck-clj-kondo)(use-package cider)(use-package clj-refactor
:ensure t
:init
(add-hook 'clojure-mode-hook 'clj-refactor-mode)
(add-hook 'clojurescript-mode-hook 'clj-refactor-mode)
:diminish clj-refactor-mode)(use-package aggressive-indent
:config
(add-hook 'clojure-mode-hook #'aggressive-indent-mode)
(add-hook 'clojurescript-mode-hook #'aggressive-indent-mode))(use-package rainbow-delimiters
:ensure t
:init
(add-hook 'clojure-mode-hook 'rainbow-delimiters-mode)
(add-hook 'clojurescript-mode-hook 'rainbow-delimiters-mode)
:diminish rainbow-delimiters-mode)(use-package lispyville
:after (org)
:init
(general-add-hook '(emacs-lisp-mode-hook lisp-mode-hook clojure-mode-hook clojurescript-mode-hook) #'lispyville-mode)
:config
(lispyville-set-key-theme '(operators c-w additional commentary slurp/barf-cp)))(use-package dockerfile-mode
:mode "Dockerfile\\'")(use-package markdown-mode
:commands (markdown-mode gfm-mode)
:mode (("README\\.md\\'" . gfm-mode)
("\\.md\\'" . markdown-mode)
("\\.markdown\\'" . markdown-mode))
:init (setq markdown-command "multimarkdown"))Enable word and line wrapping in markdown modes using visual mode
(add-hook 'markdown-mode-hook 'visual-line-mode)
(add-hook 'gfm-mode-hook 'visual-line-mode)Enable spell checking in markdown-mode.
(add-hook 'markdown-mode-hook 'flyspell-mode)(use-package lsp-pyright
:ensure t
:hook (python-mode . (lambda ()
(require 'lsp-pyright)
(lsp)))) ; or lsp-deferred(use-package python-black
:demand t
:after python
:hook (python-mode . python-black-on-save-mode))Pipfile should use conf-toml-mode.
(add-to-list 'auto-mode-alist '("\\Pipfile\\'" . conf-toml-mode))(use-package yaml-mode
:mode "\\.(yml|yaml)\\'")(use-package rustic)(use-package terraform-mode)(use-package nim-mode
:ensure t
:hook
(nim-mode . lsp))(use-package nix-mode
:mode "\\.nix\\'"
:config
(setq nix-nixfmt-bin "~/.nix-profile/bin/nixfmt"))Handy keymaps for handling files.
(defun rkn/reload-emacs-config()
(interactive)
(load-file user-init-file))
(rkn/keymap-define-global
;; grep current file quickly
"/" 'consult-line
"f" '(:ignore t :which-key "file")
"f f" 'find-file
"f d" '(:ignore t :which-key "dot")
"f d e" '((lambda() (interactive)(find-file "~/.config/dotfiles/modules/editors/emacs/config/emacs.org")) :which-key "dot-edit")
"f d i" '((lambda() (interactive)(find-file user-init-file)) :which-key "dot-edit")
"f d r" '((lambda() (interactive)(rkn/reload-emacs-config)) :which-key "reload-emacs-config")
"f d R" '((lambda() (interactive)(shell-command "dot rebuild")(rkn/reload-emacs-config)) :which-key "reload-dotfiles"))Git operations
(rkn/keymap-define-global
;; grep current file quickly
"g" '(:ignore t :which-key "git")
"g g" 'magit-status
"g b" 'magit-blame)Handing switching between projects, finding files in projects etc.
(rkn/keymap-define-global
;; grep current file quickly
"p" '(:ignore t :which-key "project")
"p p" 'projectile-switch-project
"p s" 'consult-ripgrep
"SPC" 'consult-find)Quick keybindings for dealing with buffers.
(rkn/keymap-define-global
"b" '(:ignore t :which-key "buffer")
"bb" 'consult-buffer)(general-define-key
"C-SPC" 'company-complete)This includes only org-agenda for now.
(rkn/keymap-define-global
"a" 'org-agenda)Global interface toggles.
(rkn/keymap-define-global
"t" '(:ignore t :which-key "toggle")
"tt" 'ef-themes-toggle
"tf" 'toggle-frame-fullscreen
"tl" 'linum-mode)(rkn/keymap-define-map
:keymaps 'org-mode-map
"m" '(:ignore t :which-key "org")
"m SPC" 'consult-outline
"m c" '(:ignore t :which-key "clock")
"m c i" 'org-clock-in
"m c o" 'org-clock-out
"m e" '(:ignore t :which-key "edit")
"m e s" 'org-edit-src-code)(rkn/keymap-define-map
:keymaps 'clojure-mode-map
"m" '(:ignore t :which-key "clojure")
;; cider
"m c" '(:ignore t :which-key "cider")
"m c c" 'cider-connect-clj
"m c s" 'cider-connect-cljs
"m e" '(:ignore t :which-key "eval")
"m e e" 'cider-eval-last-sexp
"m e c" 'cider-eval-defun-to-comment
"m r" '(:ignore t :which-key "repl")
"m r n" 'cider-repl-set-ns)(rkn/keymap-define-map
:keymaps 'nix-mode-map
"m" '(:ignore t :which-key "nix")
"m f" 'nix-format-buffer)