Emacs is a neat text editor
Automagically update packages weekly if updates are available.
;; Automatically pull updates weekly and hide results
(use-package auto-package-update
:straight t
:custom
(auto-package-update-interval 7)
(auto-package-update-hide-results t)
:config
(auto-package-update-maybe))
Gcmh uses some clever trickery to perform garbage collections in when idle, minimizing the impact. It’s enabled last thing in init.el, allowing initialization without gc, but enabling it before user input.
(use-package gcmh
:straight t)
The following section configures the basics of the stock Emacs UI. Inint.el also disables several UI elements as well as the startup message. Here we configure default buffer rendering and UI behavior.
(set-fringe-mode 0)
;; Show column numbers in the modeline
(column-number-mode)
;; Enable line numbers for some modes
(dolist (mode '(text-mode-hook
prog-mode-hook
conf-mode-hook))
(add-hook mode (lambda () (display-line-numbers-mode 1))))
;; 8 character tabs are too damn large
(setq-default tab-width 4)
;; Default behavior is case sensitive for sorting.
;; Just sort alphabetically
(setq sort-fold-case t)
Default file backup behavior is awful. Make it less awful:
(setq user-emacs-directory "~/.cache/emacs")
(use-package no-littering
:straight t)
;; no-littering doesn't set this by default so we must place
;; auto save files in the same path as it uses for sessions
(setq auto-save-file-name-transforms
`((".*" ,(no-littering-expand-var-file-name "auto-save/") t)))
Load evil super early so my key bindings don’t change when I goof my config
Evil mode brings Vim keybindings to Emacs.
(defun void/evil-hook ()
(dolist (mode '(custom-mode
eshell-mode
git-rebase-mode
erc-mode
circe-server-mode
circe-chat-mode
circe-query-mode
sauron-mode
term-mode))
(add-to-list 'evil-emacs-state-modes mode)))
(use-package evil
:straight t
:init
(setq evil-want-integration t)
(setq evil-want-keybinding nil)
(setq evil-want-C-u-scroll t)
(setq evil-want-C-i-jump nil)
:hook (evil-mode . void/evil-hook)
:config
(evil-mode 1)
(define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state)
(define-key evil-insert-state-map (kbd "C-h") 'evil-delete-backward-char-and-join)
;; Use visual line motions everywhere
(evil-global-set-key 'motion "j" 'evil-next-visual-line)
(evil-global-set-key 'motion "k" 'evil-previous-visual-line)
(evil-set-initial-state 'messages-buffer-mode 'normal)
(evil-set-initial-state 'dashboard-mode 'normal))
Evil Collection Provides a sensible set of file types and automatically configures Evil mode for them
(use-package evil-collection
:straight t
:init
(evil-collection-init))
Fira Code is a beautiful, open source font for programming. It has very pretty ligatures for common programming symbol combinations.
;; Used as default font for most things
(set-face-attribute 'default nil :font "Fira Code Retina" :height 120)
(use-package fira-code-mode
:straight t
:hook prog-mode) ; mode to enable fira-code-mode in
;;Fira Code Mode requires that the fonts be installed to the system before use.
;; Check for them and install if unavailable
(if(not(find-font(font-spec :name "Fira Code Symbol")))
(fira-code-mode-install-fonts))
(use-package all-the-icons
:straight t)
;; All the icons requires that the fonts be installed to the system before use.
;; Check for them and install if unavailable, silencing the confirmation
(if(not(find-font(font-spec :name "all-the-icons")))
(all-the-icons-install-fonts 0))
Set of packages to improve the look and functionality of the UI
Beacon makes it easy to find your cursor when the screen moves
(use-package beacon
:straight t
:config
(beacon-mode 1))
The Doom modeline provides a concise view of current mode functionality
(use-package doom-modeline
:straight t
:init (doom-modeline-mode 1)
:custom ((doom-modeline-height 16)))
(use-package doom-themes
:straight t
:config
(doom-themes-visual-bell-config)
(doom-themes-treemacs-config)
:init
(load-theme 'doom-gruvbox t))
Add friendly mulit-editing
(use-package multiple-cursors
:straight t
:config
(global-set-key (kbd "C-S-c C-S-c") 'mc/edit-lines))
Rainbow delimiters makes it much easier to match up scope delimiters such as parenthesis
(use-package rainbow-delimiters
:straight t
:hook (prog-mode . rainbow-delimiters-mode))
(use-package solaire-mode
:straight t
:config
(solaire-global-mode +1))
Treemacs provides a file and project explorer. It gives a nice outline similar to many IDEs.
(use-package treemacs
:straight t
:ensure t
:defer t
:init(with-eval-after-load 'winum
(define-key winum-keymap (kbd "M-0") #'treemacs-select-window)))
(use-package treemacs-evil
:straight t
:after evil treemacs)
(use-package treemacs-magit
:straight t
:after magit treemacs)
(use-package treemacs-projectile
:straight t
:after projectile treemacs)
Undo-Tree provides a powerful visualization of the undo tree structure
(use-package undo-tree
:straight t
:config
(global-undo-tree-mode 1))
(use-package vertico
:straight t
:bind (:map vertico-map
("C-j" . vertico-next)
("C-k" . vertico-previous)
("C-f" . vertico-exit)
:map minibuffer-local-map
("M-h" . backward-kill-word))
:custom
(vertico-cycle t)
:init
(vertico-mode))
(use-package savehist
:straight t
:init
(savehist-mode))
(use-package marginalia
:straight t
:after vertico
:ensure t
:custom
(marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil))
:init
(marginalia-mode))
(use-package ctrlf
:straight t
:config
(ctrlf-mode +1))
(use-package orderless
:straight t)
(setq completion-styles '(orderless)
completion-category-defaults nil
completion-category-overrides '((file (styles . (partial-completion)))))
Prescient is a sorting and filtering extension which improves the usability of suggestions by from vertico, Company
(use-package prescient
:straight t)
(use-package company-prescient
:straight t
:after company prescient)
Helpful is an alternative to the built-in emacs help functionality that provides considerably more contextual information.
(use-package helpful
:straight t
:bind
([remap describe-command] . helpful-command)
([remap describe-key] . helpful-key))
Which-key provides helpful command completion for partial command prefixes. It’s configured with an idle delay, so that it doesn’t pop up when commands are entered quickly, but shows the help after a short delay.
(use-package which-key
:straight t
:init (which-key-mode)
:diminish(which-key-mode)
:config
(setq which-key-idle-delay 0.3))
Packages and configuration related to key bindings
General provides a convenient key binding method for key bindings. Set up custom leader key with space bar.
(setq mac-command-modifier 'meta)
(use-package general
:straight t
:config (general-create-definer void/leader-keys
:keymaps '(normal insert visual emacs) :prefix "SPC" :global-prefix
"C-SPC") (void/leader-keys "to" '(:ignore t :which-key "toggles")
"tt" '(counsel-load-theme :which-key "chose theme")))
(general-define-key "C-M-j" 'counsel-switch-buffer)
Hydra provides a utility for creating modal clusters of bindings which dismiss automatically after a specified timeout. This is used to create a custom mode for quickly scaling text.
(use-package hydra
:straight t)
(defhydra hydra-text-scale (:timeout 4)
"scale text"
("j" text-scale-increase "in")
("k" text-scale-decrease "out")
("f" nil "finished" :exit t))
(void/leader-keys
"ts" '(hydra-text-scale/body :which-key "scale-text" ))
;; Replace list hyphen with dot
(font-lock-add-keywords 'org-mode
'(("^ *\\([-]\\) "
(0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•"))))))
;; Set faces for heading levels
(dolist (face '((org-level-1 . 1.2)
(org-level-2 . 1.1)
(org-level-3 . 1.05)
(org-level-4 . 1.0)
(org-level-5 . 1.1)
(org-level-6 . 1.1)
(org-level-7 . 1.1)
(org-level-8 . 1.1)))
(set-face-attribute (car face) nil :font "Cantarell" :weight 'regular :height (cdr face)))
;; Ensure that anything that should be fixed-pitch in Org files appears that way
(set-face-attribute 'org-block nil :foreground nil :inherit 'fixed-pitch)
(set-face-attribute 'org-table nil :inherit 'fixed-pitch)
(set-face-attribute 'org-formula nil :inherit 'fixed-pitch)
(set-face-attribute 'org-code nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-table nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-special-keyword nil :inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-meta-line nil :inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-checkbox nil :inherit 'fixed-pitch)
(set-face-attribute 'line-number nil :inherit 'fixed-pitch)
(set-face-attribute 'line-number-current-line nil :inherit 'fixed-pitch)
Configure org-mode itself. Replace ellipsis in collapsed sections with a nice arrow indicating additional content.
(setq org-agenda-files
'("~/.org/tasks.org"
"~/.org/birthdays.org"))
(setq org-ellipsis " ▾")
(setq org-log-done t)
Org mode babel integration for emacs-lisp and python
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)
(python . t)))
(setq org-confirm-babel-evaluate nil)
(push '("conf-unix" . conf-unix) org-src-lang-modes)
(require 'org-tempo )
(add-to-list 'org-structure-template-alist '("c99" . "src c"))
(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
(add-to-list 'org-structure-template-alist '("py" . "src python"))
(add-to-list 'org-structure-template-alist '("sh" . "src shell"))
Nice bullets
(use-package org-superstar
:straight t
:after org
:hook( org-mode . org-superstar-mode )
:custom
(org-superstar-remove-leading-stars t)
(org-superstar-headline-bullets-list '("◉" "○" "●" "○" "●" "○" "●")))
Configure org mode content to render in center of buffer
(defun void/org-mode-visual-fill ()
(setq visual-fill-column-width 120
visual-fill-column-center-text t)
(visual-fill-column-mode 1)
(visual-line-mode 1))
(use-package visual-fill-column
:straight t
:after org
:defer t
:hook (org-mode . void/org-mode-visual-fill)
(markdown-mode . void/org-mode-visual-fill))
I’ll probably have something to say here eventually
(use-package org-roam
:straight t
:after org
:init
(setq org-roam-v2-ack t) ;; Never had a 1.0 database, don't worry about it
:custom
(org-roam-directory (file-truename "~/.roam/"))
:bind (("C-c n l" . org-roam-buffer-toggle)
("C-c n f" . org-roam-node-find)
("C-c n g" . org-roam-graph)
("C-c n i" . org-roam-node-insert)
("C-c n c" . org-roam-capture)
;; Dailies
("C-c n j" . org-roam-dailies-capture-today)
:map org-mode-map
("C-M-i" . completion-at-point))
:config
(org-roam-db-autosync-mode)
;; If using org-roam-protocol
(require 'org-roam-protocol))
Company is a completion framework for Emacs. It includes backends for many common tasks.
(use-package company
:straight t
:init
(add-hook 'after-init-hook 'global-company-mode))
Flycheck provides on the fly syntax checking.
(use-package flycheck
:straight t
:init (global-flycheck-mode))
Forge provides integration to advanced git hosting features from providers such as GitHub and GitLab.
(use-package forge
:straight t)
(use-package highlight-indent-guides
:straight t
:config
(setq highlight-indent-guides-method 'character))
lsp-mode provides advanced language server based features to Emacs.
(defun void/lsp-mode-setup ()
(setq lsp-headerline-breadcrumb-segments '(path-up-to-project file symbols))
(lsp-headerline-breadcrumb-mode))
(use-package lsp-mode
:straight t
:init
;; set prefix for lsp-command-keymap (few alternatives - "C-l", "C-c l")
(setq lsp-keymap-prefix "C-c l")
:config
(setq read-process-output-max (* 5 1024 1024))
(lsp-enable-which-key-integration))
(use-package lsp-ui
:straight t
:after lsp-mode
:hook (lsp-mode . lsp-ui-mode)
:custom
(lsp-ui-doc-position 'atpoint))
(use-package dap-mode
:straight t
:after lsp-mode
:config
(require 'dap-gdb-lldb)
(dap-register-debug-template "Rust::GDB Run Configuration"
(list :type "gdb"
:request "launch"
:name "GDB::Run"
:gdbpath "rust-gdb"
:target nil
:cwd nil)))
Magit is an incredible, text based git client. It has a beautiful, text based graph, and all of the power of the command line interface (+ some really nice convenience features).
(use-package magit
:straight t)
Projectile is a project interaction library for Emacs that adds capabilities for quickly navigating around the files within a project.
(use-package projectile
:straight t
:diminish projectile-mode
:config (projectile-mode)
:bind-keymap
("C-c p" . projectile-command-map)
:init
(setq projectile-enable-cmake-presets t)
(setq projectile-switch-project-action #'projectile-dired))
Ripgrep provides blazing fast search capabilities. Integrated with Projectile via projectile-ripgrep
(use-package ripgrep
:straight t)
(use-package projectile-ripgrep
:straight t
:after projectile ripgrep)
Yasnippet expands templates
(use-package yasnippet
:straight t
:config
(yas-global-mode t))
Cleanup
(require 'whitespace)
(setq whitespace-style
'(face trailing indentation::tab space-before-tab::tab space-after-tab))
(use-package ws-butler
:straight t
:config
(ws-butler-global-mode))
(add-hook 'prog-mode-hook ; turn on whitespace-mode in any 'programming mode'
(lambda ()
(whitespace-mode t)))
CCLS is a C/C++ indexer which uses the compilation commands and clang frontend to ensure that the indexing is accurate.
(use-package ccls
:straight t
:after lsp
:hook ((c-mode c++-mode objc-mode cuda-mode) .
(lambda ()
(require 'ccls)
(lsp)))
:init
(with-eval-after-load "lsp-mode"
(add-to-list 'lsp-enabled-clients 'ccls))
(setq ccls-executable "ccls")
(setq ccls-initialization-options '(:cache (:directory "build/.ccls-cache")
:clang ( :excludeArgs ["-working-directory"] ))))
(use-package clang-format+
:straight t
:hook ((c-mode c++-mode) .
(lambda ()
(require clang-format+)
(clang-format+-mode) )))
(use-package omnisharp
:straight t
:hook
(csharp-mode . (lambda ()
(omnisharp-mode)
(add-to-list 'company-backends 'company-omnisharp))))
;; add support for xaml and cshtml
(add-to-list 'auto-mode-alist '("\\.xaml\\'" . xml-mode))
(add-to-list 'auto-mode-alist '("\\.cshtml\\'" . html-mode))
(add-to-list 'auto-mode-alist '("\\.razor\\'" . html-mode))
Add support for CMake files.
(use-package cmake-mode
:straight t)
Add support for Dart and Flutter development.
(use-package dart-mode
:straight t)
(use-package lsp-dart
:straight t
:after lsp-mode
:hook
(dart-mode-hook . lsp))
Add support for Jenkinsfiles
(use-package jenkinsfile-mode
:straight t)
(use-package make-mode
:straight t
:mode (( "\\Doxyfile\\'" . makefile-mode)))
Markdown-mode is a major mode for editing markdown files.
(use-package markdown-mode
:straight t
:commands
(markdown-mode gfm-mode)
:mode (("README\\.md\\'" . gfm-mode)
("\\.md\\'" . markdown-mode)
("\\.markdown\\'" . markdown-mode))
:init (setq markdown-command "pandoc"))
(use-package meson-mode
:straight t)
PlantUML is an excellent uml and diagram markup language. It allows you to create pretty diagrams with very little effort. Plantuml-mode adds a major mode for editing PlantUML diagrams.
(use-package plantuml-mode
:straight t
:config
(setq plantuml-default-exec-mode 'executable))
(use-package lsp-jedi
:straight t
:ensure t
:config
(with-eval-after-load "lsp-mode"
(add-to-list 'lsp-enabled-clients 'jedi)))
(use-package python-black
:demand t
:straight t
:after python lsp-mode
:hook (python-mode . (lambda ()
(python-black-on-save-mode-enable-dwim)
(lsp))))
(use-package rustic
:ensure t
:straight t
:init
(with-eval-after-load "lsp-mode"
(add-to-list 'lsp-enabled-clients 'rust-analyzer)
(require 'dap-cpptools))
:after lsp-mode)
Swift language support is added with the swift-mode package. Language server features are added with lsp-sourcekit. Finally, syntax checking is provided by
(use-package lsp-sourcekit
:straight t
:after lsp-mode
:config
(setq lsp-sourcekit-executable "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/sourcekit-lsp"))
(use-package swift-mode
:straight t
:hook (swift-mode . (lambda () (lsp))))
(require 'ansi-color)
(defun colorize-compilation-buffer ()
(ansi-color-apply-on-region compilation-filter-start (point-max)))
(add-hook 'compilation-filter-hook 'colorize-compilation-buffer)
(use-package typescript-mode
:ensure t
:straight t
:init
(with-eval-after-load "lsp-mode"
(add-to-list 'lsp-enabled-clients 'ts-ls))
:mode "\\.ts\\'"
:hook (typescript-mode . lsp-deferred))
(use-package yaml-mode
:straight t)
Configuration for terminals which all use
(setq explicit-shell-file-name "zsh")
(setq term-prompt-regexp "^#$%>\n]*[#$%>] *")
(use-package vterm
:straight t
:commands vterm
:config
(setq vterm-max-scrollback 10000))
Emacs is frequently started from the UI instead of terminal. Make sure the path still works.
(defun void/configure-eshell ()
;; Save a command history
(add-hook 'eshell-pre-command-hook 'eshell-save-some-history)
;; Truncate buffer for performance
(add-to-list 'eshell-output-filter-functions 'eshell-truncate-buffer)
;; Bind C-r to pull up history buffer
(evil-define-key '(normal insert visual) eshell-mode-map (kbd "C-r") 'counsel-esh-history)
;; Renormalize keymaps
(evil-normalize-keymaps)
(setq eshell-history-size 10000
eshell-buffer-maximum-lines 10000
eshell-hist-ignoredups t
eshell-scroll-to-bottom-on-input t))
(use-package exec-path-from-shell
:straight t)
(when (memq window-system '(mac ns x))
(exec-path-from-shell-initialize))
(use-package eshell-git-prompt
:straight t)
(use-package eshell
:straight t
:hook (eshell-first-time-mode . void/configure-eshell)
:config
(eshell-git-prompt-use-theme 'powerline))
(use-package eterm-256color
:straight t
:hook (term-mdode . eterm-256color-mode))
(use-package mu4e
:config
(require 'org-mu4e)
;; Refresh mail using isync every 10 minutes
(setq mu4e-update-interval (* 10 60))
(setq mu4e-get-mail-command "mbsync -a")
(setq mu4e-maildir "~/mail")
;; Set up vertico for completions
(setq mu4e-completing-read-function #'vertico--advice)
;; Force Mu4e to change filenames when moving messages to different folders
(setq mu4e-change-filenames-when-moving t)
(setq mu4e-contexts
'(,(make-mu4e-context
:name "Voidstar"
:match-func (lambda (msg)
(when msg
(string-prefix-p "/voidstar"
(mu4e-message-field msg :maildir))))
:vars '(
(user-full-name . "Zach Heylmun")
(user-mail-address . "zach@voidstarsolutions.com")
(mu4e-sent-folder . "/voidstar/Sent Items")
(mu4e-trash-folder . "/voidstar/Trash")
(mu4e-drafts-folder . "/voidstar/Drafts")
(mu4e-refile-folder . "/voidstar/Archive")
(mu4e-sent-messages-behavior . sent)
))
,(make-mu4e-context
:name "Personal"
:match-func (lambda (msg) (when msg
(string-prefix-p "/Personal" (mu4e-message-field msg :maildir))))
:vars '
(mu4e-sent-folder . "/Personal/Sent")
(mu4e-trash-folder . "/Personal/Deleted")
(mu4e-refile-folder . "/Personal/Archive")
))
))
(setq mu4e-context-policy 'pick-first)
)