dotfiles/emacs/.config/emacs/Emacs.org

20 KiB

My Emacs Config

Basic Settings

UI

  (setq inhibit-startup-message t)
  (tool-bar-mode -1)
  (tooltip-mode -1)
  (set-fringe-mode 10)
  (menu-bar-mode -1)
  (setq visible-bell t)
  (setq frame-resize-pixelwise t)
  (fset 'yes-or-no-p 'y-or-n-p)
  (setq default-frame-alist '((undecorated . t)))
  (scroll-bar-mode -1)

Backups

  (defvar wball/backup-directory (concat user-emacs-directory "backups"))
  (if (not (file-exists-p wball/backup-directory))
      (make-directory wball/backup-directory t))
  (setq backup-directory-alist `(("." . ,wball/backup-directory)))
  (setq make-backup-files t
        backup-by-copying t
        version-control t
        delete-old-versions t
        auto-save-default t)

Packages

Elpaca

Set up variables.

  (defvar elpaca-installer-version 0.11)
  (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 :inherit ignore
                                :files (:defaults "elpaca-test.el" (:exclude "extensions"))
                                :build (:not elpaca--activate-package)))

Bootstrap elpaca

  (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)
      (let ((load-source-file-function nil)) (load "./elpaca-autoloads"))))
  (add-hook 'after-init-hook #'elpaca-process-queues)
  (elpaca `(,@elpaca-order))

Enable use-package integration

  (elpaca elpaca-use-package
    (elpaca-use-package-mode))

use-package

  (setq use-package-always-ensure t)

Set up path correctly

  (use-package exec-path-from-shell
    :config
    (exec-path-from-shell-initialize))

Automatic updates

  (use-package auto-package-update
    :custom
    (auto-package-update-interval 7)
    (auto-package-update-prompt-before-update t)
    (auto-package-update-hide-results t)
    :config
    (auto-package-update-maybe)
    (auto-package-update-at-time "09:00"))

UI

Icons

  (use-package all-the-icons)

Rainbow delimiters

  (use-package rainbow-delimiters
    :hook (prog-mode . rainbow-delimiters-mode))

Fonts

  (use-package fontaine
    :config
    (setq fontaine-presets
          '((regular
             :default-height 130)
            (small
             :default-height 80)
            (large
             :default-weight semilight
             :default-height 150
             :bold-weight extrabold)
            (extra-large
             :default-weight semilight
             :default-height 180
             :bold-weight extrabold)
            (t
             :default-family "Iosevka Nerd Font"
             :default-weight normal
             :variable-pitch-family "Inter")))
    (fontaine-set-preset 'regular))

Which key

  (use-package which-key
    :defer 0
    :diminish which-key-mode
    :config
    (which-key-mode)
    (setq which-key-idle-delay 0.3))

Theme

Modus Themes

  (use-package emacs
    :ensure nil
    :config
    (require-theme 'modus-themes)
    (setq modus-themes-italic-constructs t
          modus-themes-bold-constructs t
  	modus-themes-links '(no-underline background faint)
          modus-themes-prompts '(bold intense)
          modus-themes-mode-line '(borderless accented moody)
          modus-themes-org-blocks 'gray-background
          modus-themes-region '(bg-only no-extend))
    (load-theme 'modus-operandi :no-confirm))

Catpuccin

  (use-package catppuccin-theme
    :init (setq catppuccin-flavor 'mocha)
    :hook (after-init . (lambda () (load-theme 'catppuccin :no-confirm))))

*** Italic Comments
#+begin_src emacs-lisp
  (advice-add #'load-theme :after (lambda (&rest _) (set-face-italic 'font-lock-comment-face t)))

Line Numbers

  (add-hook 'prog-mode-hook 'display-line-numbers-mode)

Modeline

  (use-package doom-modeline
    :init (doom-modeline-mode 1))
  (use-package hide-mode-line)

Smooth Scroll

  (use-package ultra-scroll
    :init
    (setq scroll-conservatively 3
          scroll-margin 0)
    :config
    (ultra-scroll-mode 1))

Functionality

Navigation

Ace-Window

  (use-package ace-window
    :bind (("M-o" . ace-window)))

Completion

Vertico

  (use-package vertico
    :init (vertico-mode)
    :custom (vertico-cycle t))

Savehist

  (use-package emacs
    :ensure nil
    :init (savehist-mode))

Orderless

  (use-package orderless
    :init
    (setq completion-styles '(orderless flex)
          completion-category-defaults nil
          completion-category-overrides '((file (styles partial-completion)))))

Corfu

  (use-package corfu
    :custom
    (corfu-cycle t)
    (corfu-auto nil)
    (corfu-echo-documentation 0.25)
    :init
    (global-corfu-mode)
    (setq tab-always-indent 'complete))

Cape

  (use-package cape
    :init
    (add-to-list 'completion-at-point-functions #'cape-dabbrev)
    (add-to-list 'completion-at-point-functions #'cape-file)
    (add-to-list 'completion-at-point-functions #'cape-history))

Marginalia

  (use-package marginalia
    :after vertico
    :init (marginalia-mode))

Consult

  (use-package consult
    :bind (("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)
           ("C-x b" . consult-buffer)
           ("C-x 4 b" . consult-buffer-other-window)
           ("C-x 5 b" . consult-buffer-other-frame)
           ("C-x t b" . consult-buffer-other-tab)
           ("C-x r b" . consult-bookmark)
           ("C-x p b" . consult-project-buffer)
           ;; Custom M-# bindings for fast register a
           ("M-#" . consult-register-load)
           ("M-'" . consult-register-store)
           ("C-M-#" . consult-register)
           ;; Other custom bindings
           ("M-y" . consult-yank-pop)
           ;; M-g bindings in `goto-map'
           ("M-g e" . consult-compile-error)
           ("M-g f" . consult-flymake)
           ("M-g g" . consult-goto-line)
           ("M-g M-g" . consult-goto-line)
           ("M-g o" . consult-outline)
           ("M-g m" . consult-mark)
           ("M-g k" . consult-global-mark)
           ("M-g i" . consult-imenu)
           ("M-g I" . consult-imenu-multi)
           ;; M-s bindings in `search-map'
           ("M-s d" . 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)
           ("M-s e" . consult-isearch-history)
           ("M-s l" . consult-line)
           ("M-s L" . consult-line-multi)
           ;; Minibuffer history
           :map minibuffer-local-map
           ("M-s" . consult-history)
           ("M-r" . consult-history))

    :hook (completion-list-mode . consult-preview-at-point-mode)

    :init
    (advice-add #'register-preview :override #'consult-register-window)
    (setq register-preview-delay 0.5)

    (setq xref-show-xrefs-function #'consult-xref
          xref-show-definitions-function #'consult-xref)

    :config

    (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 '(:debounce 0.4 any))

    (setq consult-narrow-key "<"))

Lsp

eglot

  (use-package eglot
    :ensure nil
    :bind (:map eglot-mode-map
                ("C-c l r" . eglot-rename)
                ("C-c l f" . eglot-format-buffer)
                ("C-c l a" . eglot-code-actions)
                ("C-c l q" . eglot-code-action-quickfix)
                ("C-c l d" . xref-find-definitions)
                ("C-c l i" . eglot-find-implementation)
                ("C-c l t" . eglot-find-type-definition)
                ("C-c l s" . xref-find-references)
                ("C-c l h" . eldoc)
                ("C-c l R" . eglot-restart-process)
                ("C-c l e" . eglot-errors-at-point))
    (:map flymake-mode-map
  	("M-n" . flymake-goto-next-error)
  	("M-p" . flymake-goto-prev-error)))

eldoc-box

  (use-package eldoc-box
    :hook (eglot-managed-mode . eldoc-box-hover-at-point-mode))

Markdown

I don't really use markdown (/wball/dotfiles/src/commit/d0b26a0962f458abf0e6e599ca939f8aff76158d/emacs/.config/emacs/Org%20Mode is a strict improvement imo), but it's handy for rendering documentation.

  (use-package markdown-mode)

Languages

Agda

;  (load-file (let ((coding-system-for-read 'utf-8))
;                  (shell-command-to-string "agda-mode locate")))

PG

  (use-package proof-general)

Idris

  (use-package idris-mode
    :custom
    (idris-interpreter-path "idris2"))
  (with-eval-after-load 'eglot
    (add-to-list 'eglot-server-programs
                 '(idris-mode . ("idris2-lsp"))))

Haskell

  (use-package haskell-mode)

Rust

  (use-package rust-mode
    :hook
    (rust-mode-hook . eglot-ensure))

Zig

  (use-package zig-mode)

C

  (use-package emacs
    :ensure nil
    :hook
    (c-mode . electric-pair-mode)
    :custom
    (c-default-style '((java-mode . "java")
  		     (awk-mode . "awk")
  		     (other . "linux"))))

Perga

  (use-package perga-mode
    :ensure (:repo "https://forgejo.ballcloud.cc/wball/perga-mode.git"))

Latex

Auctex

  (use-package tex
    :ensure auctex
    :hook
    (LaTeX-mode . visual-line-mode)
    (LaTeX-mode . flyspell-mode)
    (LaTeX-mode . reftex-mode)
    (LaTeX-mode . prettify-symbols-mode)
    (LaTeX-mode . outline-minor-mode)
    :custom
    (TeX-auto-save t)
    (TeX-parse-self t)
    (TeX-master t)
    (reftex-plug-in-to-AUCTeX t)
    (preview-auto-cache-preamble t)
    (preview-scale-function 0.50)
    (TeX-view-program-selection
     '(((output-dvi has-no-display-manager) "dvi2tty")
       ((output-dvi style-pstricks) "dvips and gv")
       (output-dvi "xdvi")
       (output-pdf "zathura")
       (output-html "xdg-open"))))

CDLatex

  (use-package cdlatex
    :hook
    (LaTeX-mode . #'turn-on-cdlatex)
    :custom
    (cdlatex-math-symbol-prefix ?\;))

Yasnippet and laas

  (use-package yasnippet
    :config
    (yas-global-mode 1))
  (defun wball/beginning-of-word ()
    "Return t if point is at the beginning of a word."
    (eq (point) (car (bounds-of-thing-at-point 'word))))

  (use-package laas
    :hook ((LaTeX-mode . laas-mode)
           (org-mode . laas-mode))
    :custom
    (laas-enable-auto-space nil)
    :config
    (aas-set-snippets 'laas-mode
      :cond #'wball/beginning-of-word
      "mk" (lambda () (interactive)
             (yas-expand-snippet "\\\\($1\\\\)$0"))
      "dm" (lambda () (interactive)
             (yas-expand-snippet "\\[\n\t$1\n\\]"))
      :cond (lambda () (and (wball/beginning-of-word) (texmathp)))
      "set" (lambda () (interactive)
              (yas-expand-snippet "\\\\{$1\\\\}$0"))
      "empty" "\\emptyset"
      "and" "\\wedge"
      "or" "\\vee"
      "forall" "\\forall"
      "exists" "\\exists"
      "notin" "\\notin"
      "cap" "\\cap"
      "cup" "\\cup"
      :cond #'texmathp
      "NN" "\\N"
      "ZZ" "\\Z"
      "QQ" "\\Q"
      "oo" "\\circ"
      "RR" "\\R"
      "CC" "\\C"
      "BB" "\\B"
      "PP" "\\P"
      "FF" "\\F"
      "HH" "\\H"
      "SS" "\\Ss"
      "TT" "\\T"
      "\\\\\\" "\\setminus"
      "s=" "\\subseteq"
      "s<" "\\subset"
      "invs" "^{-1}"
      "opl" "\\oplus"
      "td" (lambda () (interactive)
             (yas-expand-snippet "^{$1}$0"))
      "__" (lambda () (interactive)
             (yas-expand-snippet "_{$1}$0"))))

Org Mode

Org itself

  (use-package org
    :ensure `(org :repo "https://code.tecosaur.net/tec/org-mode.git/"
                  :branch "dev")
    :defer
    :init
    (setq org-list-allow-alphabetical t)
    :custom
    (org-startup-indented t)
    (org-hide-emphasis-markers t)
    (org-startup-with-inline-images t)
    (org-image-actual-width '(300))
    (org-export-with-smart-quotes t)
    (org-directory "~/Nextcloud/org")
    (org-cite-global-bibliography '("~/Nextcloud/library.bib"))
    (org-agenda-files `(,org-directory))
    (org-default-notes-file (mapcar (lambda (x) (concat org-directory x))
                                    '("/todo.org" "/done.org")))
    (org-latex-preview-mode-display-live t)
    :config
    (setq org-format-latex-options (plist-put org-format-latex-options :scale 0.6))
    (require 'ox-latex)
    (require 'ox-beamer)
    (add-to-list 'org-latex-classes '("myreport" "\\documentclass[11pt]{report}"
                                      ("\\chapter{%s}" . "\\chapter*{%s}")
                                      ("\\section{%s}" . "\\section*{%s}")
                                      ("\\subsection{%s}" . "\\subsection*{%s}")
                                      ("\\subsubsection{%s}" . "\\subsubsection*{%s}")))
    :hook
    (org-mode . visual-line-mode)
    (org-mode . flyspell-mode)
    (org-mode . org-latex-preview-mode))

toki pona support

  (with-eval-after-load 'ox
    (add-to-list 'org-export-dictionary	       
                 '("Footnotes" ("tok" :default "toki anpa")))
    (add-to-list 'org-export-dictionary	       
                 '("Author" ("tok" :default "jan toki")))
    (add-to-list 'org-export-dictionary	       
                 '("Table of Contents" ("tok" :default "ni li lon lipu ni::")))
    (add-to-list 'org-export-dictionary	       
                 '("Created" ("tok" :default "mi pali e ni lon tenpo"))))

Prettify

  (use-package org-modern
    :hook ((org-mode . org-modern-mode)
           (org-agenda-finalize . org-modern-agenda)))

Simple Presentations

  (use-package org-present)

Org Bloggy stuff

  (setq org-publish-project-alist
        `(("org-posts"
           :base-directory "~/repos/blog/posts/"
           :publishing-directory "/ssh:wball@ballcloud.cc:~/blog/"
           :base-extension "org"
           :recursive t
           :publishing-function org-html-publish-to-html
  	 :author "William Ball"
  	 :language "en"
           :auto-sitemap t
           :sitemap-filename "archive.org"
           :sitemap-title "Archive"
           :sitemap-style list
  	 :sitemap-sort-files anti-chronologically
           :html-head "<link rel=\"stylesheet\" href=\"/static/style.css\" type=\"text/css\"/><link rel=\"icon\" href=\"static/favicon.ico\"/>"
           :html-preamble t
           :html-preamble-format (("en" "<div class=\"blog-header\"><a href=\"archive.html\">Post Archive</a></div>")
                                  ("tok" "<div class=\"blog-header\"><a href=\"archive.html\">toki ante</a></div>"))
           )
  	("org-pages"
  	 :base-directory "~/repos/blog/pages/"
  	 :publishing-directory "/ssh:wball@ballcloud.cc:~/blog/"
  	 :base-extension "org"
  	 :recursive t
  	 :publishing-function org-html-publish-to-html
  	 :author "William Ball"
  	 :language "en"
  	 :html-head "<link rel=\"stylesheet\" href=\"/static/style.css\" type=\"text/css\"/><link rel=\"icon\" href\"static/favicon.ico\"/>"
  	 )
  	("org-static"
  	 :base-directory "~/repos/blog/static/"
  	 :publishing-directory "/ssh:wball@ballcloud.cc:~/blog/static/"
  	 :base-extension "ico\\|ttf\\|css"
  	 :publishing-function org-publish-attachment
  	 :recursive t
  	 )
  	("org-media"
  	 :base-directory "~/repos/blog/media/"
  	 :publishing-directory "/ssh:wball@ballcloud.cc:~/blog/media/"
  	 :base-extension "png\\|svg\\|pdf\\|mp4\\|mp3\\|ogg"
  	 :publishing-function org-publish-attachment
  	 :recursive t
  	 )
  	("org" :components ("org-posts" "org-static" "org-media" "org-pages"))
  	))

  (use-package htmlize)

Simple http server

  (use-package simple-httpd)

Pdfs

Pdf tools

  (use-package pdf-tools)

Terminals/Shells

Eshell

  (defun wball/configure-eshell ()
    (add-hook 'eshell-pre-command-hook 'eshell-save-some-history)
    (add-to-list 'eshell-output-filter-functions 'eshell-truncate-buffer)

    (setq eshell-history-size 10000
          eshell-buffer-maximum-lines 10000
          eshell-history-ignoredups t
          eshell-scroll-to-bottom-on-input t))

  (use-package eshell
    :ensure nil
    :commands eshell
    :hook (eshell-first-time-mode . wball/configure-eshell)
    :bind (("C-c e" . eshell))
    :config
    (with-eval-after-load 'esh-opt
      (setq eshell-destroy-buffer-when-process-dies t)))

  (defalias 'eshell/ff 'find-file)
  (defalias 'eshell/fo 'find-file-other-window)

eat

  (use-package eat)

Dired

  (use-package emacs
    :ensure nil
    :commands (dired dired-jump)
    :custom ((dired-listing-switches "-agho --group-directories-first"))
    :config
    (require 'dired-x))

  (use-package dired-hide-dotfiles
    :hook (dired-mode . dired-hide-dotfiles-mode))

Misc

magit

  (use-package magit)