aboutsummaryrefslogtreecommitdiff
path: root/emacs-init.el
diff options
context:
space:
mode:
authorTimo Wilken2022-12-30 10:54:17 +0100
committerTimo Wilken2022-12-30 10:54:17 +0100
commit0f308b1c90444f5f0293bf40aa1ef177bc51036c (patch)
treeb052860a66b8bf3b094fa16e4538887003c37ada /emacs-init.el
parentda1ff8a0816e430d2c035217d80db3be5cc919ab (diff)
Reorganise Guix home declaration into module tree
Diffstat (limited to 'emacs-init.el')
-rw-r--r--emacs-init.el538
1 files changed, 0 insertions, 538 deletions
diff --git a/emacs-init.el b/emacs-init.el
deleted file mode 100644
index 8badabce..00000000
--- a/emacs-init.el
+++ /dev/null
@@ -1,538 +0,0 @@
-;;; init.el --- Emacs configuration. -*- lexical-binding: t -*-
-;;; Commentary:
-;;; Code:
-
-;; Load settings set through Custom.
-;; (setq custom-file (locate-user-emacs-file "custom.el"))
-;; (when (file-readable-p custom-file)
-;; (load custom-file))
-
-(defun tw/xdg-emacs-subdir (type name)
- "Get the name of a subdirectory called NAME under $XDG_<TYPE>_HOME/emacs."
- (expand-file-name
- (concat (string-trim-right name "/") "/")
- (expand-file-name
- "emacs/" (pcase type
- ('cache (or (getenv "XDG_CACHE_HOME") "~/.cache/"))
- ('config (or (getenv "XDG_CONFIG_HOME") "~/.config/"))
- ('data (or (getenv "XDG_DATA_HOME") "~/.local/share/"))
- ;; The following two are Guix/GuixSD extensions.
- ('log (or (getenv "XDG_LOG_HOME") "~/.local/var/log/"))
- ('state (or (getenv "XDG_STATE_HOME") "~/.local/var/lib/"))
- (_ (error "Unknown XDG directory type: %S" type))))))
-
-;; Global/built-in Custom settings
-;; Apply these as early as possible so that e.g. the native-comp files go to the right place.
-(mapc (apply-partially #'apply #'customize-set-variable)
- `((native-comp-async-report-warnings-errors silent "Don't pop up Warnings buffer for native compilation.")
- (native-compile-target-directory ,(tw/xdg-emacs-subdir 'cache "eln") "Put native-compiled binaries in the cache.")
- (inhibit-startup-screen t "Don't show the startup screen with help links.")
- (indent-tabs-mode nil "Always use spaces to indent.")
- (sh-basic-offset 2 "Use 2 spaces for `sh-mode' indents.")
- (menu-bar-mode nil "Hide the menu bar globally.")
- (tool-bar-mode nil "Hide the tool bar globally.")
- (tooltip-mode nil "Show tooltips in the echo area instead.")
- (global-hl-line-mode t "Highlight the current line in all buffers.")
- (column-number-mode t "Show the column number in the statusline.")
- (electric-pair-mode t "Auto-pair suitable characters like parentheses.")
- (backup-directory-alist (("." . ,(tw/xdg-emacs-subdir 'data "backup"))) "Save all backup files in one place to avoid clutter.")
- (scroll-up-aggressively 0.0 "Don't recenter the window if the point moves off the page.")
- (scroll-down-aggressively 0.0 "Don't recenter the window if the point moves off the page.")
- (max-mini-window-height 3 "Let the echo area grow to a maximum of 4 lines, e.g. when using `eldoc-mode'.")
- (package-archives nil "Don't fetch packages from the internet; only get them from Guix.")
- (recentf-max-saved-items 10000 "Save lots of recently-opened files.")))
-
-(defalias 'yes-or-no-p #'y-or-n-p
- "Always use `y-or-n-p' when asking for confirmation.")
-
-;; Custom modes depending on file names.
-(mapc (apply-partially #'add-to-list 'auto-mode-alist)
- `((,(rx (or bos "/") "PKGBUILD" eos) . sh-mode)
- (,(rx ".install" eos) . sh-mode)
- (,(rx bos "/tmp/neomutt-") . mail-mode)
- (,(rx "." (1+ anything) "rc" eos) . conf-unix-mode)
- (,(rx ".gnuplot" eos) . gnuplot-mode)
- (,(rx ".aurora" eos) . python-mode)))
-
-(add-to-list 'magic-mode-alist
- `(,(rx "#!" (* (not space))
- (? "env" (+ space) (? "-S" (+ space)))
- (or "guile" "racket"))
- . scheme-mode))
-
-(add-hook 'mail-mode-hook #'auto-fill-mode)
-
-;; `use-package' requirements.
-(require 'package)
-(package-initialize t)
-(eval-when-compile
- (require 'use-package))
-(use-package diminish) ; for using :diminish later
-(use-package bind-key) ; for using :bind later
-
-;; Some packages below have `:commands (...) :demand t'.
-;; We need :commands for the byte-compiler, but we want to load the package immediately.
-
-;; Look and feel
-(set-face-attribute 'default nil :family "Hermit" :height 100)
-
-(use-package autothemer
- ;; The "catppuccin" theme is linked to the appropriate variant by guix home.
- :config (load-theme 'catppuccin-mocha t))
-
-(defun tw/get-catppuccin-color (name)
- "Get the hex code of the Catppuccin color named NAME."
- (cl-loop for color in (autothemer--theme-colors autothemer-current-theme)
- when (string= (autothemer--color-name color) name)
- return (autothemer--color-value color)))
-
-(custom-set-faces
- `(cursor ((default :background ,(tw/get-catppuccin-color "rosewater"))) t
- "Make the cursor \"rosewater\", as recommended by Catppuccin upstream, overriding catppuccin/emacs."))
-
-(use-package smart-mode-line
- :commands (sml/setup) :demand t
- :custom
- (sml/no-confirm-load-theme t "Stop Emacs from constantly asking for user confirmation.")
- (sml/mode-width 'right "Move the minor-mode list to the right of the modeline.")
- (sml/theme 'respectful "Make `smart-mode-line' blend in with the active theme.")
- :config (sml/setup))
-
-;; General editor behaviour.
-(use-package ivy
- :commands (ivy-mode) :demand t
- :config (ivy-mode +1)
- :diminish ivy-mode)
-
-(use-package counsel ; extra niceties for `ivy-mode'
- :after (ivy evil) ; evil for :bind-ing to <leader>
- :bind (("<leader>SPC" . counsel-M-x) ; <leader><leader> doesn't work
- ("<leader>fr" . counsel-buffer-or-recentf)
- :map evil-visual-state-map
- ("<leader>SPC" . counsel-M-x))
- :commands (counsel-mode) :demand t
- :config (counsel-mode +1)
- :diminish counsel-mode)
-
-(defun tw/counsel-dash-is-help ()
- "Install `counsel-dash-at-point' as `evil-lookup-func'."
- (setq-local evil-lookup-func #'counsel-dash-at-point))
-
-(use-package counsel-dash
- :bind (("<leader>K" . counsel-dash-at-point) ; TODO: just install as `evil-lookup-func'?
- ("<leader>dK" . counsel-dash)
- ("<leader>di" . counsel-dash-install-docset)
- ("<leader>da" . counsel-dash-activate-docset)
- ("<leader>dd" . counsel-dash-deactivate-docset))
- :hook (python-mode . tw/counsel-dash-is-help)
- :custom
- (counsel-dash-docsets-path (tw/xdg-emacs-subdir 'data "dash-docsets") "Store docsets in the XDG data directory.")
- (counsel-dash-browser-func 'eww "Open documentation pages using `eww' instead of an external browser.")
- (counsel-dash-enable-debugging nil "Disable popping up useless warnings."))
-
-(use-package rainbow-mode
- :after (evil)
- :bind (("<leader>tR" . rainbow-mode)))
-
-(use-package display-line-numbers
- ;; Included in Emacs >= 26. Better than `linum-mode'.
- ;; There is also `global-display-line-numbers-mode', but that also
- ;; enables line numbers in help windows, which I don't want.
- :hook (prog-mode conf-mode))
-
-(use-package which-key
- :commands (which-key-mode) :demand t
- :config (which-key-mode +1)
- :diminish which-key-mode)
-
-(use-package undo-tree
- :after (evil) ; for our :bind-ing
- :bind (("<leader>U" . undo-tree-visualize))
- :custom
- (undo-tree-history-directory-alist
- `(("." . ,(tw/xdg-emacs-subdir 'data "undo-tree-history")))
- "Store all `undo-tree' history in a single directory, instead of next to the associated file.")
- :commands (global-undo-tree-mode)
- :demand t ; this is required so that the :config stanza is actually run asap despite :bind
- :config (global-undo-tree-mode +1))
-
-;; IDE-like features.
-(use-package vc
- :after (which-key evil)
- :init (which-key-add-key-based-replacements
- "<leader>g" '("vc" . "Version control")
- "<leader>gM" '("merge" . "Version control merging"))
- :bind-keymap ("<leader>g" . vc-prefix-map))
-
-(use-package company
- :hook (prog-mode ledger-mode)
- ;; Use TAB for selecting completions. Config from:
- ;; https://github.com/company-mode/company-mode/blob/master/company-tng.el
- :bind (:map company-active-map
- ([tab] . company-select-next)
- ([backtab] . company-select-previous))
- :custom
- (company-minimum-prefix-length 2 "Start showing completion candidates slightly earlier.")
- (company-idle-delay (lambda () (if (company-in-string-or-comment) nil 0.3))
- "Automatically show completions when editing non-comment parts of code.")
- :diminish company-mode)
-
-(use-package company-quickhelp
- :after (company autothemer) ; autothemer needed for `tw/get-catppuccin-color'
- :hook company-mode
- :custom
- (company-quickhelp-delay 0.2 "Automatically show quickhelp for completions.")
- (company-quickhelp-color-background (tw/get-catppuccin-color "surface0") "Give the quickhelp tooltip a nicer background colour.")
- (company-quickhelp-color-foreground (tw/get-catppuccin-color "text") "Give the quickhelp tooltip the default text colour."))
-
-(use-package company-posframe
- :after (company company-quickhelp)
- :hook company-mode
- :diminish company-posframe-mode)
-
-(use-package flyspell
- :hook mail-mode)
-
-(use-package flymake
- :after (evil which-key)
- :hook prog-mode
- :init (which-key-add-key-based-replacements
- "<leader>e" '("errors" . "Flymake"))
- :bind (("<leader>eb" . flymake-start)
- ("<leader>el" . flymake-show-buffer-diagnostics)
- ("<leader>ep" . flymake-show-project-diagnostics)
- ("<leader>e." . display-local-help) ; Show the error message at point in the minibuffer.
- ; `flymake' also shows it using `eldoc', but documentation
- ; seems to override error messages.
- ("<leader>en" . flymake-goto-next-error)
- ("<leader>eN" . flymake-goto-prev-error))
- :custom
- (flymake-suppress-zero-counters nil "Show severity counters even when they are zero."))
-
-(use-package flymake-collection
- :after (flymake)
- ;; This needs to be called in `after-init-hook' so that all other
- ;; packages' `:flymake-hook's are processed before f-c-hook-setup is
- ;; called. See https://github.com/mohkale/flymake-collection.
- :hook (after-init . flymake-collection-hook-setup))
-
-;; Language Server Protocol.
-(defun tw/help-is-eldoc (&rest _)
- "Set up `evil-lookup-func' to display the `eldoc' buffer."
- (setq-local evil-lookup-func #'eldoc-doc-buffer))
-
-(use-package eglot
- ;; I have clang (for clangd) and python-lsp-server installed.
- ;; `:hook' adds `-mode' to the package name, but `eglot-mode' doesn't exist.
- :hook ((python-mode c-mode c++-mode) . eglot)
- :custom
- (eglot-autoshutdown t "Shut down language servers after deleting their last associated buffer.")
- (eglot-sync-connect 0.1 "Wait for the language server in the background if it takes longer than 100ms.")
- :config
- ;; TODO: only run `tw/help-is-eldoc' if `eglot-managed-p' is true.
- (add-hook 'eglot-managed-mode-hook #'tw/help-is-eldoc))
-
-;; Non-LSP language modes.
-(use-package mmm-mode
- :commands (mmm-mode))
-(use-package cmake-mode
- :mode (rx (or (: (or bos "/") "CMakeLists.txt") ".cmake") eos))
-(use-package puppet-mode
- :mode (rx ".pp" eos))
-(use-package web-mode
- :mode (rx "." (or "htm" "html" "js" "css" "scss") eos))
-(use-package yaml-mode
- :mode (rx ".y" (? "a") "ml" eos))
-(use-package rec-mode
- :mode (rx ".rec" eos))
-(use-package hcl-mode
- :mode (rx "." (or "hcl" "nomad") eos))
-(use-package graphviz-dot-mode
- :mode (rx ".dot" eos)
- :custom (graphviz-dot-view-command "xdot %s" "Use xdot for previewing graphviz files."))
-(use-package tcl
- :mode ((rx ".tcl" eos) . tcl-mode)
- :magic ((rx "#%Module1.0") . tcl-mode))
-
-(use-package ledger-mode
- :mode (rx ".journal" eos)
- :custom
- (ledger-default-date-format ledger-iso-date-format "Use hledger-style dates.")
- (ledger-reconcile-default-date-format ledger-iso-date-format "Use hledger-style dates.")
- (ledger-reconcile-default-commodity "€" "Make euros the default currency.")
- (ledger-post-account-alignment-column 2 "Use 2-space indents.")
- (ledger-post-amount-alignment-at :decimal "Align amounts at decimal points/commas.")
- (ledger-post-amount-alignment-column 52 "Align amounts' decimal points to the 52nd column.")
- (ledger-highlight-xact-under-point nil "Don't highlight the transaction at point."))
-
-(use-package geiser
- :after (evil)
- :commands (geiser geiser-eval-buffer geiser-eval-definition geiser-eval-region geiser-eval-last-sexp)
- :hook (scheme-mode . geiser-autodoc-mode)
- :config
- (evil-define-key '(normal visual) scheme-mode-map
- (kbd "<localleader>i") #'geiser
- (kbd "<localleader>eb") #'geiser-eval-buffer
- (kbd "<localleader>ef") #'geiser-eval-definition
- (kbd "<localleader>er") #'geiser-eval-region
- (kbd "<localleader>el") #'geiser-eval-last-sexp)
- :defines scheme-mode-map)
-
-(use-package geiser-racket
- :after (geiser))
-(use-package geiser-guile
- :after (geiser))
-
-;; Org-mode
-(use-package org)
-(use-package ob ; org-babel
- :after (org))
-
-(use-package outline
- :commands (outline-mode outline-minor-mode)
- :custom
- ;; Mirror the default "C-c @" binding for `outline-minor-mode'.
- (outline-minor-mode-prefix (kbd "<localleader>@") "Use localleader for `outline-minor-mode' keybindings."))
-
-;; My own custom packages, and stuff that isn't on MELPA.
-;; (use-package actionlint ; TODO: port to flymake
-;; :after (flycheck)
-;; :load-path "include/")
-
-(use-package alidist-mode
- :after (flymake mmm-mode yaml-mode)
- :mode (rx (or bos "/") "alidist/" (1+ anything) ".sh" eos)
- :load-path "include/")
-
-(use-package bemscript-mode
- :load-path "include/"
- :mode (rx ".bem" eos))
-
-(use-package ifm-mode
- :load-path "include/"
- :mode (rx ".ifm" eos))
-
-(use-package pam-env-mode
- :load-path "include/"
- :mode (rx (or bos "/") (or "pam_env.conf" ".pam_environment") eos))
-
-(use-package environmentd-mode
- :load-path "include/"
- :mode (rx (or bos "/")
- (or (: (? "etc/") "environment")
- (: ".environment.d/" (1+ (not ?\/)) ".conf"))
- eos))
-
-(use-package org-latex-classes
- :after (ox-latex)
- :load-path "include/")
-
-(use-package ob-rec
- ;; `org-babel' hooks for `rec-mode'
- :after (org ob)
- :load-path "include/")
-
-(use-package vcard-mode
- :load-path "include/"
- :mode (rx "." (or "vcf" "vcard") eos))
-
-;; Vim keybindings.
-(defun tw/switch-to-other-buffer ()
- "Switch to the last-used buffer."
- (interactive)
- (switch-to-buffer (other-buffer)))
-
-(defun tw/new-buffer ()
- "Open a new, empty buffer."
- (interactive)
- (switch-to-buffer (generate-new-buffer "untitled")))
-
-(use-package evil
- :after (which-key)
- :commands (evil-mode evil-ex-nohighlight)
- :init (setq evil-want-keybinding nil) ; evil-collection needs this
- :custom
- (evil-undo-system 'undo-tree "Use `undo-tree' for evil's undo-redo function.")
- (evil-want-minibuffer t "Use evil bindings in the minibuffer too.")
- (evil-want-C-u-scroll t "Scroll on C-u in normal mode, not `universal-argument'.")
- (evil-want-C-u-delete t "Delete line on C-u in insert mode, not `universal-argument'.")
- (evil-want-Y-yank-to-eol t "Yank from point to end-of-line on Y.")
- :config
- (evil-mode +1)
- (evil-set-leader '(normal visual) (kbd "SPC")) ; <leader>
- (evil-set-leader '(normal visual) (kbd "\\") t) ; <localleader>
- (evil-define-key '(normal insert visual replace) 'global
- (kbd "C-s") #'save-buffer)
- ;; Global major-mode-independent keys should be defined here. Major
- ;; mode-dependent keys (e.g. for launching a REPL) should go under
- ;; <localleader> instead. Use `use-package' `:bind' for those.
- (evil-define-key '(normal visual) 'global
- ;; These keybindings mirror the default Spacemacs ones because I have
- ;; muscle memory of those.
- (kbd "<leader>:") #'eval-expression
- (kbd "<leader>TAB") #'tw/switch-to-other-buffer
- (kbd "<leader>bb") #'switch-to-buffer
- (kbd "<leader>bd") #'kill-current-buffer
- (kbd "<leader>bn") #'tw/new-buffer
- (kbd "<leader>br") #'revert-buffer-quick
- (kbd "<leader>bx") #'kill-buffer-and-window
- (kbd "<leader>ff") #'find-file
- (kbd "<leader>fs") #'save-buffer
- (kbd "<leader>h") help-map
- (kbd "<leader>sc") #'evil-ex-nohighlight
- (kbd "<leader>tf") #'auto-fill-mode
- (kbd "<leader>tl") #'toggle-truncate-lines
- (kbd "<leader>tn") #'display-line-numbers-mode
- (kbd "<leader>u") #'universal-argument
- (kbd "<leader>w") evil-window-map
- (kbd "<leader>wd") #'evil-window-delete ; analogous to "<leader>bd"
- (kbd "<leader>wx") #'kill-buffer-and-window) ; analogous to "<leader>bx"
- (which-key-add-key-based-replacements
- ;; Names are a `cons' of a short name and a long name.
- ;; E.g. for <leader>b, "buffer" is shown under "b" in the "<leader>" menu,
- ;; while "Buffers" is shown as the title in the "<leader>b" menu.
- "<leader>b" '("buffer" . "Buffers")
- "<leader>f" '("file" . "Files")
- "<leader>h" '("help" . "General help and documentation")
- "<leader>q" '("quit" . "Finish editing the current buffer in emacsclient")
- "<leader>s" '("search" . "Search operations and options")
- "<leader>t" '("toggle" . "Toggles and quick settings")
- "<leader>w" '("window" . "Windows"))
- :functions (evil-define-key evil-set-leader
- evil-define-key* evil-window-delete evil-delay)
- :defines (evil-visual-state-map))
-
-(use-package evil-collection
- :after (evil)
- :commands (evil-collection-init) :demand t
- :config (evil-collection-init))
-
-(use-package evil-org
- :after (evil org)
- :hook org-mode
- :config
- (evil-define-key '(normal visual) org-mode-map
- (kbd "<localleader>\\") #'org-ctrl-c-ctrl-c
- (kbd "<localleader>'") #'org-edit-src-code
- (kbd "<localleader>e") #'org-export-dispatch)
- (evil-define-key '(normal visual) org-src-mode-map
- (kbd "<localleader>'") #'org-edit-src-exit
- (kbd "<localleader>\\") #'org-edit-src-save
- (kbd "<localleader>a") #'org-edit-src-abort))
-
-(use-package evil-replace-with-register
- :after (evil)
- :commands (evil-replace-with-register-install) :demand t
- ;; :custom (evil-replace-with-register-key "gR" "Use the default key.")
- :config (evil-replace-with-register-install))
-
-(use-package evil-commentary
- :after (evil)
- :commands (evil-commentary-mode) :demand t
- :config (evil-commentary-mode +1))
-
-(use-package evil-expat ; for :reverse, :remove, :rename, :colo, :g*, ... ex commands
- :after (evil))
-
-(use-package evil-surround
- :after (evil)
- :commands (global-evil-surround-mode) :demand t
- :config (global-evil-surround-mode +1))
-
-(use-package evil-smartparens
- :after (evil smartparens)
- :hook smartparens-enabled-hook)
-
-(use-package evil-multiedit
- ;; See: https://github.com/hlissner/evil-multiedit#usage
- :commands (evil-multiedit-default-keybinds) :demand t
- :config (evil-multiedit-default-keybinds))
-
-(use-package evil-args
- :after (evil)
- :config
- ;; Bind evil-args text objects only.
- ;; See https://github.com/wcsmith/evil-args for more bindings.
- (define-key evil-inner-text-objects-map "a" 'evil-inner-arg)
- (define-key evil-outer-text-objects-map "a" 'evil-outer-arg))
-
-(use-package evil-numbers
- :after (evil)
- :bind (("<leader>+" . evil-numbers/inc-at-pt)
- ("<leader>-" . evil-numbers/dec-at-pt)))
-
-(use-package evil-goggles ; visual previews for edit operations
- :after (evil)
- :commands (evil-goggles-mode evil-goggles-use-diff-faces) :demand t
- :config
- (evil-goggles-mode +1)
- (evil-goggles-use-diff-faces)
- :diminish evil-goggles-mode)
-
-(use-package evil-traces ; visual previews for :ex commands
- :after (evil)
- :commands (evil-traces-mode evil-traces-use-diff-faces) :demand t
- :config
- (evil-traces-mode +1)
- (evil-traces-use-diff-faces)
- :diminish evil-traces-mode)
-
-(use-package evil-markdown
- :after (evil markdown-mode)
- :hook markdown-mode)
-
-(use-package evil-tex
- :after (evil tex)
- :hook tex-mode)
-
-(use-package evil-text-object-python
- :after (evil python)
- :hook (python-mode . evil-text-object-python-add-bindings))
-
-;; Lisp features
-(use-package aggressive-indent
- :hook (; scheme-mode
- emacs-lisp-mode common-lisp-mode))
-
-(defun tw/lisp-evil-setup ()
- "Set up evil in general `lisp-mode' buffers."
- (setq-local evil-symbol-word-search t
- ;; https://github.com/wcsmith/evil-args#customization
- evil-args-delimiters '(" ")))
-
-;; Sadly, not all Lisp modes derive from `lisp-mode'.
-(add-hook 'lisp-mode-hook #'tw/lisp-evil-setup)
-(add-hook 'lisp-data-mode-hook #'tw/lisp-evil-setup) ; for elisp
-(add-hook 'scheme-mode-hook #'tw/lisp-evil-setup)
-
-;; buffer-locally set `evil-lookup-func' (used on K keys) for
-;; languages where something better than man pages is available
-;; (e.g. `describe-symbol' for elisp).
-(defun tw/elisp-lookup-func ()
- "Show help in `emacs-lisp-mode' buffers."
- (let ((sym (symbol-at-point)))
- (if sym (describe-symbol sym)
- (call-interactively #'describe-symbol))))
-
-(defun tw/emacs-lisp-evil-setup ()
- "Set up evil in `emacs-lisp-mode' buffers."
- (setq-local evil-lookup-func #'tw/elisp-lookup-func))
-
-(add-hook 'emacs-lisp-mode-hook #'tw/emacs-lisp-evil-setup)
-
-(defun tw/hack-guile-indents ()
- "Set the proper `scheme-indent-function' for Guix macros."
- (put 'modify-phases 'scheme-indent-function 1)
- (put 'add-before 'scheme-indent-function 2)
- (put 'substitute* 'scheme-indent-function 1))
-
-(add-hook 'scheme-mode-hook #'tw/hack-guile-indents)
-
-(evil-define-key '(normal visual) emacs-lisp-mode-map
- (kbd "<localleader>eb") #'eval-buffer
- (kbd "<localleader>ef") #'eval-defun
- (kbd "<localleader>er") #'eval-region
- (kbd "<localleader>el") #'eval-last-sexp
- (kbd "<localleader>ep") #'eval-print-last-sexp)
-
-;;; init.el ends here