Last active
December 13, 2023 07:59
-
-
Save antler5/efa81fbb3ecc2c4fdd97785731f4348c to your computer and use it in GitHub Desktop.
My Emacs Config as of /right now/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;; early-init.el -*- lexical-binding: t; -*- | |
;; Substantial credit to mnewt's dotemacs repo | |
;; Never load outdated bytecode | |
(setq load-prefer-newer t) | |
;; Garbage Collection Pt. 1 | |
(setq gc-cons-threshold most-positive-fixnum) | |
;;; Performance | |
;; Unset `file-name-handler-alist' (temporarily). | |
;; Opened files iterate through this list, but it never hits during startup. | |
(defvar file-name-handler-alist-old file-name-handler-alist) | |
(setq file-name-handler-alist nil) | |
(add-hook 'emacs-startup-hook | |
(lambda () | |
(setq file-name-handler-alist file-name-handler-alist-old))) | |
;; Theme | |
;; Faster to disable these here (before they've been initialized) | |
;; TODO: better syntax / numbers / what are the the defaults anyways | |
(push '(menu-bar-lines . 0) default-frame-alist) | |
(push '(tool-bar-lines . 0) default-frame-alist) | |
(push '(vertical-scroll-bars) default-frame-alist) | |
(push '(height . 50) default-frame-alist) | |
(push '(width . 174) default-frame-alist) | |
;; Skip adjusting frame-size based on font-size | |
(setq frame-inhibit-implied-resize t | |
frame-resize-pixelwise t) | |
;; Avoid flash of unstyled text | |
(set-face-attribute 'mode-line nil :background "#444" | |
:foreground "#fef8ea" | |
:overline "#666" | |
:underline "#666") | |
(set-face-attribute 'default nil :background "#242424" | |
:foreground "#f6f3e8") | |
(set-face-attribute 'fringe nil :background "#303030" | |
:foreground "#ddaa6f") | |
;; Ignore X Resources | |
(advice-add #'x-apply-session-resources :override #'ignore) | |
;; Guix will take care of this | |
(setq package-enable-at-startup nil) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; init.el -*- lexical-binding: t; -*- | |
;; | |
;; I'll have my dots availible someday, but having benefited so much from | |
;; the work of others, I want this milestone of mine availible for reference-- | |
;; maybe for me to look back on? I've just "finished" a re-write, 'cept that I've | |
;; got one prior config to skim form features (notably some splash-screen stuff) | |
;; and intend to rework most of my keybindings in tantum with a WIP custom keyboard | |
;; layout. Maybe try meow-mode? But I like a lot of Vim's eg. cmd-prompt stuff. | |
;; | |
;; Anyway, here's what I have /right now/, as finished as it is. | |
;; (No warranty expressed or implied). | |
;; | |
;; TODO: Intangible eshell prompt? | |
;; TODO: Vertico for :e find-file style prompt? | |
;; TODO: EAT term | |
;; TODO: Configure lispyville? | |
;; TODO: Can :q pls only close a buffer if no other windows have it open? | |
;; TODO: Fence edit | |
;; TODO: Sync C-w <arrow> bindings with kb config /and/ hjkl? | |
;; | |
;; The code is organized in pages, separated by formfeed characters. | |
;; | |
;; Substantial portions wisdom of: | |
;; - [doomemacs](https://github.com/doomemacs/doomemacs) | |
;; - emacs-bedrock | |
;; - mnewt's dotemacs repo | |
;; - kristofferbalintona.me | |
;; | |
;;; Native Compilation | |
(when (fboundp 'native-compile) | |
(setq package-native-compile t) | |
(custom-set-variables | |
'(native-comp-async-report-warnings-errors nil))) | |
;;; Optimization from doom-start.el | |
(setq auto-mode-case-fold nil) | |
(setq-default bidi-display-reordering 'left-to-right | |
bidi-paragraph-direction 'left-to-right) | |
(setq bidi-inhibit-bpa t) | |
(setq idle-update-delay 1.0) | |
;; Apparently can make posframes more responsive, cool | |
(when (boundp 'pgtk-wait-for-event-timeout) | |
(setq pgtk-wait-for-event-timeout 0.001)) | |
;; Don't ping things that look like domain names when using | |
;; find-file-at-point. | |
(setq ffap-machine-p-known 'reject) | |
;; Scolling optimization and tweaks | |
(setq jit-lock-defer-time 0) | |
(setq mouse-wheel-progressive-speed nil) | |
;; Ooo, yay! UTF-8! | |
(set-language-environment "UTF-8") | |
(setq default-input-method nil) | |
;;; Use-Package | |
'(:guix (emacs-use-package ; This refers to my fork with :custom-face <string> [...] | |
--with-git-url=emacs-use-package=file:///home/antlers/Projects/upstream/use-package | |
--with-branch=emacs-use-package=hotfix/revert-texi-setfilename)) | |
(eval-when-compile | |
(require 'use-package)) | |
(require 'bind-key) | |
;; Some hooks are un-usable without this. | |
(setq use-package-hook-name-suffix nil) | |
;; Setup the no-op :guix keyword | |
(push :guix use-package-keywords) | |
(defun use-package-normalize/:guix (_ keyword args) | |
(use-package-only-one (symbol-name keyword) args | |
(lambda (label arg) '()))) | |
(defun use-package-handler/:guix (name-symbol keyword archive-name rest state) | |
(use-package-process-keywords name-symbol rest state)) | |
;;; Packages with `use-package' extensions or no autoloads | |
(use-package dash :guix (emacs-dash)) | |
(use-package delight :guix (emacs-delight)) | |
(use-package general :guix (emacs-general)) | |
;;; Guix Integration | |
(use-package guix | |
:guix (emacs-guix) | |
:general (evil-leader-map "g u" 'guix) | |
:delight (guix-prettify-mode nil guix-prettify) | |
:custom (global-guix-prettify-mode t)) | |
;; Locate profile and home packages | |
(-map (lambda (dir) | |
(let ((default-directory dir)) | |
(normal-top-level-add-subdirs-to-load-path))) | |
'("~/.guix-home/profile/share/emacs/site-lisp/" | |
"~/.guix-profile/share/emacs/site-lisp/")) | |
;; Locate setuid binaries | |
;; Yes, I will pay the runtime cost of de-duping my PATH. | |
(when (file-directory-p "/run/setuid-programs") | |
(setenv "PATH" | |
(apply 'concat (delete-dups | |
(split-string (concat "/run/setuid-programs:" | |
(getenv "PATH")) | |
":")))) | |
(add-to-list 'exec-path "/run/setuid-programs")) | |
;; Load fonts from XDG directory | |
(-map (-cut add-to-list 'bdf-directory-list <>) | |
(-filter 'file-directory-p | |
(-map (-cut concat <> "fonts/truetype") | |
(parse-colon-path (getenv "XDG_DATA_DIRS"))))) | |
;;; Garbage Collection Pt. 2 | |
(use-package gcmh | |
:guix (emacs-gcmh) | |
:delight | |
:custom | |
(gcmh-idle-delay 'auto) ; default is 15s | |
(gcmh-auto-idle-delay-factor 10) | |
(gcmh-high-cons-threshold (* 16 1024 1024)) ; 16mb | |
(gcmh-mode t)) | |
;;; Native Emacs Configuration | |
(use-package autorevert | |
:custom | |
(auto-revert-avoid-polling t) | |
(auto-revert-check-vc-info t) | |
(auto-revert-interval 5) | |
(global-auto-revert-mode t)) | |
(use-package emacs | |
:custom | |
(cursor-in-non-selected-windows nil) ; Hide the cursor in inactive windows | |
(custom-file ; Disable custom-file persistence | |
(make-temp-file "custom-" nil ".el")) | |
(display-line-numbers-width 3) ; Mode-toggle is bound in evil config | |
(echo-keystrokes 0.001) ; Display prefixes in minibuffer instantly | |
(help-window-select t) ; Focus new help windows when opened | |
(highlight-nonselected-windows nil) ; Hide active region in inactive windows | |
(select-enable-clipboard t) ; Merge System and Emacs clipboard | |
(sentence-end-double-space nil) ; Let one space end a sentence | |
(switch-to-buffer-obey-display-actions t) ; "Make switching buffers more consistent" | |
(tab-always-indent 'complete) ; Preferred TAB behavior | |
(visible-bell nil) ; Disable visual-bell | |
;; Customized Modes | |
(blink-cursor-mode nil) ; Disable cursor blinking | |
(global-so-long-mode t) ; Disable major + some minor modes in large files | |
(repeat-mode t) ; Enable repeat-maps | |
(save-place-mode t) ; Remember cursor position | |
(savehist-mode t) ; Save history of minibuffer | |
(tooltip-mode nil) ; Disable tooltips | |
;; startup.el | |
(inhibit-startup-screen t) | |
(initial-scratch-message nil) | |
(initial-major-mode 'fundamental-mode) | |
:config | |
(server-start) ; Start server for emacsclient | |
(defalias 'yes-or-no-p 'y-or-n-p) ; Replace yes/no prompts with y/n | |
;; GPG / Pinentry | |
(setq epa-pinentry-mode 'loopback) | |
(defun pinentry-emacs (desc prompt ok error) | |
(concat (replace-regexp-in-string "%22" "\"" | |
(replace-regexp-in-string "%0A" "\n" desc)) | |
prompt ": ")) | |
;; FIX: Correct forward-page behavior when on a page delimiter | |
(advice-add 'forward-page :before | |
(lambda (_) | |
(when (and (looking-at page-delimiter) | |
(> (match-end 0) (point))) | |
(forward-char 1))))) | |
;; Default Tabs & Indents | |
(use-package emacs | |
:custom | |
(tab-width 2) | |
(indent-tabs-mode nil) | |
;; Must come last to use modified `tab-width'. | |
(tab-stop-list (number-sequence tab-width 120 tab-width)) | |
:config | |
(add-to-list 'warning-suppress-types '(defvaralias)) | |
(-map (-cut defvaralias <> 'tab-width) | |
'(c-basic-offset | |
css-indent-offset | |
evil-shift-width | |
lisp-indent-offset | |
sh-basic-offset))) | |
;; Mode-line | |
(use-package moody | |
:guix (emacs-moody) | |
:custom | |
(display-time-default-load-average nil) | |
(display-time-mode t) | |
(moody-mode-line-height 20) ; ~1ch | |
(x-underline-at-descent-line t) | |
:custom-face | |
(mode-line ((t (:overline "#666666" | |
:underline "#666666" | |
:foreground "#fef8ea")))) ; warmer text | |
(mode-line-inactive ((t :background "#383838"))) | |
:config | |
(moody-replace-mode-line-buffer-identification) | |
(moody-replace-vc-mode) | |
(moody-replace-eldoc-minibuffer-message-function)) | |
(use-package emacs | |
:delight (eldoc-mode nil eldoc) ; Hide eldoc-mode lighter | |
:custom (column-number-mode t) ; Enable column display | |
:config | |
(defun spaceline--column-number-at-pos (pos) | |
"Column number at POS. Analog to `line-number-at-pos'." | |
(save-excursion (goto-char pos) (current-column))) | |
(defun spaceline--selection-info () | |
"Information about the size of the current selection, when applicable. | |
Supports both Emacs and Evil cursor conventions." | |
(if (or mark-active | |
(and (bound-and-true-p evil-local-mode) | |
(eq 'visual evil-state))) | |
(let* ((lines (count-lines (region-beginning) (min (1+ (region-end)) (point-max)))) | |
(chars (- (1+ (region-end)) (region-beginning))) | |
(cols (1+ (abs (- (spaceline--column-number-at-pos (region-end)) | |
(spaceline--column-number-at-pos (region-beginning)))))) | |
(evil (and (bound-and-true-p evil-state) (eq 'visual evil-state))) | |
(rect (or (bound-and-true-p rectangle-mark-mode) | |
(and evil (eq 'block evil-visual-selection)))) | |
(multi-line (or (> lines 1) (and evil (eq 'line evil-visual-selection))))) | |
(cond | |
(rect (format "%d×%d" lines (if evil cols (1- cols)))) | |
(multi-line (format "%d/%d" lines chars)) | |
(t (format "1×%d" (if evil chars (1- chars)))))) | |
"0×0")) | |
(setq mode-line-position | |
(append mode-line-position | |
'((:propertize | |
(:eval (spaceline--selection-info)) | |
display | |
(min-width (5.0))))))) | |
;; Theme, Graphics, and Fringe | |
(use-package emacs | |
:guix (font-mononoki) | |
:custom (indicate-buffer-boundaries 'left) | |
:custom-face | |
(default ((t (:family "mononoki" :height 110)))) | |
;; These set the cursor, active-, & other- isearch results | |
;; (respectively, and which all default to grey) to visible colors. | |
(cursor ((t (:background"#ddaa6f")))) | |
(isearch ((t (:background ,(face-background 'cursor))))) | |
(lazy-highlight ((t (:background "#6b8dff")))) | |
;; Highlights | |
(custom-highlight | |
"My custom face for highlights and regions." | |
((((class color) (background dark)) :background "#00415e") | |
(((class color) (background light)) :background "#c0efff"))) | |
(highlight ((t (:inherit 'custom-highlight :background unspecified :underline nil)))) | |
(region ((t (:inherit 'custom-highlight :background unspecified :underline nil)))) | |
(show-paren-match ((t (:background "#6fa2dd")))) | |
;; Fringe | |
(fringe ((t (:foreground "#ddaa6f")))) | |
(vertical-border ((t (:background "#000")))) | |
:config (load-theme 'wombat)) | |
(use-package yascroll | |
:commands global-yascroll-bar-mode | |
:custom (yascroll:scroll-bar 'left-fringe) | |
(yascroll:delay-to-hide nil) | |
:custom-face (yascroll:thumb-fringe | |
((t (:foreground "#c69963" :background "#c69963"))))) | |
:init (general-after-gui | |
(global-yascroll-bar-mode 1)) | |
(use-package prettify-symbols-mode | |
:ghook 'lisp-mode-hook 'lisp-data-mode-hook) | |
(use-package highlight-indent-guides | |
:guix (emacs-highlight-indent-guides) | |
:delight | |
:ghook 'prog-mode-hook | |
:custom | |
;; Issue #107: Method 'character breaks with whitespace.el | |
(highlight-indent-guides-method 'column) | |
(highlight-indent-guides-auto-even-face-perc 20) | |
(highlight-indent-guides-auto-odd-face-perc 15)) | |
;; Enable /all/ the icons | |
(use-package all-the-icons | |
:guix (emacs-all-the-icons) | |
:defer t) | |
(use-package all-the-icons-dired | |
:guix (emacs-all-the-icons-dired) | |
:init (defun antlers/load-all-the-icons-dired-mode () | |
(unless (or (not (display-graphic-p)) | |
(file-remote-p default-directory)) | |
(all-the-icons-dired-mode) | |
(whitespace-mode -1))) | |
:ghook ('dired-mode-hook #'antlers/load-all-the-icons-dired-mode)) | |
(use-package all-the-icons-completion | |
:guix (emacs-all-the-icons-completion) | |
:init (add-function :before-while | |
all-the-icons-completion-mode | |
#'display-graphic-p) | |
:ghook ('marginalia-mode-hook #'all-the-icons-completion-marginalia-setup) | |
'vertico-mode-hook | |
'corfu-mode-hook) | |
(use-package kind-icon | |
:guix (emacs-kind-icon) | |
:after corfu | |
;; "To compute blended backgrounds correctly" | |
:custom (kind-icon-default-face 'corfu-default) | |
:ghook ('corfu-margin-formatters #'kind-icon-margin-formatter)) | |
;; Butlers | |
(use-package no-littering | |
:guix (emacs-no-littering) | |
:custom (auto-save-file-name-transforms | |
`((".*" ,(no-littering-expand-var-file-name "auto-save/") t)))) | |
(use-package ws-butler | |
:delight | |
:guix (emacs-ws-butler) | |
:ghook 'text-mode-hook) | |
;; Undo | |
(use-package undo-tree | |
:guix (emacs-undo-tree) | |
:delight | |
:custom | |
(undo-tree-auto-save-history t) ; preserve undo history | |
(undo-tree-histoyry-directory-alist ; where to keep it | |
(expand-file-name "undo-tree" user-emacs-directory)) | |
:config (global-undo-tree-mode t)) ; enable globally | |
;; Lisp Parens | |
(use-package rainbow-delimiters | |
:guix (emacs-rainbow-delimiters) | |
:ghook 'lisp-mode-hook | |
'emacs-lisp-mode-hook | |
'scheme-mode-hook | |
:config | |
(require 'cl-lib) | |
(require 'color) | |
(-map (lambda (lst) (set-face-foreground (car lst) (cadr lst))) | |
'((rainbow-delimiters-depth-1-face "dark orange") | |
(rainbow-delimiters-depth-2-face "deep pink") | |
(rainbow-delimiters-depth-3-face "chartreuse") | |
(rainbow-delimiters-depth-4-face "deep sky blue") | |
(rainbow-delimiters-depth-5-face "yellow") | |
(rainbow-delimiters-depth-6-face "orchid") | |
(rainbow-delimiters-depth-7-face "spring green") | |
(rainbow-delimiters-depth-8-face "sienna1"))) | |
(cl-loop for index from 1 to rainbow-delimiters-max-face-count do | |
(let ((face (intern (format "rainbow-delimiters-depth-%d-face" index)))) | |
;; TODO: Tune these in a GUI frame pls | |
(cl-callf color-desaturate-name (face-foreground face) 60) | |
(cl-callf color-darken-name (face-foreground face) 25)))) | |
;; Evil | |
(use-package evil | |
:guix (emacs-evil) | |
:demand | |
:general ("C-M-u" #'universal-argument) ; evil-want-Y-yank-to-eol | |
;; Swap evil section keys with emacs defaults | |
;; C-g -> normal mode | |
(:states 'normal | |
"\\" #'evil-leader-map | |
"C-SPC" #'evil-leader-map) | |
(:states 'insert | |
"C-g" #'evil-normal-state) | |
(:states 'motion | |
"] ]" #'forward-page | |
"[ [" #'backward-page | |
"C-x ]" #'evil-forward-section-begin | |
"C-x [" #'evil-backward-section-end) | |
;; Prioritize native org-cycle over evil-jump-forward | |
(:states 'normal | |
:keymaps 'org-mode-map | |
"<tab>" #'org-cycle | |
"TAB" #'org-cycle) | |
(:keymaps 'evil-leader-map | |
"#" #'display-line-numbers-mode) | |
;; TODO: Why no general do this? | |
:bind (:repeat-map evil-windows/repeat-map | |
(">" . evil-window-increase-width) | |
("<" . evil-window-decrease-width)) | |
:custom | |
(evil-respect-visual-line-mode t) | |
(evil-undo-system 'undo-tree) | |
(evil-want-C-u-scroll t) ; universal-arg is rebound to C-M-u in :bind | |
(evil-want-Y-yank-to-eol t) | |
(evil-want-fine-undo t) | |
(evil-want-integration t) | |
(evil-want-keybinding nil) | |
:init | |
(evil-mode t) | |
:config | |
;; enable leader key, bound to \ and C-SPC in normal mode | |
;; XXX: C-SPC doesn't work in TUI frames :/ | |
(define-prefix-command 'evil-leader-map) | |
(evil-set-initial-state 'eshell-mode 'normal)) | |
(use-package evil-collection | |
:guix (emacs-evil-collection) | |
:after evil | |
:delight (evil-collection-unimpaired-mode nil evil-collection-unimpaired) | |
:custom (evil-collection-setup-minibuffer t) | |
:config (evil-collection-init)) | |
;; Other Navigation | |
(use-package avy | |
:guix (emacs-avy) | |
:after (evil) | |
:custom (avy-timeout-seconds 0.35) | |
;; Good combo of QUERTY and STRDY keys | |
(avy-keys '(?s ?d ?l ?o ?u ?i ?e ?a ?f ?r)) | |
:general ("C-l" 'evil-avy-goto-line) | |
(:states 'motion | |
"g s" #'evil-avy-goto-char-timer | |
"g l" #'evil-avy-goto-line) | |
(isearch-mode-map | |
"M-j" #'avy-isearch) | |
:config | |
;; https://gist.github.com/karthink/af013ffd77fe09e67360f040b57b4c7b | |
;; Embark | |
(defun avy-action-embark (pt) | |
(unwind-protect | |
(save-excursion | |
(goto-char pt) | |
(embark-act)) | |
(select-window | |
(cdr (ring-ref avy-ring 0)))) | |
t) | |
(setf (alist-get ?. avy-dispatch-alist) 'avy-action-embark) | |
;; Kill text | |
(defun avy-action-kill-whole-line (pt) | |
(save-excursion | |
(goto-char pt) | |
(kill-whole-line)) | |
(select-window | |
(cdr (ring-ref avy-ring 0))) | |
t) | |
(setf (alist-get ?k avy-dispatch-alist) 'avy-action-kill-stay | |
(alist-get ?K avy-dispatch-alist) 'avy-action-kill-whole-line) | |
;; Copy text | |
(defun avy-action-copy-whole-line (pt) | |
(save-excursion | |
(goto-char pt) | |
(cl-destructuring-bind (start . end) | |
(bounds-of-thing-at-point 'line) | |
(copy-region-as-kill start end))) | |
(select-window | |
(cdr (ring-ref avy-ring 0))) | |
t) | |
(setf (alist-get ?w avy-dispatch-alist) 'avy-action-copy | |
(alist-get ?W avy-dispatch-alist) 'avy-action-copy-whole-line) | |
;; Yank text | |
(defun avy-action-yank-whole-line (pt) | |
(avy-action-copy-whole-line pt) | |
(save-excursion (yank)) | |
t) | |
(setf (alist-get ?y avy-dispatch-alist) 'avy-action-yank | |
(alist-get ?Y avy-dispatch-alist) 'avy-action-yank-whole-line) | |
;; Transpose/Move text | |
(defun avy-action-teleport-whole-line (pt) | |
(avy-action-kill-whole-line pt) | |
(save-excursion (yank)) t) | |
(setf (alist-get ?t avy-dispatch-alist) 'avy-action-teleport | |
(alist-get ?T avy-dispatch-alist) 'avy-action-teleport-whole-line) | |
;; Transpose/Move sexp | |
(defun avy-action-exchange (pt) | |
(set-mark pt) | |
(transpose-sexps 0)) | |
(add-to-list 'avy-dispatch-alist '(?e . avy-action-exchange)) | |
;; Mark text | |
(defun avy-action-mark-to-char (pt) | |
(activate-mark) | |
(goto-char pt)) | |
(setf (alist-get ? avy-dispatch-alist) 'avy-action-mark-to-char)) | |
;;; Completion-at-point Stack | |
(use-package orderless | |
:guix (emacs-orderless) | |
:custom | |
(completion-styles '(orderless)) | |
(completion-category-defaults nil) | |
(completion-category-overrides '((file (styles partial-completion))))) | |
;; Vertico | |
(use-package vertico | |
:guix (emacs-vertico) | |
;; https://kristofferbalintona.me/posts/202202211546/ | |
:after (savehist orderless) | |
:init | |
(defun kb/vertico-quick-embark (&optional arg) | |
"Embark on candidate using quick keys." | |
(interactive) | |
(when (vertico-quick-jump) | |
(embark-act arg))) | |
(vertico-mode t) | |
:custom | |
(enable-recursive-minibuffers t) ; i need this | |
(minibuffer-depth-indicate-mode t) | |
;; Do not allow the cursor inside the text of the minibuffer prompt | |
(minibuffer-prompt-properties | |
'(read-only t cursor-intangible t face minibuffer-prompt)) | |
:ghook ('minibuffer-setup-hook #'cursor-intangible-mode) | |
:general (vertico-map | |
"C-l" #'kb/vertico-quick-embark | |
"<backspace>" #'vertico-directory-delete-char | |
"C-<backspace>" #'vertico-directory-delete-word | |
"RET" #'vertico-directory-enter)) | |
(use-package vertico-posframe | |
:guix (emacs-vertico-posframe) | |
:after vertico | |
:custom (vertico-posframe-parameters '((frame-border-width . 8))) | |
:init (when (display-graphic-p) (vertico-posframe-mode 1))) | |
(use-package marginalia | |
:guix (emacs-marginalia) | |
:after vertico | |
:general (minibuffer-local-map "M-A" #'marginalia-cycle) | |
:init (marginalia-mode t)) | |
(use-package corfu | |
:guix (emacs-corfu) | |
:after (cape consult) | |
:custom | |
(corfu-auto t) | |
(corfu-cycle t) | |
(corfu-echo-documentation nil) | |
(corfu-min-width 35) | |
(corfu-preselect-first nil) | |
(corfu-quit-no-match nil) | |
(global-corfu-mode t) | |
:general (corfu-map | |
;; XXX: Prevents tab-completion of a single candidate | |
; "TAB" #'corfu-next | |
; [tab] #'corfu-next | |
; "S-TAB" #'corfu-previous | |
; [backtab] #'corfu-previous | |
"S-SPC" #'corfu-insert-separator) | |
:config | |
;; Move to Minibuffer | |
;; This is from the Corfu README, but pairs well with `embark-collect' | |
(defun corfu-move-to-minibuffer () | |
(interactive) | |
(let ((completion-extra-properties corfu--extra) | |
completion-cycle-threshold completion-cycling) | |
(apply 'consult-completion-in-region completion-in-region--data))) | |
(define-key corfu-map "\M-m" 'corfu-move-to-minibuffer) | |
;; Enable around Vertico | |
(defun corfu-enable-always-in-minibuffer () | |
"Enable Corfu in the minibuffer if Vertico/Mct are not active." | |
(unless (bound-and-true-p vertico--input) | |
(setq-local corfu-auto nil) ; only in buffer | |
(corfu-mode 1))) | |
(add-hook 'minibuffer-setup-hook 'corfu-enable-always-in-minibuffer 1) | |
;; Enable in Eshell | |
(add-hook 'eshell-mode-hook | |
(lambda () | |
(setq-local corfu-auto nil) ; only in buffer | |
(corfu-mode 1))) | |
(defun corfu-send-shell (&rest _) | |
"Send completion candidate when inside comint/eshell." | |
(cond | |
((and (derived-mode-p 'eshell-mode) (fboundp 'eshell-send-input)) | |
(eshell-send-input)) | |
((and (derived-mode-p 'comint-mode) (fboundp 'comint-send-input)) | |
(comint-send-input)))) | |
(advice-add 'corfu-insert :after 'corfu-send-shell) | |
;; Strongly recommended in the README | |
(-map (-cut advice-add 'pcomplete-completions-at-point :around <>) | |
(list 'cape-wrap-silent 'cape-wrap-purify))) | |
(use-package corfu-terminal | |
:guix (emacs-corfu-terminal) | |
:config (unless (display-graphic-p) | |
(corfu-terminal-mode 1))) | |
(use-package cape | |
:guix (emacs-cape) | |
:demand | |
;; These are defaults from the cape README. | |
:general ("C-c p p" #'completion-at-point | |
"C-c p t" #'complete-tag | |
"C-c p h" #'cape-history | |
"C-c p f" #'cape-file | |
"C-c p k" #'cape-keyword | |
"C-c p s" #'cape-symbol | |
"C-c p a" #'cape-abbrev | |
"C-c p i" #'cape-ispell | |
"C-c p l" #'cape-line | |
"C-c p w" #'cape-dict | |
"C-c p r" #'cape-rfc1345) | |
:init | |
(add-to-list 'completion-at-point-functions 'cape-file)) | |
(use-package embark | |
:guix (emacs-embark ; This refers to my fork with a page-able which-key pop-up on `embark-collect' | |
--with-git-url=emacs-embark=file:///home/antlers/Projects/upstream/embark | |
--with-branch=emacs-embark=fix/issue-647) | |
:after evil | |
:general ("C-." #'embark-act ; pick some comfortable binding | |
"C-;" #'embark-dwim ; good alternative: M-. | |
"C-h B" #'embark-bindings) ; alternative for `describe-bindings' | |
(:state 'normal | |
;; XXX: "C-." doesn't work in Zorin's Gnome Terminal. | |
"C-." #'embark-act) | |
;; Replace the key help with a completing-read interface | |
:custom (prefix-help-command 'embark-prefix-help-command) | |
:config | |
(defun embark--add-which-key-map (keymap) | |
(make-composed-keymap (which-key--get-popup-map) keymap)) | |
(advice-add #'embark--action-keymap | |
:filter-return | |
#'embark--add-which-key-map) | |
(defun embark-which-key-indicator () | |
"An embark indicator that displays keymaps using which-key. | |
The which-key help message will show the type and value of the | |
current target followed by an ellipsis if there are further | |
targets." | |
(lambda (&optional keymap targets prefix) | |
(if (null keymap) | |
(which-key--hide-popup-ignore-command) | |
(which-key--show-keymap | |
(if (eq (plist-get (car targets) :type) 'embark-become) | |
"Become" | |
(format "Act on %s '%s'%s" | |
(plist-get (car targets) :type) | |
(embark--truncate-target (plist-get (car targets) :target)) | |
(if (cdr targets) "…" ""))) | |
(if prefix | |
(pcase (lookup-key keymap prefix 'accept-default) | |
((and (pred keymapp) km) km) | |
(_ (key-binding prefix 'accept-default))) | |
keymap) | |
nil nil t (lambda (binding) | |
(not (string-suffix-p "-argument" (cdr binding)))))))) | |
(setq embark-indicators | |
'(embark-which-key-indicator | |
embark-highlight-indicator | |
embark-isearch-highlight-indicator)) | |
(defun embark-hide-which-key-indicator (fn &rest args) | |
"Hide the which-key indicator immediately when using the completing-read prompter." | |
(which-key--hide-popup-ignore-command) | |
(let ((embark-indicators | |
(remq #'embark-which-key-indicator embark-indicators))) | |
(apply fn args))) | |
(advice-add #'embark-completing-read-prompter | |
:around #'embark-hide-which-key-indicator) | |
;; Hide the mode line of the Embark live/completions buffers | |
(add-to-list 'display-buffer-alist | |
'("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*" | |
nil | |
(window-parameters (mode-line-format . none))))) | |
(use-package consult | |
:guix (emacs-consult) | |
:demand | |
:general ("M-y" #'consult-yank-pop ; orig. yank-pop | |
;; C-x bindings (ctl-x-map) | |
[remap switch-to-buffer] #'consult-buffer | |
"C-x p b" #'consult-project-buffer ; orig. project-switch-to-buffer | |
"C-x r b" #'consult-bookmark ; prefer to narrow consult-buffer | |
;; M-g bindings (goto-map) | |
"M-g o" #'consult-outline | |
"M-g g" #'consult-goto-line ; orig. goto-line | |
"M-g i" #'consult-imenu | |
;; M-s bindings (search-map) | |
"M-s d" #'consult-find | |
"M-s g" #'consult-grep | |
"M-s G" #'consult-git-grep | |
"M-s r" #'consult-ripgrep | |
"C-s" #'consult-line | |
"M-s l" #'consult-line | |
"M-s L" #'consult-line-multi | |
"M-s s" #'isearch-forward) | |
;; Isearch integration | |
(:keymaps 'isearch-mode-map | |
"M-m" #'consult-isearch-history ; like move-to-minibuffer | |
"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 (???) | |
:custom (consult-narrow-key "<")) | |
(use-package embark-consult | |
:ghook ('embark-collect-mode-hook #'consult-preview-at-point-mode)) | |
;; Minor Modes | |
(use-package flyspell | |
:ghook ('(prog-mode-hook) #'flyspell-prog-mode) | |
('(git-commit-mode-hook) #'flyspell-mode) | |
:custom | |
(ispell-personal-dictionary ; Keep `ispell' dictionary in .emacs.d | |
"/home/antlers/Sync/org/ispell-english.dict") | |
(ispell-silently-savep t)) ; Don't ask before saving dict. updates | |
(use-package which-key | |
:delight | |
:guix (emacs-which-key) | |
;; "same as default, except all keys from local maps shown first" | |
:custom | |
(which-key-sort-order 'which-key-local-then-key-order) | |
(which-key-use-C-h-commands t) | |
(which-key-idle-delay 0.5) | |
:init (which-key-mode t)) | |
(use-package whitespace | |
:ghook ('prog-mode-hook #'whitespace-mode) | |
:custom (whitespace-space 'whitespace-newline) | |
(whitespace-style '(face lines-tail missing-newline-at-eof tab-mark))) | |
(use-package git-gutter | |
:guix (emacs-git-gutter) | |
:commands (git-gutter-mode) | |
:ghook ('prog-mode-hook #'git-gutter-mode)) | |
(use-package rainbow-mode | |
:delight | |
:guix (emacs-rainbow-mode) | |
:ghook ('prog-mode-hook #'rainbow-mode)) | |
;;; Application Packages | |
(use-package dirvish | |
:guix (emacs-dirvish) | |
:init (dirvish-override-dired-mode)) | |
(use-package magit | |
:guix (emacs-magit) | |
:general (evil-leader-map "g g" #'magit) | |
:custom (magit-diff-refine-hunk t)) | |
(defvar ledger-dir | |
(concat (getenv "HOME") "/Sync/org/ledger")) | |
(defvar ledger-init-file-name | |
(concat ledger-dir "/ledgerrc")) | |
(use-package ledger-mode | |
:guix (emacs-ledger-mode) | |
:general (evil-leader-map | |
"l" '((lambda () | |
(interactive) | |
(find-file ledger-dir)) | |
:which-key "ledger"))) | |
;; Org | |
(use-package org | |
:guix (emacs-org) | |
:custom | |
(org-startup-indented t) | |
(org-agenda-files '("~/Sync/org/")) | |
(diary-file "~/Sync/org/diary") | |
(org-default-notes-file "~/Sync/org/agenda.org") | |
(org-todo-keywords '((sequence "TODO" "HOLD" "DONE"))) | |
(org-todo-keyword-faces '(("TODO" . org-todo) | |
("HOLD" . org-warning) | |
("DONE" . org-done))) | |
:general (:keymaps 'evil-leader-map | |
"a" #'org-agenda | |
"t" #'org-todo-list | |
"c" #'org-capture) | |
:gfhook 'visual-line-mode | |
'flyspell-mode) | |
;; This is it's own block because `org-agenda-map' isn't loaded by `org'. | |
(use-package org-agenda | |
:after org | |
:general (:keymaps 'org-agenda-mode-map | |
"j" #'evil-next-line | |
"k" #'evil-previous-line)) | |
(use-package ob | |
:after org | |
:custom (org-src-preserve-indentation t) | |
:config (org-babel-do-load-languages | |
'org-babel-load-languages | |
'((gnuplot . t)))) | |
(use-package ox-haunt | |
:after ox) | |
;; Eshell | |
(use-package eshell | |
:general (:keymaps 'evil-leader-map | |
"q" #'eshell | |
"Q" #'eshell) | |
:init | |
(defun maybe-eshell () | |
"Open eshell instead of *scratch* buffer." | |
(when (and (string= "*scratch*" (buffer-name)) (not (buffer-file-name))) | |
(eshell))) | |
:ghook ('after-init-hook #'maybe-eshell) | |
:config | |
;; Clever rebinding of nvim/emacs -> :edit | |
(defun eshell/my-find-file (pattern) | |
(if (stringp pattern) | |
(find-file pattern) | |
(mapc 'find-file (mapcar 'expand-file-name pattern)))) | |
(defun eshell/nvim (&rest args) | |
(apply 'eshell/my-find-file args)) | |
(defun eshell/emacs (&rest args) | |
(apply 'eshell/my-find-file args)) | |
;; Ooo, now here's something bold: | |
(defun quit-to-eshell () | |
(interactive) | |
(if (> (count-windows) 1) | |
(kill-buffer-and-window) | |
(kill-buffer) | |
(eshell))) | |
(defun save-and-quit-to-eshell () | |
(interactive) | |
(save-buffer) | |
(if (> (count-windows) 1) | |
(kill-buffer-and-window) | |
(kill-buffer) | |
(eshell))) | |
(evil-ex-define-cmd "q[uit]" 'quit-to-eshell) | |
(evil-ex-define-cmd "wq[writequit]" 'save-and-quit-to-eshell)) | |
(use-package eshell-syntax-highlighting | |
:guix (emacs-eshell-syntax-highlighting) | |
:after eshell | |
:config (eshell-syntax-highlighting-global-mode t)) | |
(use-package eshell-prompt-extras | |
:guix (emacs-eshell-prompt-extras) | |
:after eshell | |
:init (autoload 'epe-theme-lambda "eshell-prompt-extras") | |
:custom (eshell-highlight-prompt nil) | |
(eshell-prompt-function 'epe-theme-lambda)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment