dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

commit c706962ff08c10066c929e7c2376e13813b6c751
Author: Lukas Henkel <lh@entf.net>
Date:   Fri,  9 Jul 2021 13:30:30 +0200

Emacs config redone!

Diffstat:
Aconfig.org | 344+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aearly-init.el | 2++
Ainit.el | 1+
3 files changed, 347 insertions(+), 0 deletions(-)

diff --git a/config.org b/config.org @@ -0,0 +1,344 @@ +#+TITLE: Emacs config +#+AUTHOR: Lukas Henkel + +* Setup +** load path +Add a local directory to the load path to be able to load custom local libraries. +#+begin_src emacs-lisp + (push + (let ((lisp-path (expand-file-name "lisp" user-emacs-directory))) + (unless (file-exists-p lisp-path) + (make-directory lisp-path)) + lisp-path) + load-path) +#+end_src +** straight.el +#+begin_src emacs-lisp + (setq straight-use-package-by-default t) + (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)) +#+end_src +** use-package +#+begin_src emacs-lisp + (straight-use-package 'use-package) +#+end_src +** diminish +diminish removes modes from the modeline, to make it a bit more clean. It's called via use-packages =diminish=. +#+begin_src emacs-lisp + (use-package diminish + :straight t) +#+end_src +** System independent directories +Here we figure out some directories later used in this config in a (hopefully) system independent way. +#+begin_src emacs-lisp + (defun lh/xdg-dir (name default) + (let ((v (string-trim (shell-command-to-string "xdg-user-dir DOCUMENTS")))) + (if (null v) + default + v))) + + (setq lh/dir-documents (expand-file-name + (cond ((eq system-type 'gnu/linux) (lh/xdg-dir "XDG_DOCUMENTS_DIR" "~/Documents")) + ((eq system-type 'windows-nt) "~/Documents")))) + + (setq lh/dir-data-home (expand-file-name + (cond ((eq system-type 'gnu/linux) (or (getenv "XDG_DATA_HOME") "~/.local/share")) + ((eq system-type 'windows-nt) (getenv "APPDATA"))))) +#+end_src +* Basic settings +** Cursor +I prefer the bar cursor. +#+begin_src emacs-lisp + (setq-default cursor-type 'bar) +#+end_src +** Fonts +#+begin_src emacs-lisp + (set-face-attribute 'default nil + :font "Go Mono" + :height 110) + (set-face-attribute 'fixed-pitch nil + :height 110) + (set-face-attribute 'variable-pitch nil + :font "IBM Plex Serif" + :height 120) +#+end_src +** Scrolling +Scrolling in Emacs is weird, this fixes it. +#+begin_src emacs-lisp + (setq scroll-conservatively 100) +#+end_src +** Disable the bell +Begone! +#+begin_src emacs-lisp + (setq ring-bell-function 'ignore) +#+end_src +** Consistent yes/no prompts +Sometimes Emacs asks you to enter y/n, other times yes/no. Why? +#+begin_src emacs-lisp + (defalias 'yes-or-no-p 'y-or-n-p) +#+end_src +** Focus newly created windows +#+begin_src emacs-lisp + (defadvice split-window-below (after lh/split-window-below activate) + (other-window 1)) + (defadvice split-window-right (after lh/split-window-right activate) + (other-window 1)) +#+end_src +** Delete the selection when you type +By default Emacs does not delete the current selection when you type. I like this, saves me one keypress. +#+begin_src emacs-lisp + (delete-selection-mode 1) +#+end_src +** Backup files +Who likes to have backup files scattered around all over your file system? A lot of people seem to disable these, but I think they are very useful and have saved me a couple of times in the past. We just need to move them to some place where we don't constantly see them. +#+begin_src emacs-lisp + (let ((backup-dir (concat user-emacs-directory "backup"))) + (unless (file-exists-p backup-dir) + (make-directory backup-dir t)) + (setq backup-directory-alist `(("." . ,backup-dir)))) + (setq backup-by-copying t + version-control t + delete-old-versions t + kept-new-versions 10 + kept-old-versions 5) +#+end_src +** Fullscreen +On fullscreen I want to hide all UI elements (toolbar and menu bar) and reenable them when I leave fullscreen. +#+begin_src emacs-lisp + (defadvice toggle-frame-fullscreen (before lh/toggle-frame-fullscreen-bars activate) + (menu-bar-mode (if menu-bar-mode -1 1)) + (tool-bar-mode (if tool-bar-mode -1 1)) + (scroll-bar-mode (if scroll-bar-mode -1 1))) +#+end_src +** transpose regions +Doesn't have a default keybinding. +#+begin_src emacs-lisp + (global-set-key (kbd "C-x C-M-t") #'transpose-regions) +#+end_src +* Basic QOL Packages +** which-key +Shows the possible keybindings in a neat menu. +#+begin_src emacs-lisp + (use-package which-key + :straight t + :diminish which-key-mode + :config (which-key-mode 1)) +#+end_src +** Selectrum +Selectrum replaces Emacs default =completing-read=, which is a bit cumbersome to use. We also enable prescient for smart recommendations. +#+begin_src emacs-lisp + (use-package selectrum + :straight t + :config (selectrum-mode 1)) + (use-package selectrum-prescient + :straight t + :after selectrum + :config + (selectrum-prescient-mode 1) + (prescient-persist-mode 1)) +#+end_src +** Marginalia +Marginalia adds additional information to =M-x=, such as keybindings and command descriptions. +#+begin_src emacs-lisp + (use-package marginalia + :straight t + :init + (setq marginalia-annotators '(marginalia-annotators-heavy)) + :config + (marginalia-mode 1)) +#+end_src +** Consult +Consult improves on a lot of default Emacs functionality and adds a lot more. I use the keybindings from the Consult Readme. +#+begin_src emacs-lisp + (use-package consult + :straight t + :bind (;; C-c bindings (mode-specific-map) + ("C-c h" . consult-history) + ("C-c m" . consult-mode-command) + ("C-c b" . consult-bookmark) + ("C-c k" . consult-kmacro) + ;; C-x bindings (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 + ;; 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 + ("<help> a" . consult-apropos) ;; orig. apropos-command + ;; M-g bindings (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-g i" . consult-imenu) + ("M-g I" . consult-project-imenu) + ;; M-s bindings (search-map) + ("M-s f" . consult-find) + ("M-s L" . 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 m" . consult-multi-occur) + ("M-s k" . consult-keep-lines) + ("M-s u" . consult-focus-lines) + ;; Isearch integration + ("M-s e" . consult-isearch) + :map isearch-mode-map + ("M-e" . consult-isearch) ;; orig. isearch-edit-string + ("M-s e" . consult-isearch) ;; orig. isearch-edit-string + ("M-s l" . consult-line)) ;; needed by consult-line to detect isearch + :config + (setq consult-project-root-function + (lambda () + (when-let (project (project-current)) + (car (project-roots project)))))) +#+end_src +** project-x +Improves on the inbuilt project.el, also needed by popper. +#+begin_src emacs-lisp + (use-package project-x + :straight (project-x :type git :host github :repo "karthink/project-x")) +#+end_src +** popper +Popper turns chosen buffers into popups, which can be shown or hidden quickly. +#+begin_src emacs-lisp + (use-package popper + :straight t + :bind + ("C-." . popper-toggle-latest) + ("M-." . popper-cycle) + ("C-M-." . popper-toggle-type) + :init + (setq popper-group-function #'popper-group-by-project) + (setq popper-reference-buffers + '("\\*Messages\\*" + "\\*scratch\\*" + "^\\*straight-")) + :config (popper-mode 1)) +#+end_src +** expand-region +Smart expand selection with one keypress. +#+begin_src emacs-lisp + (use-package expand-region + :straight t + :bind ("C-+" . er/expand-region)) +#+end_src +** ace-window +Makes it easy to switch windows. +#+begin_src emacs-lisp + (use-package ace-window + :straight t + :bind ("M-o" . ace-window) + :init + (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l) + aw-scope 'frame + aw-dispatch-always t)) +#+end_src +* Org +#+begin_src emacs-lisp + (use-package org + :straight t + :hook + (org-mode . visual-line-mode) + :init + (setq org-startup-indented nil + org-src-window-setup 'current-window + org-support-shift-select t)) +#+end_src +* Code +** Autocomplete +#+begin_src emacs-lisp + (use-package company + :straight t + :diminish company-mode + :init (setq company-idle-delay 0) + :config (global-company-mode 1)) +#+end_src +Company prescient for smart completions. +#+begin_src emacs-lisp + (use-package company-prescient + :straight t + :config + (company-prescient-mode 1)) +#+end_src +** Lisp +#+begin_src emacs-lisp + (use-package sly + :straight t + :init (setq inferior-lisp-program "sbcl")) +#+end_src +** Go +#+begin_src emacs-lisp + (use-package go-mode + :straight t) +#+end_src +** LSP and DAP +Using the language server protocol, we can support a lot of different programming languages +#+begin_src emacs-lisp + (use-package lsp-mode + :straight t + :init + (setq lsp-keymap-prefix "C-c l") + :hook ((go-mode . lsp-mode) + (lsp-mode . lsp-enable-which-key-integration)) + :commands lsp) + + (use-package lsp-ui + :straight t + :commands lsp-ui-mode + :init + (setq lsp-ui-sideline-show-diagnostics t) + :bind (:map lsp-mode-map + ("M-ß" . lsp-ui-peek-find-definitions) + ("M-?" . lsp-ui-peek-find-references))) + + (use-package dap-mode + :straight t) +#+end_src +* Other packages +** Magit +Magit is a git UI for Emacs. +#+begin_src emacs-lisp + (use-package magit + :straight t) +#+end_src +** elfeed +A tag based news reader for emacs. +#+begin_src emacs-lisp + (use-package elfeed + :straight t + :config + (setq elfeed-db-directory (let ((data-dir (expand-file-name "elfeed" lh/dir-data-home))) + (unless (file-exists-p data-dir) + (make-directory data-dir)) + data-dir)) + (let ((feeds (expand-file-name "feeds.el" user-emacs-directory))) + (when (file-exists-p feeds) + (load feeds)))) +#+end_src + +** nov.el +Emacs EPub reader. +#+begin_src emacs-lisp + (use-package nov + :straight t + :mode ("\\.epub\\'" . nov-mode)) +#+end_src diff --git a/early-init.el b/early-init.el @@ -0,0 +1,2 @@ +(setq gc-cons-threshold most-positive-fixnum) +(setq package-enable-at-startup nil) diff --git a/init.el b/init.el @@ -0,0 +1 @@ +(org-babel-load-file (expand-file-name "config.org" user-emacs-directory))