mirror of
https://codeberg.org/andyscott/dotfiles.git
synced 2024-12-22 09:53:10 -05:00
1759 lines
52 KiB
Cheetah
1759 lines
52 KiB
Cheetah
;;; init.el --- GNU Emacs Initialization File -*- lexical-binding: t; -*-
|
|
|
|
;; Author: Andrew Scott <git at andyscott dot me>
|
|
;; URL: https://codeberg.org/andyscott/dotfiles
|
|
;; Keywords: convenience, tools
|
|
|
|
;; This file is not part of GNU Emacs.
|
|
|
|
;; Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
|
;; software and associated documentation files (the "Software"), to deal in the Software
|
|
;; without restriction, including without limitation the rights to use, copy, modify,
|
|
;; merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
|
;; permit persons to whom the Software is furnished to do so.
|
|
|
|
;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
;; INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
;; PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
;; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
;; OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
;;; Commentary:
|
|
|
|
;; My Emacs initialization file.
|
|
|
|
;;; Code:
|
|
|
|
;;;; Debug Init
|
|
|
|
;;;;; Debug on Error
|
|
|
|
;; (setq debug-on-error t)
|
|
|
|
;;;;; Profiling
|
|
|
|
;;;;;; Use Package Report
|
|
|
|
;; (with-eval-after-load 'elpaca
|
|
;; (add-hook 'elpaca-after-init-hook #'use-package-report))
|
|
|
|
;;;;;; Profiler
|
|
|
|
;; (profiler-start 'cpu+mem)
|
|
;; (with-eval-after-load 'elpaca
|
|
;; (add-hook 'elpaca-after-init-hook (lambda ()
|
|
;; (profiler-stop)
|
|
;; (profiler-report))))
|
|
|
|
;;;; package Management
|
|
|
|
;;;;; Elpaca
|
|
|
|
(defvar elpaca-installer-version 0.7)
|
|
(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
|
|
:files (:defaults "elpaca-test.el" (:exclude "extensions"))
|
|
:build (:not elpaca--activate-package)))
|
|
(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)
|
|
(load "./elpaca-autoloads")))
|
|
(add-hook 'after-init-hook #'elpaca-process-queues)
|
|
(elpaca `(,@elpaca-order))
|
|
|
|
(defmacro use-feature (name &rest args)
|
|
"Like `use-package' but without updating built-in packages.
|
|
|
|
NAME and ARGS are in `use-package'. Credit to @progfolio:
|
|
<https://github.com/progfolio/.emacs.d?tab=readme-ov-file#use-package>"
|
|
(declare (indent defun))
|
|
`(use-package ,name
|
|
:ensure nil
|
|
,@args))
|
|
|
|
(defun +elpaca-build-steps-with-unload (pkg)
|
|
"Some built-in PKG need special handling for upgrades.
|
|
|
|
Unloads PKG before continuing with build. See:
|
|
<https://github.com/progfolio/elpaca/issues/216>"
|
|
(append (butlast (if (file-exists-p (file-name-concat elpaca-builds-directory
|
|
(symbol-name pkg)))
|
|
elpaca--pre-built-steps elpaca-build-steps))
|
|
(list `(lambda (e)
|
|
(when (featurep ',pkg) (unload-feature ',pkg t))
|
|
(elpaca--continue-build e))
|
|
'elpaca--activate-package)))
|
|
|
|
;; Unload and build `seq'
|
|
(elpaca `(seq :build ,(+elpaca-build-steps-with-unload 'seq)))
|
|
|
|
;;;;; use-package
|
|
|
|
(elpaca elpaca-use-package
|
|
(require 'elpaca-use-package)
|
|
(elpaca-use-package-mode)
|
|
(setopt use-package-always-ensure t
|
|
;; NOTE: Comment/remove stats when done profiling startup
|
|
use-package-compute-statistics t))
|
|
|
|
;;;;;; use-package and debugging
|
|
|
|
(if debug-on-error
|
|
(setopt use-package-verbose t
|
|
use-package-expand-minimally nil
|
|
use-package-compute-statistics t)
|
|
(setopt use-package-verbose nil
|
|
use-package-expand-minimally t))
|
|
|
|
;; NOTE: Must wait for `elpaca--queues' to be processed
|
|
(elpaca-wait)
|
|
|
|
;;;;;; use-package keyword order
|
|
|
|
;; :disabled
|
|
;; :load-path
|
|
;; :requires
|
|
;; :defines
|
|
;; :functions
|
|
;; :preface
|
|
;; :if :when :unless
|
|
;; :no-require
|
|
;; :catch
|
|
;; :after
|
|
;; :custom
|
|
;; :custom-face
|
|
;; :bind
|
|
;; :bind*
|
|
;; :bind-keymap
|
|
;; :bind-keymap*
|
|
;; :interpreter
|
|
;; :mode
|
|
;; :magic
|
|
;; :magic-fallback
|
|
;; :hook
|
|
;; :commands
|
|
;; :autoload
|
|
;; :init
|
|
;; :defer
|
|
;; :demand
|
|
;; :load
|
|
;; :config
|
|
|
|
;;;; Basic options
|
|
|
|
;;;;; ANSI Escape Codes (Operating System Commands)
|
|
|
|
(use-feature ansi-osc
|
|
:custom
|
|
(ansi-osc-for-compilation-buffer t "Collect and handle OSC sequences")
|
|
:hook
|
|
(ansi-osc-compilation-filter . compilation-filter))
|
|
|
|
;;;;; Auto Revert
|
|
|
|
(use-feature autorevert
|
|
:custom
|
|
(auto-revert-interval 10 "Increase time between file checks")
|
|
:hook
|
|
(elpaca-after-init . global-auto-revert-mode))
|
|
|
|
;;;;; Buffer Menu
|
|
|
|
(use-feature ibuffer
|
|
:bind
|
|
("C-x C-b" . ibuffer))
|
|
|
|
;;;;; Customization settings & commands
|
|
|
|
(use-feature cus-edit
|
|
:custom
|
|
(custom-file null-device "Fall into the nothingness that awaits you..."))
|
|
|
|
(use-feature custom
|
|
:custom
|
|
(custom-safe-themes t))
|
|
|
|
;;;;; "Electric"
|
|
|
|
;;;;;; Electric Indent/Quote/Newline
|
|
|
|
(use-feature electric
|
|
:hook
|
|
;; REVIEW: See local var `electric-indent-inhibit'
|
|
((org-mode
|
|
python-mode
|
|
python-ts-mode) . (lambda () (electric-indent-local-mode -1))))
|
|
|
|
|
|
;;;;;; Electric Pair Mode
|
|
|
|
(use-feature elec-pair
|
|
:hook ((conf-mode
|
|
markdown-mode
|
|
org-mode
|
|
prog-mode) . electric-pair-local-mode))
|
|
|
|
;;;;; Emacs
|
|
|
|
(use-feature emacs
|
|
:bind
|
|
(:map global-map
|
|
;; Disable `suspend-frame' shortcut (currently overwritten by `undo-fu' anyway)
|
|
("C-z" . nil)
|
|
("C-x k" . my-kill-buffer)
|
|
("C-x 4 C-0" . as/kill-buffer-and-other-window)
|
|
;; Escape behaves like C-g
|
|
("<escape>" . keyboard-escape-quit))
|
|
:custom
|
|
(auto-window-vscroll nil "Stop scro my window")
|
|
(completion-ignore-case t "Ignore case for completions")
|
|
(cursor-type 'bar "Cursor appearance")
|
|
(enable-recursive-minibuffers t "Allow minibuffer commands in the minibuffer")
|
|
(fast-but-imprecise-scrolling t "Don't fontify when scrolling")
|
|
(fill-column 79 "Increase default column for line wrapping")
|
|
(history-delete-duplicates t "Delete identical elements when adding to history")
|
|
(indicate-empty-lines t "Show empty lines in fringe")
|
|
(inhibit-compacting-font-caches t "More memory, potentially more responsive")
|
|
(minibuffer-prompt-properties
|
|
'(read-only t cursor-intangible t face minibuffer-prompt) "Disable prompt in minibuffer")
|
|
(next-screen-context-lines 0 "Keep point position when scrolling")
|
|
(read-buffer-completion-ignore-case t "Ignore case for buffer name completions")
|
|
(scroll-step 1 "Try scrolling N lines before recentering")
|
|
(scroll-conservatively 101 "I'll tell /you/ when to recenter")
|
|
(scroll-preserve-screen-position t "Point keeps screen position when moved vertically")
|
|
(sentence-end-double-space nil "Single space ends sentences")
|
|
(tab-always-indent 'complete "Complete at point if line is already indented")
|
|
;; REVIEW
|
|
;; tab-first-completion 'word-or-paren-or-punct
|
|
(use-short-answers t "Never make me fully type 'yes' and 'no'")
|
|
:custom-face
|
|
{{- if eq .chezmoi.hostname "helix" }}
|
|
(default ((t (:font "Hack" :height 135))))
|
|
(fixed-pitch ((t (:font "Hack" :height 135))))
|
|
(variable-pitch ((t (:font "Liberation Sans" :height 150))))
|
|
{{- else }}
|
|
(default ((t (:font "Hack" :height 120))))
|
|
(fixed-pitch ((t (:font "Hack" :height 120))))
|
|
(variable-pitch ((t (:font "Liberation Sans" :height 120))))
|
|
{{- end }}
|
|
:hook
|
|
(minibuffer-setup . cursor-intangible-mode)
|
|
(elpaca-after-init . (lambda ()
|
|
(message "Emacs loaded in %s with %d garbage collections."
|
|
(format "%.2f seconds"
|
|
(float-time
|
|
(time-subtract (current-time) before-init-time)))
|
|
gcs-done)))
|
|
:config
|
|
(defun display-startup-echo-area-message ()
|
|
"Somehow less awful than messing with `inhibit-startup-echo-area-message'
|
|
|
|
I could use advice, but I'll never want to see this message.")
|
|
|
|
(defun my-kill-buffer ()
|
|
"Like `kill-buffer' but with a diff option"
|
|
(interactive)
|
|
(catch 'quit
|
|
(save-window-excursion
|
|
(let (done)
|
|
(when (and buffer-file-name (buffer-modified-p))
|
|
(while (not done)
|
|
(let ((response (read-char-choice
|
|
(format "Save file %s? (y, n, d, q) " (buffer-file-name))
|
|
'(?y ?n ?d ?q))))
|
|
(setq done (cond
|
|
((eq response ?q) (throw 'quit nil))
|
|
((eq response ?y) (save-buffer) t)
|
|
((eq response ?n) (set-buffer-modified-p nil) t)
|
|
((eq response ?d) (diff-buffer-with-file) nil))))))
|
|
(kill-buffer (current-buffer))
|
|
(force-mode-line-update)))))
|
|
|
|
(defun as/kill-buffer-and-other-window ()
|
|
"Kill the most recently selected buffer and delete it's window"
|
|
(interactive)
|
|
(other-window -1)
|
|
(when (not (one-window-p))
|
|
(my-kill-buffer)
|
|
(delete-window)))
|
|
|
|
(defun crm-indicator (args)
|
|
"For `vertico' / Adds a prompt indicator to `completing-read-multiple'"
|
|
(cons (format "[CRM%s] %s"
|
|
(replace-regexp-in-string
|
|
"\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" ""
|
|
crm-separator)
|
|
(car args))
|
|
(cdr args)))
|
|
(advice-add #'completing-read-multiple :filter-args #'crm-indicator))
|
|
|
|
;;;;; Fill Column Indicator
|
|
|
|
(use-feature display-fill-column-indicator
|
|
:hook
|
|
((conf-mode prog-mode) . display-fill-column-indicator-mode))
|
|
|
|
;;;;; Spell checking
|
|
|
|
;;;;;; Flyspell
|
|
|
|
(use-feature flyspell
|
|
:custom
|
|
(flyspell-use-meta-tab nil "Disable correction with M-TAB")
|
|
:hook
|
|
(((git-commit-mode text-mode) . flyspell-mode)))
|
|
|
|
;;;;;; Flyspell Correction Functions
|
|
|
|
(use-package flyspell-correct
|
|
:after (flyspell)
|
|
:bind
|
|
(:map flyspell-mode-map
|
|
("C-M-." . flyspell-correct-wrapper)))
|
|
|
|
;;;;; Frame & Cursor Blink
|
|
|
|
(use-feature frame
|
|
:custom
|
|
(blink-cursor-delay 1.0 "Increase time between blinks")
|
|
(blink-cursor-interval 0.75 "Increase blink length"))
|
|
|
|
;;;;; Help System
|
|
|
|
(use-feature help
|
|
:defer t
|
|
:custom
|
|
(help-enable-variable-value-editing t "Allow editing in *Help* buffers")
|
|
(help-window-select t "Always select *Help* buffers"))
|
|
|
|
;;;;;; Better Help Buffers (`helpful.el')
|
|
|
|
(use-package helpful
|
|
:bind
|
|
("C-h f" . helpful-callable)
|
|
("C-h v" . helpful-variable)
|
|
("C-h x" . helpful-command)
|
|
("C-c C-d" . helpful-at-point)
|
|
("C-c F" . helpful-function))
|
|
;;;;; Keybind Hints
|
|
|
|
;;;;;; Which Key
|
|
|
|
;; NOTE: Will be built-in for Emacs 30?
|
|
(use-package which-key
|
|
:custom
|
|
(which-key-idle-delay 0.3 "Decrease idle delay")
|
|
(which-key-use-C-h-commands nil "Using `embark-prefix-help-command'")
|
|
:hook
|
|
(elpaca-after-init . which-key-mode))
|
|
|
|
;;;;; Display Line Number Mode
|
|
|
|
(use-feature display-line-numbers
|
|
:custom
|
|
(display-line-numbers-grow-only t "Maintain width for large files")
|
|
:hook
|
|
((conf-mode prog-mode) . display-line-numbers-mode))
|
|
|
|
;;;;; Mini-buffer
|
|
|
|
;;;;;; Mini-buffer Settings
|
|
|
|
(use-feature minibuffer
|
|
:custom
|
|
(read-file-name-completion-ignore-case t "Ignore file name case for minibuffer completions"))
|
|
|
|
;;;;;; Mini-buffer History
|
|
|
|
(use-feature savehist
|
|
:custom
|
|
(savehist-additional-variables
|
|
'(command-history compile-command kill-buffer kill-ring) "Add additional variables to history")
|
|
(savehist-autosave-interval 120 "Decrease time between auto-saves")
|
|
(savehist-file
|
|
(expand-file-name "savehist" xdg_cache_home) "Move history file to XDG_CACHE_HOME")
|
|
:hook
|
|
(elpaca-after-init . savehist-mode))
|
|
|
|
;;;;;; Embark (Context Menu)
|
|
|
|
(use-package embark
|
|
:custom
|
|
(prefix-help-command
|
|
#'embark-prefix-help-command "Change function to run when `help-char' follows a prefix key")
|
|
:bind
|
|
(("C-." . embark-act)
|
|
("C-;" . embark-dwim)
|
|
("C-h B" . embark-bindings)
|
|
("C-c M-k" . embark-kill-buffer-and-window))
|
|
:defer 3
|
|
:config
|
|
;; Hide the mode line
|
|
(add-to-list 'display-buffer-alist '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
|
|
nil
|
|
(window-parameters (mode-line-format . none)))))
|
|
|
|
;;;;;; Embark + Consult
|
|
|
|
(use-package embark-consult
|
|
:if (and (elpaca-installed-p 'embark)
|
|
(elpaca-installed-p 'consult))
|
|
:hook (embark-collect-mode . consult-preview-at-point-mode))
|
|
|
|
;;;;; Terminal Encoding
|
|
|
|
(use-feature mule
|
|
:defer t
|
|
:config
|
|
(unless (display-graphic-p)
|
|
(set-terminal-coding-system 'utf-8)))
|
|
|
|
;;;;; Show Paren Mode
|
|
|
|
(use-feature paren
|
|
:custom
|
|
(show-paren-context-when-offscreen 'child-frame "Show context in frame at top left")
|
|
(show-paren-style 'mixed "Show parens if visible, otherwise the whole expression")
|
|
(show-paren-when-point-inside-paren t "Show paren when just inside parens")
|
|
:hook
|
|
((conf-mode markdown-mode prog-mode) . show-paren-local-mode))
|
|
|
|
;;;;; Mouse
|
|
|
|
(use-feature mouse
|
|
:custom
|
|
(mouse-1-click-follows-link 'double "I /hate/ when mouse-1 is unexpectedly remapped (org)")
|
|
(mouse-scroll-delay 0.15 "Decrease delay"))
|
|
|
|
;;;;;; Mouse Wheel
|
|
|
|
(use-feature mwheel
|
|
:custom
|
|
(mouse-wheel-follow-mouse t "Scroll window under mouse")
|
|
(mouse-wheel-progressive-speed nil "Don't increase scroll speed with wheel")
|
|
(mouse-wheel-scroll-amount '(1
|
|
((shift) . 1)
|
|
((meta) . 0.5)
|
|
((control meta) . global-text-scale)
|
|
((control) . text-scale))
|
|
"Amount to scroll with and without modifiers"))
|
|
|
|
;;;;;; Pixel Scroll Precision Mode
|
|
|
|
(use-feature pixel-scroll
|
|
:unless
|
|
(pixel-scroll-precision-mode)
|
|
:defer 1
|
|
:config
|
|
(pixel-scroll-precision-mode))
|
|
|
|
;;;;; Comments
|
|
|
|
(use-feature newcomment
|
|
:custom
|
|
(comment-style 'multi-line "Use one comment for all lines, end without extra line"))
|
|
|
|
;;;;; Shell Mode
|
|
|
|
(use-feature shell
|
|
:defer t
|
|
:hook (shell-mode . ansi-color-for-comint-mode-on))
|
|
|
|
;;;;; Basic Commands (`simple.el')
|
|
|
|
(use-feature simple
|
|
:custom
|
|
(read-extended-command-predicate
|
|
#'command-completion-default-include-p "Exclude non-current mode completions, include no-mode completions")
|
|
(indent-tabs-mode nil "Tabs for C, and C alone")
|
|
:hook
|
|
((conf-mode prog-mode) . column-number-mode)
|
|
(git-commit-mode . auto-fill-mode))
|
|
|
|
;;;;; Typing Breaks
|
|
|
|
(use-feature type-break
|
|
:custom
|
|
(type-break-keystroke-threshold '(nil . nil) "Disable keystroke limit")
|
|
:defer t)
|
|
|
|
;;;;; Whitespace
|
|
|
|
(use-feature whitespace
|
|
:custom
|
|
;; (whitespace-action 'auto-cleanup)
|
|
(whitespace-line-column nil "Use `fill-column' instead")
|
|
(whitespace-style '(lines-char
|
|
missing-newline-at-eof
|
|
space-after-tab
|
|
space-before-tab
|
|
tabs
|
|
trailing) "Clean up without visualizing whitespace")
|
|
:hook
|
|
(elpaca-after-init . whitespace-mode)
|
|
:config
|
|
;; TODO: Fix `whitespace-action' above?
|
|
(add-hook 'before-save-hook #'whitespace-cleanup))
|
|
|
|
;;;;; Undo/Redo
|
|
|
|
;;;;;; Undo Fu
|
|
|
|
(use-package undo-fu
|
|
:defer 3
|
|
:bind
|
|
(("C-z" . undo-fu-only-undo)
|
|
("C-S-z" . undo-fu-only-redo)))
|
|
|
|
;;;;;; Vundo
|
|
|
|
(use-package vundo
|
|
:custom
|
|
(vundo-glyph-alist vundo-unicode-symbols)
|
|
:defer 3)
|
|
|
|
;;;;;; Undo Fu Persistence
|
|
|
|
(use-package undo-fu-session
|
|
:if
|
|
(elpaca-installed-p 'undo-fu)
|
|
:after
|
|
(undo-fu)
|
|
:custom
|
|
(undo-fu-session-incompatible-files
|
|
'("/COMMIT_EDITMSG\\'" "/git-rebase-todo\\'") "Don't track changes to these files")
|
|
(undo-fu-session-directory
|
|
(expand-file-name "undo-fu-session" xdg_cache_home) "Relocate to XDG_CACHE_HOME")
|
|
:config
|
|
(undo-fu-session-global-mode))
|
|
|
|
;;;;; Windows
|
|
|
|
;;;;;; Window Settings
|
|
|
|
(use-feature window
|
|
:custom
|
|
(switch-to-buffer-obey-display-actions t "Respect other settings when switching buffers")
|
|
:bind
|
|
(:map global-map
|
|
;; Automatically select new window when splitting
|
|
("C-x 2" . (lambda () (interactive)(split-window-below) (other-window 1)))
|
|
("C-x 3" . (lambda () (interactive)(split-window-right) (other-window 1)))
|
|
;; Resizing buffers
|
|
("S-C-<left>" . shrink-window-horizontally)
|
|
("S-C-<right>" . enlarge-window-horizontally)
|
|
("S-C-<down>" . shrink-window)
|
|
("S-C-<up>" . enlarge-window)))
|
|
|
|
;;;;;; Ace Window
|
|
|
|
(use-package ace-window
|
|
:bind
|
|
("C-c w" . ace-window))
|
|
|
|
;;;;; Mode-line
|
|
|
|
;;;;;; Show Current/Total Matches (Anzu)
|
|
|
|
(use-package anzu
|
|
:defer 3
|
|
:config
|
|
(global-anzu-mode))
|
|
|
|
;;;; Appearance
|
|
|
|
;;;;; Startup
|
|
|
|
;;;;;; Grid
|
|
|
|
(use-package grid
|
|
:ensure (:host github :repo "ichernyshovvv/grid.el"))
|
|
|
|
;;;;;; Enlight
|
|
|
|
(use-package enlight
|
|
:if
|
|
(elpaca-installed-p 'grid)
|
|
:after
|
|
(grid)
|
|
:hook
|
|
(elpaca-after-init . enlight-open)
|
|
:config
|
|
(setopt
|
|
enlight-content
|
|
(grid-get-row
|
|
`(,(enlight-menu
|
|
'(("Files"
|
|
("Find File" find-file "f")
|
|
("Recent Files" consult-recent-file "r")
|
|
("Projects" project-switch-project "p")
|
|
("Treemacs" treemacs "t"))))
|
|
" "
|
|
,(enlight-menu
|
|
'(("Org"
|
|
("Super Agenda" (org-agenda nil "u") "u")
|
|
("Time Blocking" org-timeblock "b")
|
|
("Consult Notes" (consult-notes) "n")
|
|
("Denote" (call-interactively 'denote-open-or-create) "d"))))
|
|
" "
|
|
,(enlight-menu
|
|
`(("Settings"
|
|
("Elpaca" elpaca-manager "L")
|
|
("Emacs"
|
|
(progn
|
|
(find-file ,user-init-file))
|
|
"I")
|
|
("Denote"
|
|
(progn
|
|
(find-file ,(replace-regexp-in-string "init.el" "lisp/init-denote.el" user-init-file)))
|
|
"D")
|
|
("Org"
|
|
(progn
|
|
(find-file ,(replace-regexp-in-string "init.el" "lisp/init-org.el" user-init-file)))
|
|
"O"))))))))
|
|
|
|
;;;;; Mode line
|
|
|
|
;;;;;; Moody
|
|
|
|
(use-package moody
|
|
:custom
|
|
(x-underline-at-descent-line t "Place underline at bottom of mode line")
|
|
;; :defer 1
|
|
:hook
|
|
(elpaca-after-init . (lambda ()
|
|
(moody-replace-eldoc-minibuffer-message-function)
|
|
(moody-replace-mode-line-buffer-identification)
|
|
(moody-replace-mode-line-front-space)
|
|
(moody-replace-vc-mode))))
|
|
|
|
;;;;;; Minor Mode Menu (Minions)
|
|
|
|
(use-package minions
|
|
:after
|
|
(moody)
|
|
:config
|
|
(minions-mode))
|
|
|
|
;;;;; Colors
|
|
|
|
;;;;;; Rainbow Mode
|
|
|
|
(use-package rainbow-mode
|
|
:hook
|
|
((conf-mode prog-mode toml-ts-mode yaml-ts-mode) . rainbow-mode))
|
|
|
|
;;;;; Icons
|
|
|
|
;;;;;; Kind Icon
|
|
|
|
(use-package kind-icon
|
|
:disabled t
|
|
:after (corfu)
|
|
:custom
|
|
(kind-icon-default-face 'corfu-default "Don't default to frame colors if otherwise unspecified")
|
|
:config
|
|
(add-to-list 'corfu-margin-formatters #'kind-icon-margin-formatter))
|
|
|
|
;;;;;; Nerd Icons
|
|
|
|
(use-package nerd-icons
|
|
:defer 1)
|
|
|
|
;;;;;;; Nerd Icons + Completion
|
|
|
|
(use-package nerd-icons-completion
|
|
:if
|
|
(and (elpaca-installed-p 'nerd-icons)
|
|
(elpaca-installed-p 'marginalia))
|
|
:after
|
|
(nerd-icons marginalia)
|
|
:config
|
|
(nerd-icons-completion-mode)
|
|
:hook
|
|
(marginalia-mode . nerd-icons-completion-marginalia-setup))
|
|
|
|
;;;;;;; Nerd Icons + Corfu
|
|
|
|
(use-package nerd-icons-corfu
|
|
:if
|
|
(and (elpaca-installed-p 'nerd-icons)
|
|
(elpaca-installed-p 'corfu))
|
|
:after
|
|
(nerd-icons corfu)
|
|
:config
|
|
(add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter))
|
|
|
|
;;;;;;; Nerd Icons + Dired
|
|
|
|
(use-package nerd-icons-dired
|
|
:if
|
|
(elpaca-installed-p 'nerd-icons)
|
|
:hook
|
|
(dired-mode . nerd-icons-dired-mode))
|
|
|
|
;;;;;;; Nerd Icons + ibuffer
|
|
|
|
(use-package nerd-icons-ibuffer
|
|
:if
|
|
(elpaca-installed-p 'nerd-icons)
|
|
:hook
|
|
(ibuffer-mode . nerd-icons-ibuffer-mode))
|
|
|
|
;;;;;;; Nerd Icons + Treemacs
|
|
(use-package treemacs-nerd-icons
|
|
:if
|
|
(and (elpaca-installed-p 'nerd-icons)
|
|
(elpaca-installed-p 'treemacs))
|
|
:after
|
|
(nerd-icons treemacs)
|
|
:config
|
|
(treemacs-load-theme "nerd-icons"))
|
|
|
|
;;;;; Highlighting
|
|
|
|
;;;;;; Indent Bars
|
|
|
|
(use-package indent-bars
|
|
:custom
|
|
(indent-bars-color '(highlight :face-bg nil :blend 0.375))
|
|
(indent-bars-color-by-depth '(:regexp "orderless-match-face-\\([0-9]+\\)" :blend 1) "Default 'outline' faces are pretty boring with doom-spacegrey")
|
|
(indent-bars-highlight-current-depth '(:blend 0.75) "Default `:pattern' requires `:stipple', revisit for Emacs 30")
|
|
(indent-bars-no-descend-lists t "Only show 1 level for lists & continued lines")
|
|
(indent-bars-prefer-character t "`:stipple' unsupported with PGTK until Emacs 30")
|
|
(indent-bars-treesit-support t "Enable `treesit' support")
|
|
;; (indent-bars-treesit-wrap '((c argument_list parameter_list init_declarator)) "Seems to not have any effect?")
|
|
:hook
|
|
(prog-mode . indent-bars-mode))
|
|
|
|
;;;;;; HL Todo
|
|
|
|
;; FIXME
|
|
(defun as/hl-todo-previous-mark-done (arg)
|
|
(interactive "p")
|
|
(save-excursion
|
|
;; (goto-char (point-max))
|
|
(let ((hl-todo-wrap-movement nil))
|
|
(hl-todo-previous arg))
|
|
`(string-match ,(concat (hl-todo--regexp) "\\=") ,(thing-at-point 'line t))
|
|
(replace-match "DONE" t t)
|
|
))
|
|
|
|
(use-package hl-todo
|
|
:ensure
|
|
(hl-todo :depth nil)
|
|
:custom
|
|
(hl-todo-highlight-punctuation ":!?" "Highlight additional punctuation characters")
|
|
(hl-todo-include-modes '(conf-mode markdown-mode prog-mode))
|
|
(hl-todo-keyword-faces '(("DEBUG" warning bold)
|
|
("DONE" success italic)
|
|
("HACK" warning bold)
|
|
("FIXME" error bold)
|
|
("NOTE" homoglyph italic)
|
|
("REVIEW" homoglyph italic)
|
|
("TODO" homoglyph bold))
|
|
"Customize faces for todo keywords")
|
|
:bind
|
|
(:map hl-todo-mode-map
|
|
("C-c C-t p" . hl-todo-previous)
|
|
("C-c C-t n" . hl-todo-next)
|
|
("C-c C-t o" . hl-todo-occur)
|
|
("C-c C-t i" . hl-todo-insert))
|
|
:hook
|
|
(elpaca-after-init . global-hl-todo-mode))
|
|
|
|
;;;;;;; Consult + HL Todo
|
|
|
|
(use-package consult-todo
|
|
:if (and (elpaca-installed-p 'hl-todo)
|
|
(elpaca-installed-p 'consult))
|
|
:after (hl-todo)
|
|
:bind
|
|
(:map hl-todo-mode-map
|
|
("C-c C-t c" . consult-todo)
|
|
("C-c C-t C-c" . consult-todo-all)))
|
|
|
|
;;;;; Line Wrapping
|
|
|
|
;;;;;; Visual Fill Column
|
|
|
|
(use-package visual-fill-column
|
|
:custom
|
|
(visual-fill-column-enable-sensible-window-split t "Don't take margins into account when splitting")
|
|
:defer t)
|
|
|
|
;;;;;; Adaptive Wrap
|
|
|
|
(use-package adaptive-wrap
|
|
:defer t)
|
|
|
|
;;;;; Themes
|
|
|
|
;;;;;; Catppuccin
|
|
|
|
(use-package catppuccin-theme
|
|
;; :disabled
|
|
:if
|
|
(eq custom-safe-themes t)
|
|
:custom
|
|
(catppuccin-flavor 'macchiato "Set variant to macchiato (medium-dark)")
|
|
:defer t
|
|
:config
|
|
(catppuccin-reload)
|
|
;; (load-theme 'catppuccin t)
|
|
)
|
|
|
|
;;;;;; Doom
|
|
|
|
(use-package doom-themes
|
|
:if
|
|
(eq custom-safe-themes t)
|
|
:custom
|
|
(doom-spacegrey-brighter-comments t "More visible comment colors")
|
|
(doom-spacegrey-brighter-modeline t "More visible mode line colors")
|
|
(doom-spacegrey-comment-bg nil "Don't lighten comment background")
|
|
(doom-themes-enable-bold t "Enable bold text faces")
|
|
(doom-themes-enable-italic t "Enable italic text faces")
|
|
(doom-themes-org-fontify-special-tags nil "Disable # and @")
|
|
:config
|
|
(doom-themes-org-config)
|
|
;; (doom-themes-treemacs-config) ; requires `all-the-icons'
|
|
(load-theme 'doom-spacegrey t))
|
|
|
|
(use-package miasma-theme
|
|
:ensure
|
|
(:host github :repo "/daut/miasma-theme.el")
|
|
:config
|
|
;; (load-theme 'miasma t)
|
|
)
|
|
|
|
;;;;;; Nimbus
|
|
|
|
(use-package nimbus-theme
|
|
:if
|
|
(eq custom-safe-themes t)
|
|
:defer t)
|
|
|
|
;;;;;; Zerodark
|
|
|
|
(use-package zerodark-theme
|
|
;; Requires `all-the-icons'
|
|
:disabled t
|
|
:defer t)
|
|
|
|
;;;; Files
|
|
|
|
;;;;; File Management
|
|
|
|
;;;;;; Dired
|
|
|
|
(use-feature dired
|
|
:custom
|
|
(dired-kill-when-opening-new-dired-buffer t "Kill current buffer when opening a new directory")
|
|
(dired-mouse-drag-files t "Allow drag-and-drop")
|
|
:commands (dired))
|
|
|
|
;;;;;; Treemacs
|
|
|
|
(use-package treemacs
|
|
:commands (treemacs)
|
|
:custom
|
|
(treemacs-eldoc-display 'simple "Only show absolute path")
|
|
(treemacs-is-never-other-window t "Disallow `other-window' and related functions")
|
|
(treemacs-persist-file
|
|
(expand-file-name "treemacs-persist" xdg_cache_home) "Relocate to XDG_CACHE_HOME")
|
|
;; (treemacs-text-scale 1 "Scale sidebar text")
|
|
(treemacs-width-is-initially-locked t "Enforce using commands to resize")
|
|
:config
|
|
(add-to-list 'treemacs-litter-directories "/zig-cache")
|
|
(add-to-list 'treemacs-litter-directories "/.zig-cache")
|
|
;; (treemacs-resize-icons 18)
|
|
(treemacs-follow-mode)
|
|
(treemacs-filewatch-mode)
|
|
(treemacs-fringe-indicator-mode 'always)
|
|
(treemacs-git-commit-diff-mode)
|
|
(treemacs-git-mode 'deferred)
|
|
;; (treemacs-hide-gitignored-files-mode nil)
|
|
(treemacs-indent-guide-mode)
|
|
:init
|
|
(bind-keys :prefix-map as/treemacs-prefix-map
|
|
:prefix "C-c t"
|
|
("0" . treemacs-select-window)
|
|
("1" . treemacs-delete-other-windows)
|
|
("t" . treemacs)
|
|
("d" . treemacs-select-directory)
|
|
("B" . treemacs-bookmark)
|
|
("C-f" . treemacs-find-file)
|
|
("M-t" . treemacs-find-tag)))
|
|
|
|
(use-package treemacs-magit
|
|
:if
|
|
(and (elpaca-installed-p 'magit)
|
|
(elpaca-installed-p 'treemacs))
|
|
:after
|
|
(treemacs magit))
|
|
|
|
;;;;; Auto-save & Backups
|
|
|
|
(use-feature files
|
|
:custom
|
|
(backup-by-copying t "Copy to back up, don't rename the current file")
|
|
(confirm-kill-processes nil "Don't ask about processes, just exit")
|
|
(delete-old-versions t "Delete excess backups")
|
|
(kept-new-versions 5 "Increase number of new backups to keep")
|
|
(kept-old-versions 3 "Increase number of old backups to keep")
|
|
(require-final-newline t "Add newline to end of file")
|
|
(version-control t "Use version numbers for backup files")
|
|
:init
|
|
(let ((auto_save_directory (concat xdg_cache_home "auto-save-list/")))
|
|
(unless (file-directory-p auto_save_directory)
|
|
(make-directory auto_save_directory))
|
|
(setopt backup-directory-alist `((".*" . ,auto_save_directory))
|
|
auto-save-list-file-prefix (concat auto_save_directory "saves-")
|
|
auto-save-file-name-transforms `((".*" ,auto_save_directory t)))))
|
|
|
|
;;;;;; Recent Files
|
|
|
|
(use-feature recentf
|
|
:custom
|
|
(recentf-auto-cleanup 600 "Clean up the list every 10 minutes, not when I load a related mode")
|
|
(recentf-max-menu-items 100 "Increase maximum number of items in the menu")
|
|
(recentf-max-saved-items 100 "Maximum number of items to save to the recentf file")
|
|
(recentf-save-file
|
|
(expand-file-name "recentf" xdg_cache_home) "Relocate to XDG_CACHE_HOME")
|
|
:hook
|
|
(elpaca-after-init . recentf-mode))
|
|
|
|
;;;;;; Save Place Mode
|
|
|
|
(use-feature saveplace
|
|
:custom
|
|
(save-place-file
|
|
(expand-file-name "places" xdg_cache_home) "Relocate to XDG_CACHE_HOME")
|
|
:hook
|
|
(elpaca-after-init . save-place-mode))
|
|
|
|
;;;; Citations
|
|
|
|
;;;;; BibTex
|
|
|
|
(use-feature bibtex
|
|
:after
|
|
(ebib)
|
|
:custom
|
|
(bibtex-autokey-additional-names "EtAl" "Append if not all names can be used")
|
|
(bibtex-autokey-edit-before-use t "Allow key editing")
|
|
(bibtex-autokey-expand-strings t "Expand strings when extracting from BibTex")
|
|
(bibtex-autokey-name-case-convert-function #'capitalize "Captialize names in reference keys")
|
|
(bibtex-autokey-name-year-separator "" "Don't separate name and year in reference keys")
|
|
(bibtex-autokey-names 2 "Use 2 names for reference keys")
|
|
(bibtex-autokey-names-stretch 1 "Allow an extra name in reference keys if it would mean using all names")
|
|
(bibtex-autokey-titlewords 3 "Use 3 words from title for reference keys")
|
|
(bibtex-autokey-titlewords-stretch 1 "Allow an extra title word in reference keys if it would end a sentence")
|
|
(bibtex-autokey-titleword-length #'infty "Disable title word character limit in reference keys")
|
|
(bibtex-autokey-titleword-separator "" "Don't separate title words")
|
|
(bibtex-autokey-titleword-case-convert-function #'capitalize "Capitalize title words in reference keys")
|
|
(bibtex-autokey-year-length 4 "Use full year in reference keys")
|
|
(bibtex-autokey-year-title-separator "" "Don't separate year and title in reference keys"))
|
|
|
|
;;;;; Biblio
|
|
|
|
(use-package biblio
|
|
:if
|
|
(elpaca-installed-p 'ebib)
|
|
:after
|
|
(ebib)
|
|
:custom
|
|
(biblio-bibtex-use-autokey t "Automatically generate new BibTex keys"))
|
|
|
|
;;;;; Biblio OpenLibrary (ISBN lookup)
|
|
(use-package biblio-openlibrary
|
|
:ensure
|
|
(biblio-openlibrary :host github :repo "fabcontigiani/biblio-openlibrary")
|
|
:if
|
|
(elpaca-installed-p 'biblio)
|
|
:after
|
|
(biblio))
|
|
|
|
;;;;; Ebib
|
|
|
|
(use-package ebib
|
|
:commands (ebib)
|
|
:custom
|
|
(ebib-autogenerate-keys t "Enabled by default, and I want to keep it that way")
|
|
(ebib-bibtex-dialect 'biblatex "Use biblatex, not BibTex")
|
|
(ebib-use-timestamp t "Create a timestamp when adding an entry")
|
|
(ebib-filters-default-file
|
|
(expand-file-name "ebib-filters" user-emacs-directory) "Relocate filters file")
|
|
(ebib-allow-identical-fields t "Merge repeated fields")
|
|
(ebib-file-associations '(("pdf" . nil) ("ps" . "gs"))
|
|
"Specify default programs for file types")
|
|
(ebib-import-target-directory
|
|
(expand-file-name "~/Nextcloud/Library/") "Directory for `ebib-download-url' and `ebib-import-file'")
|
|
(ebib-default-directory
|
|
(expand-file-name "~/Nextcloud/Library/") "Default directory when, ex., prompting user")
|
|
(ebib-preload-bib-files
|
|
`(,(expand-file-name "~/Nextcloud/Library/Bibliography/Library.bib")) "Bib files to autoload")
|
|
;; (ebib-bib-search dirs nil "Directory to seach for multiple .bib files")
|
|
;;; Editing
|
|
;; (ebib-save-xrefs-first nil "Save entries with cross-references first - required for cross-referencing unless sort order is changed")
|
|
;; (ebib-sort-order nil "Change sort order of .bib files - be sure to unset `ebib-save-xrefs-first'")
|
|
(ebib-filters-ignore-case t "True by default, and I want to keep it that way")
|
|
;;; Downloading/Filenames
|
|
;;; Notes
|
|
;; ebib-notes-storage 'multiple-notes-per-file ; probabably set to `multiple-notes-per-file' for org?
|
|
;; (ebib-notes-locations nil "Set locations for notes")
|
|
;; (ebib-notes-default-file nil "Doesn't matter for `org-capture' but can still be set")
|
|
;;; Org-capture
|
|
;; (ebib-notes-use-org-capture nil "Skip `org-capture' and use this template")
|
|
;; (ebib-org-capture nil "Function to call `org-capture' from `ebib'")
|
|
;;; Reading list
|
|
;; (ebib-reading-list-file nil "Set reading list location")
|
|
;; (ebib-reading-list-todo-marker "TODO" "Default todo state for reading list")
|
|
;; (ebib-reading-list-template "" "Format for reading list todo items")
|
|
;; (ebib-reading-list-add-item-function "" "Change where new reading list items are added")
|
|
;; (ebib-reading-list-remove-item "" "Function run when removing an item from the list - default is to mark DONE")
|
|
;;; Keywords
|
|
;; (ebib-keywords nil "Keywords always available for completion")
|
|
;;; org-ebib
|
|
;; (org-ebib-link-type 'key "Type of link produced by `org-store-link' on entries")
|
|
)
|
|
|
|
(use-package ebib-biblio
|
|
:ensure nil ; It's included with `ebib' so I don't want to try and build it
|
|
:if
|
|
(and (elpaca-installed-p 'biblio)
|
|
(elpaca-installed-p 'ebib))
|
|
:after
|
|
(ebib biblio)
|
|
:bind
|
|
(:map ebib-index-mode-map
|
|
("B" . ebib-biblio-import-doi))
|
|
(:map biblio-selection-mode-map
|
|
("e" . ebib-biblio-selection-import)))
|
|
|
|
;;;; Completion
|
|
|
|
;;;;; Cape (`completion-at-point' extensions)
|
|
|
|
(use-package cape
|
|
:bind-keymap
|
|
("M-p" . cape-prefix-map)
|
|
:config
|
|
(advice-add 'eglot-completion-at-point :around #'cape-wrap-buster)
|
|
(advice-add 'eglot-completion-at-point :around #'cape-wrap-noninterruptible)
|
|
:defer 3
|
|
;; :hook
|
|
;; (completion-at-point-functions . cape-dabbrev)
|
|
;; (completion-at-point-functions . cape-file)
|
|
;; (completion-at-point-functions . cape-elisp-block)
|
|
)
|
|
|
|
;;;;; Mini-buffer Completion
|
|
|
|
;;;;;; Annnotations (Marginalia)
|
|
|
|
(use-package marginalia
|
|
:defer 1
|
|
:config
|
|
(marginalia-mode))
|
|
|
|
;;;;;; UI (Vertico)
|
|
|
|
(use-package vertico
|
|
:custom
|
|
(vertico-cycle t "Cycle with `vertico-next' and `vertico-previous'")
|
|
(vertico-count 15 "Maximum number of candidates to display")
|
|
;; (vertico-multiform-categories
|
|
;; '((file (vertico-sort-function . vertico-sort-alpha)))
|
|
;; "Sort files alphabetically")
|
|
(vertico-resize t "Allow both shrinking and growing")
|
|
(vertico-scroll-margin 1 "Reduce lines at top and bottom when scrolling")
|
|
:config
|
|
(vertico-mode)
|
|
;; (setopt vertico-multiform-categories '((file (vertico-sort-function . vertico-sort-alpha))))
|
|
;; (vertico-multiform-mode)
|
|
)
|
|
|
|
;;;;;; Completions (Consult)
|
|
|
|
(use-package consult
|
|
:custom
|
|
(consult-narrow-key "<" "Prefix for completion narrowing")
|
|
;; Register formatting
|
|
(register-preview-delay 0.6 "Decrease wait time for register preview")
|
|
(register-preview-function
|
|
#'consult-register-format "Use `consult' for register previews")
|
|
;; Select xref locations with preview
|
|
(xref-show-xrefs-function
|
|
#'consult-xref "Use `consult' for external reference search results")
|
|
(xref-show-definitions-function
|
|
#'consult-xref "Use `consult' to display external reference search results")
|
|
:bind (;; C-c bindings in `mode-specific-map'
|
|
("C-c M-x" . consult-mode-command)
|
|
("C-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) ; 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
|
|
("C-x r b" . consult-bookmark) ; orig. bookmark-jump
|
|
("C-x p b" . consult-project-buffer) ; orig. project-switch-to-buffer
|
|
("C-x M-r" . consult-recent-file)
|
|
;; 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
|
|
;; M-g bindings in `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-imenu-multi)
|
|
;; M-s bindings in `search-map'
|
|
("M-s d" . consult-find)
|
|
("M-s D" . 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) ; orig. isearch-edit-string
|
|
("M-s e" . consult-isearch-history) ; orig. isearch-edit-string
|
|
("M-s l" . consult-line) ; needed by consult-line to detect isearch
|
|
("M-s L" . consult-line-multi) ; needed by consult-line to detect isearch
|
|
;; Minibuffer history
|
|
:map minibuffer-local-map
|
|
("M-s" . consult-history) ; orig. next-matching-history-element
|
|
("M-r" . consult-history) ; orig. previous-matching-history-element
|
|
)
|
|
:config
|
|
;; Register preview window
|
|
(advice-add #'register-preview :override #'consult-register-window))
|
|
|
|
;;;;;; Consult Dir (directory switching in mini-buffer)
|
|
|
|
(use-package consult-dir
|
|
:if
|
|
(and (elpaca-installed-p 'consult)
|
|
(elpaca-installed-p 'vertico))
|
|
:after
|
|
(consult vertico)
|
|
:bind
|
|
(("C-x C-d" . consult-dir)
|
|
:map vertico-map
|
|
("C-x C-d" . consult-dir)
|
|
("C-x C-j" . consult-dir-jump-file)))
|
|
|
|
;;;;; Completion in Region
|
|
|
|
;;;;;; Corfu
|
|
|
|
(use-package corfu
|
|
:ensure
|
|
(corfu :files (:defaults "extensions/*"))
|
|
:defer 3
|
|
:custom
|
|
;; (corfu-auto t "Enable auto-completion")
|
|
(corfu-cycle t "Enable cycling with `corfu-next' and `corfu-previous'")
|
|
:config
|
|
(when (>= emacs-major-version 30)
|
|
(setopt text-mode-ispell-word-completion nil))
|
|
(global-corfu-mode)
|
|
(corfu-popupinfo-mode))
|
|
|
|
;;;;;; Completion Styles
|
|
|
|
;;;;;;; Orderless
|
|
|
|
(use-package orderless
|
|
:custom
|
|
(completion-styles '(basic substring orderless) "Add `orderless', remove `emacs22' & `partial-completion'")
|
|
(completion-category-overrides '((file (styles basic substring partial-completion))
|
|
(eglot (styles basic substring orderless))
|
|
(eglot-capf (styles basic substring orderless)))
|
|
"Override file for `tramp' and add orderless to `eglot'")
|
|
(orderless-matching-styles '(orderless-literal
|
|
orderless-regexp
|
|
;; orderless-flex
|
|
orderless-prefixes
|
|
orderless-initialism
|
|
)
|
|
"Add prefixes and initialism")
|
|
:defer 1)
|
|
|
|
;;;; Abbreviations
|
|
|
|
;;;;; Template Expansion
|
|
|
|
;;;;;; Yasnippet
|
|
|
|
(use-package yasnippet
|
|
:bind
|
|
(:map yas-minor-mode-map
|
|
("<tab>" . nil)
|
|
("TAB" . nil)
|
|
("C-c y i" . yas-insert-snippet)
|
|
("C-c y v" . yas-visit-snippet-file))
|
|
:config
|
|
(yas-reload-all) ; needed if not using `yas-global-mode'
|
|
:hook
|
|
((org-mode prog-mode) . yas-minor-mode-on))
|
|
|
|
;;;;;; Yasnippet Snippets
|
|
|
|
(use-package yasnippet-snippets
|
|
:if
|
|
(elpaca-installed-p 'yasnippet)
|
|
:after
|
|
(yasnippet))
|
|
|
|
;;;;;; Yasnippet + Consult
|
|
|
|
(use-package consult-yasnippet
|
|
:if
|
|
(and (elpaca-installed-p 'consult)
|
|
(elpaca-installed-p 'yasnippet))
|
|
:after (consult yasnippet)
|
|
:bind
|
|
(:map yas-minor-mode-map
|
|
("C-c y c" . consult-yasnippet)))
|
|
|
|
;;;; Programming
|
|
|
|
;;;;; Compiling
|
|
|
|
(use-feature compile
|
|
:custom
|
|
(compilation-ask-about-save nil "Just save, don't ask")
|
|
(compilation-scroll-output 'first-error "Stop scrolling at first error")
|
|
:defer t
|
|
:hook
|
|
(compilation-filter . ansi-color-compilation-buffer))
|
|
|
|
;;;;;; Documentation
|
|
|
|
;;;;;; Creating Documentation
|
|
|
|
;;;;;;; Doxygen
|
|
|
|
(use-package gendoxy
|
|
:after
|
|
(c-ts-mode)
|
|
:ensure (:host gitlab :repo "mp81ss_repo/gendoxy")
|
|
:bind
|
|
(:map c-ts-mode-map
|
|
("C-c c d" . gendoxy-tag)
|
|
("C-c c D" . gendoxy-tag-header))
|
|
(:map c++-ts-mode-map
|
|
("C-c c d" . gendoxy-tag)
|
|
("C-c c D" . gendoxy-tag-header)))
|
|
|
|
;;;;;; Reading Documentation
|
|
|
|
;;;;;;; DevDocs
|
|
|
|
(use-package devdocs
|
|
:bind
|
|
("C-h D" . devdocs-lookup))
|
|
|
|
;;;;;;; Eldoc Box
|
|
(use-package eldoc-box
|
|
:custom
|
|
(setopt eldoc-box-max-pixel-height 200)
|
|
(setopt eldoc-box-max-pixel-width 355)
|
|
:custom-face
|
|
(eldoc-box-body ((t (:font "Liberation Sans" :height 120))))
|
|
:bind
|
|
("C-c h" . eldoc-box-help-at-point)
|
|
:hook
|
|
(eglot-managed-mode . eldoc-box-hover-mode))
|
|
|
|
;;;;; Debugging
|
|
|
|
;;;;;; Realgud
|
|
|
|
(use-package realgud
|
|
:defer t)
|
|
|
|
(use-package realgud-lldb
|
|
:defer t)
|
|
|
|
;;;;; Formatting
|
|
|
|
;;;;;; Apheleia
|
|
|
|
(use-package apheleia
|
|
:defer t)
|
|
|
|
;;;;;; Clang Format
|
|
|
|
(use-package clang-format
|
|
:after
|
|
(c-ts-mode)
|
|
:custom
|
|
(clang-format-style "file" "Default to using .clang-format file")
|
|
:bind
|
|
(:map c-ts-mode-map
|
|
("C-c c f" . clang-format-buffer)
|
|
("C-c c F" . clang-format-region))
|
|
(:map c++-ts-mode-map
|
|
("C-c c f" . clang-format-buffer)
|
|
("C-c c F" . clang-format-region)))
|
|
|
|
;;;;;; Reformatter
|
|
|
|
;; Required for "zig fmt" functions
|
|
(use-package reformatter
|
|
:if
|
|
(elpaca-installed-p 'zig-mode)
|
|
:after
|
|
(zig-mode))
|
|
|
|
;;;;; Languages
|
|
|
|
;;;;;; C
|
|
|
|
(defun as/c-ts-mode-setup ()
|
|
"Set indentation style and offset for `c-ts-mode' or `c++-ts-mode'."
|
|
(if (eq major-mode #'c-ts-mode)
|
|
(progn (setq-local c-ts-mode-indent-offset 8
|
|
c-ts-mode-indent-style 'linux
|
|
indent-tabs-mode t)
|
|
(when (elpaca-installed-p 'clang-format)
|
|
(setq-local clang-format-fallback-style "webkit")))
|
|
(progn (setq-local c-ts-mode-indent-offset 4
|
|
c-ts-mode-indent-style 'k&r)
|
|
(when (elpaca-installed-p 'clang-format)
|
|
(setq-local clang-format-fallback-style "llvm"))))
|
|
(when (elpaca-installed-p 'indent-bars)
|
|
(when (eq indent-bars-mode t)
|
|
(indent-bars-reset))))
|
|
|
|
(use-feature c-ts-mode
|
|
:hook
|
|
(c-ts-mode . as/c-ts-mode-setup)
|
|
:defer t)
|
|
|
|
;;;;;; C++
|
|
|
|
(use-feature c++-ts-mode
|
|
:hook
|
|
(c++-ts-mode . as/c-ts-mode-setup)
|
|
:init
|
|
(add-to-list 'major-mode-remap-alist '(c++-mode . c++-ts-mode))
|
|
:defer t)
|
|
|
|
(use-package modern-cpp-font-lock
|
|
;; REVIEW: Not sure if I need this with `treesit.el'
|
|
:disabled t
|
|
:hook (c++-ts-mode . modern-c++-font-lock-mode))
|
|
|
|
;;;;;; Python
|
|
|
|
(use-feature python
|
|
:init
|
|
(add-to-list 'major-mode-remap-alist '(python-mode . python-ts-mode))
|
|
:defer t)
|
|
|
|
(use-package pyenv-mode
|
|
:hook
|
|
(python-ts-mode . pyenv-mode))
|
|
|
|
;;;;;; Rust
|
|
|
|
(use-package rust-mode
|
|
:custom
|
|
(rust-mode-treesitter-derive t "Derive `rust-mode' from `rust-ts-mode'")
|
|
:defer t)
|
|
|
|
(use-package cargo-mode
|
|
:bind
|
|
(:map cargo-minor-mode-map
|
|
("C-c a" . nil))
|
|
:bind-keymap
|
|
("C-c g" . cargo-mode-command-map)
|
|
:config
|
|
;; Mode uses `comint' by default
|
|
(setq-local compilation-scroll-output t)
|
|
:hook
|
|
(rust-ts-mode . cargo-minor-mode))
|
|
|
|
;;;;;; Web (i.e. JavaScript, PHP)
|
|
|
|
;; REVIEW: Testing astro-ts-mode
|
|
;; (define-derived-mode astro-mode web-mode "astro")
|
|
(use-package web-mode
|
|
:custom
|
|
;; (web-mode-attr-value-indent-offset 2 "HTML attribute indentation")
|
|
(web-mode-code-indent-offset 2 "Decrease indentation in web languages")
|
|
(web-mode-css-indent-offset 2 "Decrease indentation for CSS")
|
|
(web-mode-markup-indent-offset 2 "Decrease indentation for markup")
|
|
(web-mode-enable-front-matter-block t "Mode should recognize front matter")
|
|
(web-mode-engines-alist '(("blade" . "\\.blade\\.")
|
|
("razor" . "\\.cshtml\\'"))
|
|
"Add .NET to the mode")
|
|
:mode
|
|
;; ("\\.astro\\'" . astro-mode)
|
|
("\\.\\(cshtml\\|html?\\|razor\\)\\'" . web-mode))
|
|
|
|
(use-package astro-ts-mode
|
|
:defer t)
|
|
|
|
;;;;;; Zig
|
|
|
|
(use-package zig-mode
|
|
:custom
|
|
(zig-format-on-save nil "Don't automatically format")
|
|
:hook
|
|
(zig-mode . zig-ts-mode)
|
|
:defer t
|
|
:config
|
|
(defun zig-compile ()
|
|
"Save buffer and compile using `zig build`.
|
|
|
|
Overrides `zig-compile' in `zig-mode.el'."
|
|
(interactive)
|
|
(save-buffer)
|
|
(zig--run-cmd "build")))
|
|
|
|
(use-package zig-ts-mode
|
|
:ensure
|
|
(:host codeberg :repo "meow_king/zig-ts-mode")
|
|
:mode
|
|
("\\.\\(zig\\|zon\\)\\'")
|
|
:config
|
|
(setopt fill-column 100))
|
|
|
|
;;;;; Language Server Protocol (LSP)
|
|
|
|
;;;;;; Eglot
|
|
|
|
(use-feature eglot
|
|
:custom
|
|
(eglot-autoshutdown t "Stop LSP server when all buffers are closed")
|
|
(eglot-ignored-server-capabilities
|
|
'(:colorProvider ; "Decorate color references"
|
|
;; :documentFormattingProvider ; "Format buffer"
|
|
;; :documentHighlightProvider ; "Highlight symbols automatically"
|
|
:documentOnTypeFormattingProvider ; "On-type formatting"
|
|
;; :documentRangeFormattingProvider ; "Format portion of buffer"
|
|
:hoverProvider ; "Documentation on hover"
|
|
;; :inlayHintProvider ; "Inlay hints"
|
|
)
|
|
"Ignore uncommented LSP options")
|
|
:bind
|
|
(:map eglot-mode-map
|
|
("C-c e a" . eglot-code-actions)
|
|
("C-c e i" . eglot-inlay-hints-mode)
|
|
("C-c e i" . eglot-inlay-hints-mode)
|
|
("C-c e o" . eglot-code-actions-organize-imports)
|
|
("C-c e r" . eglot-rename)
|
|
("C-c e f" . eglot-format))
|
|
:hook
|
|
((astro-ts-mode
|
|
bash-ts-mode
|
|
c-ts-mode
|
|
c++-ts-mode
|
|
python-ts-mode
|
|
rust-ts-mode
|
|
sh-script
|
|
zig-ts-mode) . eglot-ensure)
|
|
(eglot-managed-mode . (lambda ()
|
|
;; Turn hints off right away rather than disable
|
|
(eglot-inlay-hints-mode -1)
|
|
;; Show flymake diagnostics before documentation
|
|
;; See: <https://github.com/joaotavora/eglot/discussions/898#discussioncomment-2609402>
|
|
(setq-local eldoc-documentation-functions
|
|
(cons #'flymake-eldoc-function
|
|
(remove #'flymake-eldoc-function eldoc-documentation-functions)))
|
|
(setq-local eldoc-documentation-strategy #'eldoc-documentation-compose)))
|
|
:config
|
|
(add-to-list 'eglot-server-programs '(astro-ts-mode . ("astro-ls" "--stdio"
|
|
:initializationOptions
|
|
(:typescript (:tsdk "/usr/lib/node_modules/typescript/lib")))))
|
|
(add-to-list 'eglot-server-programs '((rust-ts-mode rust-mode) . ("rustup" "run" "stable" "rust-analyzer"
|
|
:initializationOptions
|
|
(:check (:command "clippy")))))
|
|
(add-to-list 'eglot-server-programs '(zig-ts-mode . ("zls"))))
|
|
|
|
;;;;;; Eglot Booster
|
|
|
|
(use-package eglot-booster
|
|
:ensure
|
|
(eglot-booster :host github :repo "jdtsmith/eglot-booster")
|
|
:if
|
|
(executable-find "emacs-lsp-booster")
|
|
:after
|
|
(eglot)
|
|
:config
|
|
(eglot-booster-mode))
|
|
|
|
;;;;;; Consult + Eglot (LSP workspace/symbols UI)
|
|
|
|
(use-package consult-eglot
|
|
:if
|
|
(elpaca-installed-p 'consult)
|
|
:after
|
|
(eglot)
|
|
:bind
|
|
(:map eglot-mode-map
|
|
("C-c e s" . consult-eglot-symbols)))
|
|
|
|
;;;;; Markup & Data Serialization
|
|
|
|
;;;;;; Markdown
|
|
|
|
(use-package markdown-mode
|
|
:custom
|
|
(markdown-hide-markup t "Hide markers for italic/bold etm.")
|
|
(markdown-hide-urls t "Hide reference links")
|
|
:bind
|
|
(:map markdown-mode-map
|
|
("C-M-i" . fill-paragraph))
|
|
:hook
|
|
(markdown-mode . visual-line-fill-column-mode)
|
|
:commands
|
|
(markdown-mode))
|
|
|
|
;;;;;; YAML
|
|
|
|
(use-package yaml-pro
|
|
:hook (yaml-ts-mode . yaml-pro-ts-mode))
|
|
|
|
;;;;; Syntax Checking
|
|
|
|
;;;;;; Flymake
|
|
|
|
(use-feature flymake
|
|
:custom
|
|
(flymake-fringe-indicator-position 'right-fringe "Move to right side")
|
|
:bind
|
|
(:map flymake-mode-map
|
|
("C-c f c" . consult-flymake)
|
|
("C-c f d" . flymake-show-buffer-diagnostics)
|
|
("C-c f D" . flymake-show-project-diagnostics)
|
|
("C-c f n" . flymake-goto-next-error)
|
|
("C-c f p" . flymake-goto-prev-error)
|
|
("C-M-;" . flymake-goto-next-error)
|
|
("C-M-'" . flymake-goto-prev-error))
|
|
:hook
|
|
(prog-mode . flymake-mode))
|
|
|
|
;;;;; Tree-sitter
|
|
|
|
;;;;;; Treesit
|
|
|
|
(use-feature treesit
|
|
:custom
|
|
(treesit-font-lock-level 4 "Increase decoration level")
|
|
:defer t)
|
|
|
|
;;;;;; Treesit Auto
|
|
|
|
(use-package treesit-auto
|
|
;; :after (treesit)
|
|
:custom
|
|
(treesit-auto-install t "Install missing grammars without prompting")
|
|
:hook
|
|
(elpaca-after-init . global-treesit-auto-mode)
|
|
:config
|
|
(setq c_tsauto_config
|
|
(make-treesit-auto-recipe
|
|
:lang 'c
|
|
:ts-mode 'c-ts-mode
|
|
:remap 'c-mode
|
|
:url "https://github.com/tree-sitter/tree-sitter-c"
|
|
:revision "v0.20.7"
|
|
:ext "\\.c\\'"))
|
|
(setq cpp_tsauto_config
|
|
(make-treesit-auto-recipe
|
|
:lang 'cpp
|
|
:ts-mode 'c++-ts-mode
|
|
:remap 'c++-mode
|
|
:url "https://github.com/tree-sitter/tree-sitter-cpp"
|
|
:revision "v0.21.0"
|
|
:ext "\\.cpp\\'"))
|
|
;; FIXME: This doesn't work, still need to use `treesit-install-language-grammar'
|
|
(setq zig_tsauto_config
|
|
(make-treesit-auto-recipe
|
|
:lang 'zig
|
|
:ts-mode 'zig-ts-mode
|
|
;; :remap 'zig-mode
|
|
:url "https://github.com/maxxnino/tree-sitter-zig"
|
|
:revision "v1.0.2"
|
|
:ext "\\.\\(zig\\|zon\\)\\'"
|
|
:source-dir "src"))
|
|
(add-to-list 'treesit-auto-recipe-list c_tsauto_config)
|
|
(add-to-list 'treesit-auto-recipe-list cpp_tsauto_config)
|
|
(add-to-list 'treesit-auto-recipe-list zig_tsauto_config)
|
|
(add-to-list 'treesit-auto-langs 'zig)
|
|
(treesit-auto-add-to-auto-mode-alist 'all))
|
|
|
|
;;;; Document Viewing
|
|
|
|
;;;;; DJVU
|
|
|
|
;; Mostly to stop `org-noter' from complaining
|
|
(use-package djvu
|
|
:defer t)
|
|
|
|
;;;;; EPUB
|
|
|
|
(use-package nov
|
|
:custom
|
|
(nov-text-width t "Set low, it goes over anyway")
|
|
:mode
|
|
("\\.epub\\'" . nov-mode)
|
|
:hook
|
|
(nov-mode . visual-line-mode)
|
|
(nov-mode . visual-fill-column-mode)
|
|
(nov-mode . (lambda ()
|
|
(face-remap-add-relative 'variable-pitch :family "Liberation Serif" :height 1.1)
|
|
(setq-local visual-fill-column-center-text t))))
|
|
|
|
;;;;; PDF
|
|
|
|
(use-package pdf-tools
|
|
:ensure
|
|
(pdf-tools :pre-build ("./server/autobuild") :files (:defaults ("lisp/*" "server/epdfinfo")))
|
|
:custom
|
|
(pdf-info-epdfinfo-program
|
|
(expand-file-name "pdf-tools/server/epdfinfo" elpaca-builds-directory)
|
|
"Builds in `elpaca' directory, see `:ensure'")
|
|
(pdf-view-resiz-efactor 1.1 "Increase view size")
|
|
(pdf-view-display-size 'fit-page "Fit page, not screen width")
|
|
:mode
|
|
("\\.pdf\\'" . pdf-view-mode)
|
|
:hook
|
|
(pdf-view-mode . pdf-annot-minor-mode)
|
|
(pdf-view-mode . pdf-view-midnight-minor-mode))
|
|
|
|
;;;;; Outline Mode
|
|
|
|
(use-feature outline
|
|
:bind
|
|
("C-c M-o" . outline-minor-mode)
|
|
:custom
|
|
(outline-minor-mode-cycle t "Enable TAB (show/hide) & S-TAB (show/hide all)"))
|
|
|
|
;;;; RSS
|
|
|
|
(use-package elfeed
|
|
:custom
|
|
(elfeed-db-directory
|
|
(expand-file-name "elfeed" user-emacs-directory) "Relocate database")
|
|
(elfeed-feeds
|
|
'(("https://sachachua.com/blog/category/emacs-news/feed/" emacs)
|
|
("https://www.mozilla.org/en-US/careers/feed/" jobs)
|
|
("https://remotive.com/remote-jobs/feed/software-dev/" jobs)
|
|
("https://archlinux.org/feeds/news/" linux)
|
|
("https://artixlinux.org/feed.php" linux)
|
|
("https://www.debian.org/News/news" linux)
|
|
("https://news.opensuse.org/feed/" linux)
|
|
("https://rockylinux.org/rss.xml" linux)
|
|
("https://ziglang.org/devlog/index.xml" programming)
|
|
("https://ziglang.org/news/index.xml" programming)
|
|
("https://blog.rust-lang.org/" programming)) "The feeds")
|
|
(elfeed-sort-order 'ascending "Oldest at top")
|
|
:commands
|
|
(elfeed)
|
|
:config
|
|
(add-hook 'elfeed-new-entry-hook
|
|
(elfeed-make-tagger :feed-url "remotive\\.com"
|
|
;; REVIEW
|
|
:entry-title "\\.\\(Senior.*\\|Staff.*\\|Principal.*\\)\\'"
|
|
;; :entry-title "Senior.*"
|
|
:add 'junk
|
|
:remove 'unread)))
|
|
|
|
;;;; Projects
|
|
|
|
(use-feature project
|
|
:custom
|
|
(project-vc-extra-root-markers '("Cargo.toml") "Add Rust manifest file")
|
|
:commands (project-find-dir project-find-file project-switch-project))
|
|
|
|
;;;; Version Control
|
|
|
|
;;;;; Magit
|
|
|
|
(use-package magit
|
|
:custom
|
|
(magit-display-buffer-function
|
|
#'magit-display-buffer-fullframe-status-v1
|
|
"I don't know what this actually does, I've had it set for years... let's see!")
|
|
;; #'magit-display-buffer-same-window-except-diff-v1)
|
|
(transient-history-file
|
|
(expand-file-name "transient-history" xdg_cache_home) "Relocate to XDG_CACHE_HOME")
|
|
:defer t)
|
|
|
|
;;;;;; Transient
|
|
|
|
;; Magit requires higher version than built-in
|
|
(use-package transient
|
|
:defer t)
|
|
|
|
;;;;; Magit + Highlight Todos
|
|
|
|
(use-package magit-todos
|
|
:if
|
|
(and (elpaca-installed-p 'magit)
|
|
(elpaca-installed-p 'hl-todo))
|
|
:hook
|
|
(magit-mode . magit-todos-mode))
|
|
|
|
(use-feature vc-hooks
|
|
:custom
|
|
(vc-follow-symlinks t "Always follow symlinks")
|
|
:defer t)
|
|
|
|
(add-to-list 'load-path "~/.config/emacs/lisp/")
|
|
(require 'init-org)
|
|
(require 'init-denote)
|
|
|
|
(provide 'init)
|
|
;;; init.el ends here
|