From 3b4590b1a745b06ce36cb558a4749923675e9b35 Mon Sep 17 00:00:00 2001 From: Jake Koroman Date: Sun, 1 Jun 2025 10:55:23 -0400 Subject: Ready. Set. Go! --- emacs/init.el | 589 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 589 insertions(+) create mode 100644 emacs/init.el (limited to 'emacs/init.el') diff --git a/emacs/init.el b/emacs/init.el new file mode 100644 index 0000000..b6f82c6 --- /dev/null +++ b/emacs/init.el @@ -0,0 +1,589 @@ +;;; -*- lexical-binding: t -*- + +(setq custom-file (concat user-emacs-directory "custom.el")) +(add-to-list 'load-path "~/.config/emacs/local") +(add-to-list 'custom-theme-load-path "~/.config/emacs/local") +(when (file-exists-p custom-file) + (load custom-file)) + +(load "odin-mode.el") + +;;; Appearance and basic functionality +(menu-bar-mode -1) +(tool-bar-mode -1) +(scroll-bar-mode -1) + +(setq jrk/font-name "Iosevka-") +(setq jrk/font-size 12) +(setq jrk/font-big-size 24) +(setq jrk/font (concat jrk/font-name (number-to-string jrk/font-size))) +(modify-all-frames-parameters `((font . ,jrk/font))) + +(set-default 'truncate-lines nil) + +(add-hook 'before-save-hook 'delete-trailing-whitespace) + +;; no tabs in lisp files +(add-hook 'scheme-mode-hook (lambda () (setq indent-tabs-mode nil))) +(add-hook 'emacs-lisp-mode-hook (lambda () (setq indent-tabs-mode nil))) + +;; tab-width 2 in html and js files +(add-hook 'mhtml-mode-hook (lambda () (setq tab-width 2))) +(add-hook 'js-mode-hook (lambda () + (setq js-indent-level 2) + (setq tab-width 2))) + +(add-hook 'Info-mode-hook (lambda () (display-line-numbers-mode -1))) + +(setq display-buffer-alist + '( + ((or "\\*Help\\*" + "\\*Occur\\*") + (display-buffer-reuse-mode-window display-buffer-below-selected)) + )) + +;; (setq-default indent-tabs-mode nil) +(setq-default tab-width 4) +(setq inhibit-splash-screen t + inhibit-startup-message t + scroll-step 3 + auto-save-default nil + make-backup-files nil + blink-cursor-mode nil + ring-bell-function 'ignore + display-line-numbers-type 'relative + dired-listing-switches "-alh --group-directories-first" + compilation-scroll-output t + gc-cons-threshold 100000000 + compilation-ask-about-save nil + frame-resize-pixelwise t + mouse-drag-mode-line-buffer 1 + display-time-24hr-format t + ) + +;; (global-hl-line-mode 1) +(global-display-line-numbers-mode) + +(require 'package) +(add-to-list 'package-archives + '("melpa-stable" . "https://stable.melpa.org/packages/") t) + +(use-package compile + :ensure t + :config + ;; pascal compilation errors + (add-to-list 'compilation-error-regexp-alist + '("^\\(.*\\)(\\([0-9]+\\)+\\,\\([0-9]+\\)).*" 1 2 3))) + +(use-package modus-themes + :ensure t + :config + (setq modus-themes-org-blocks 'gray-background) + (load-theme 'modus-operandi t)) + +(use-package ef-themes + :ensure t) + +;;; TODO: make guix package +;; (use-package gruber-darker-theme +;; :ensure t) + +(use-package minions + :ensure t + + :custom + (minions-mode-line-delimiters (cons "" "")) + + :config + (defun +set-minions-mode-line-lighter () + (setq minions-mode-line-lighter + (if (display-graphic-p) "⚙" "#"))) + + (add-hook 'server-after-make-frame-hook #'+set-minions-mode-line-lighter) + (display-time-mode 1) + (display-battery-mode 1) + (minions-mode 1)) + +(use-package olivetti + :ensure t + :config + (add-hook 'olivetti-mode-on-hook (lambda () (olivetti-set-width 144)))) + +(use-package zenburn-theme + :ensure t) + +(use-package savehist + :ensure nil + :init + (savehist-mode)) + +(use-package eat + :ensure t) +;; (add-hook 'eshell-first-time-mode-hook #'eat-eshell-mode)) + +(use-package eshell + :ensure nil + :config + (setq eshell-cp-interactive-query t) (add-to-list 'eshell-modules-list 'eshell-elecslash) + :hook (eshell-mode . (lambda () + (display-line-numbers-mode -1)))) + +(use-package vertico + :ensure t + :init + (vertico-mode 1) + (setq vertico-cycle t) + :config + (setq vertico-multiform-categories + '((consult-grep + buffer + (vertico-buffer-display-action . (display-buffer-same-window)))))) + +(use-package orderless + :ensure t + :init + ;; Configure a custom style dispatcher (see the Consult wiki) + ;; (setq orderless-style-dispatchers '(+orderless-consult-dispatch orderless-affix-dispatch) + ;; orderless-component-separator #'orderless-escapable-split-on-space) + (setq completion-styles '(orderless basic) + completion-category-defaults nil + completion-category-overrides '((file (styles partial-completion)))) + :config + (vertico-multiform-mode) + (setq vertico-multiform-categories + '((consult-grep buffer)))) + +(use-package dired + :ensure nil + :bind + (:map dired-mode-map + ("o" . dired-find-file) + ("n" . dired-up-directory)) + :config + (setq dired-clean-up-buffers-too t + dired-dwim-target t + dired-recursive-copies 'always + dired-recursive-deletes 'top + global-auto-revert-non-file-buffers t + auto-revert-verbose nil)) + +(use-package marginalia + :ensure t + :init + (marginalia-mode)) + +(use-package company + :ensure t + :config + (setq company-idle-delay nil) + (global-company-mode) + :bind + ("C-" . company-complete) + ("C-" . dabbrev-expand)) + +(use-package yasnippet + :ensure t + :config + (require 'company) + ;; Add yasnippet support for all company backends + ;; https://github.com/syl20bnr/spacemacs/pull/179 + (defvar company-mode/enable-yas t + "Enable yasnippet for all backends.") + + (defun company-mode/backend-with-yas (backend) + (if (or (not company-mode/enable-yas) (and (listp backend) (member 'company-yasnippet backend))) + backend + (append (if (consp backend) backend (list backend)) + '(:with company-yasnippet)))) + (setq company-backends (mapcar #'company-mode/backend-with-yas company-backends)) + (yas-global-mode 1)) + +(use-package dumb-jump + :ensure t + :config + (setq xref-show-definitions-function #'xref-show-definitions-completing-read) + (add-hook 'xref-backend-functions #'dumb-jump-xref-activate)) + +(use-package magit :ensure t) + +(use-package go-mode :ensure t) + +(use-package lua-mode :ensure t) + +(use-package rust-mode :ensure t) + +(use-package glsl-mode :ensure t) + +(use-package htmlize :ensure t) + +(use-package zig-mode + :ensure t + :config + (setq zig-format-on-save nil)) + +(use-package org + :ensure nil + :config + (setq org-directory "~/org") + (setq org-agenda-files (list org-directory)) + (setq org-html-validation-link nil) + (setq org-insert-heading-respect-content t) + (org-babel-do-load-languages + 'org-babel-load-languages + '((shell . t))) + :hook (org-mode . (lambda () + (display-line-numbers-mode -1)))) + +(use-package org-tempo + :ensure t + :after (org) + :config + (add-to-list 'org-structure-template-alist + '("el" . "src emacs-lisp"))) + +(use-package org-bullets + :ensure t + :after (org) + :ensure + :hook + (org-mode . (lambda () + (org-bullets-mode)))) + +(use-package ido + :ensure t + :config + (setq ido-enable-flex-matching t + ido-everywhere t + ido-show-dot-for-dired t + ido-auto-merge-work-directories-length -1) + (ido-mode 0)) + +(use-package message + :ensure nil + :config + (setq message-kill-buffer-on-exit t)) + +(use-package notmuch + :ensure t + :hook + (message-setup . (lambda () (mml-secure-sign-pgpmime))) + :bind + ("C-c n" . notmuch) + :config + (setq send-mail-function 'sendmail-send-it + sendmail-program "msmtp" + ;; msmtp read from address to determine which smtp account to use + message-sendmail-extra-arguments '("--read-envelope-from") + ;; removes the very evil --from + message-sendmail-f-is-evil t) + + (setq notmuch-identities '("Jake Koroman " + "Jake Koroman ")) + (setq notmuch-fcc-dirs '(("jake@jakekoroman.com" . "personal/Sent") + ("koromanj@miltonhydro.com" . "work/Sent"))) + (setq notmuch-always-prompt-for-sender t) + (setq notmuch-draft-folder "drafts")) + +(setq-default c-basic-offset 4 + c-default-style '((java-mode . "java") + (awk-mode . "awk") + (other . "bsd"))) +(c-set-offset 'case-label '+) + +(font-lock-add-keywords 'c-mode + '(("internal" . font-lock-keyword-face) + ("global" . 'font-lock-keyword-face))) + +(defun jrk/eshell () + "Open eshell in other window" + (interactive) + (split-window-sensibly) + (other-window 1) + (eshell)) + +(defun jrk/indent-buffer () + "Run indent-region on entire buffer" + (interactive) + (indent-region (point-min) (point-max) nil)) +;; (add-hook 'before-save-hook 'indent-buffer) + +(defun jrk/find-corresponding-file () + "Find the file that corresponds to this one." + (interactive) + (setq CorrespondingFileName nil) + (setq BaseFileName (file-name-sans-extension buffer-file-name)) + (if (string-match "\\.c" buffer-file-name) + (setq CorrespondingFileName (concat BaseFileName ".h"))) + (if (string-match "\\.h" buffer-file-name) + (if (file-exists-p (concat BaseFileName ".c")) + (setq CorrespondingFileName (concat BaseFileName ".c")) + (setq CorrespondingFileName (concat BaseFileName ".cpp")))) + (if (string-match "\\.hin" buffer-file-name) + (setq CorrespondingFileName (concat BaseFileName ".cin"))) + (if (string-match "\\.cin" buffer-file-name) + (setq CorrespondingFileName (concat BaseFileName ".hin"))) + (if (string-match "\\.cpp" buffer-file-name) + (setq CorrespondingFileName (concat BaseFileName ".h"))) + (if CorrespondingFileName (find-file CorrespondingFileName) + (error "Unable to find a corresponding file"))) + +(defun jrk/find-corresponding-file-other-window () + "Finds the file that corresponds to this and opens it in the other window." + (interactive) + (find-file-other-window buffer-file-name) + (find-corresponding-file)) + +(defun jrk/gud () + "Run gud-gdb in other window" + (interactive) + (let* ((files (directory-files (file-name-directory buffer-file-name))) + (input (completing-read "executable: " files))) + (split-window-sensibly) + (other-window 1) + (gud-gdb (concat "gdb --fullname " input)))) + +;; Sets the default compile command based on OS +(if (string= system-type "windows-nt") + (setq compile-command "build.bat") + (setq compile-command "guix shell -m ./manifest.scm -- ./build.sh")) + +(defun jrk/disable-all-themes () + "Disables all active themes." + (interactive) + (dolist (i custom-enabled-themes) + (disable-theme i))) + +(defun jrk/load-theme-proper () + "Disables all active themes and loads new one" + (interactive) + (let ((theme (completing-read "Load custom theme: " (custom-available-themes)))) + (jrk/disable-all-themes) + (load-theme (intern theme) t))) + +(defun jrk/update-theme () + "Set theme based on time of day" + (interactive) + (let ((hour (nth 2 (parse-time-string (current-time-string))))) + (disable-all-themes) + (if (and (> hour 9) + (< hour 18)) + (load-theme 'zenburn t) + (load-theme 'gruber-darker t)))) + +(defun jrk/swap-theme () + "Swaps theme to either zenburn or gruber-darker" + (interactive) + (let ((theme (nth 0 custom-enabled-themes))) + (disable-all-themes) + (if (string= theme "gruber-darker") + (load-theme 'zenburn t) + (load-theme 'gruber-darker t)))) + +(defun jrk/transparency (value) + "Sets the transparency of the frame window. 0=transparent/100=opaque" + (interactive "nTransparency Value 0 - 100 opaque: ") + (set-frame-parameter (selected-frame) 'alpha-background value)) + +(defun jrk/toggle-big-font () + "Toggles on/off a bigger font for hidpi or presentations" + (interactive) + (if (eq (aref (font-info (face-attribute 'default :font)) 2) (* 2 jrk/font-size)) + (setq jrk/font (concat jrk/font-name (number-to-string jrk/font-big-size))) + (setq jrk/font (concat jrk/font-name (number-to-string jrk/font-size)))) + (set-frame-font jrk/font)) + +(defun jrk/meow-setup-colemakdh () + (setq meow-cheatsheet-layout meow-cheatsheet-layout-colemak-dh) + (meow-motion-overwrite-define-key + '("i" . meow-prev) + '("e" . meow-next) + '(";" . meow-temp-normal) + '("/" . meow-visit) + '("" . ignore)) + (meow-leader-define-key + '("?" . meow-cheatsheet) + '("." . find-file) + '("," . switch-to-buffer) + '(">" . find-file-other-window) + '("<" . switch-to-buffer-other-window) + '("q" . compile) + '("d" . dired-jump) + '("o" . other-window) + '("1" . meow-digit-argument) + '("2" . meow-digit-argument) + '("3" . meow-digit-argument) + '("4" . meow-digit-argument) + '("5" . meow-digit-argument) + '("6" . meow-digit-argument) + '("7" . meow-digit-argument) + '("8" . meow-digit-argument) + '("9" . meow-digit-argument) + '("0" . meow-digit-argument)) + (meow-normal-define-key + '("0" . meow-expand-0) + '("1" . meow-expand-1) + '("2" . meow-expand-2) + '("3" . meow-expand-3) + '("4" . meow-expand-4) + '("5" . meow-expand-5) + '("6" . meow-expand-6) + '("7" . meow-expand-7) + '("8" . meow-expand-8) + '("9" . meow-expand-9) + '("-" . negative-argument) + '(";" . meow-reverse) + '("," . meow-inner-of-thing) + '("." . meow-bounds-of-thing) + '("[" . meow-beginning-of-thing) + '("]" . meow-end-of-thing) + '("/" . meow-visit) + '("a" . meow-append) + '("A" . meow-open-below) + '("b" . meow-back-word) + '("B" . meow-back-symbol) + '("c" . meow-change) + '("i" . meow-prev) + '("I" . join-line) + '("f" . meow-find) + '("g" . meow-cancel-selection) + '("G" . meow-grab) + '("n" . meow-left) + '("N" . meow-left-expand) + '("o" . meow-right) + '("O" . meow-right-expand) + '("j" . meow-join) + '("k" . meow-kill) + '("l" . meow-line) + '("L" . meow-goto-line) + '("h" . meow-mark-word) + '("H" . meow-mark-symbol) + '("e" . meow-next) + '("E" . meow-next-expand) + '("m" . meow-block) + '("M" . meow-to-block) + '("p" . meow-yank) + '("q" . meow-quit) + '("r" . meow-replace) + '("s" . meow-insert) + '("S" . meow-open-above) + '("t" . meow-till) + '("u" . meow-undo) + '("U" . meow-undo-in-selection) + '("v" . meow-search) + '("w" . meow-next-word) + '("W" . meow-next-symbol) + '("x" . meow-delete) + '("X" . meow-backward-delete) + '("y" . meow-save) + '("z" . meow-pop-selection) + '("'" . repeat) + '("" . ignore))) + +(global-set-key (kbd "M-n") 'next-error) +(global-set-key (kbd "M-p") 'previous-error) +(global-set-key (kbd "") 'olivetti-mode) + +(use-package meow + :ensure t + :config + (add-to-list 'meow-mode-state-list '(notmuch-hello-mode . motion)) + (add-to-list 'meow-mode-state-list '(notmuch-search-mode . motion)) + (setq meow-use-clipboard t) + (setq meow-keypad-self-insert-undefined nil) + (jrk/meow-setup-colemakdh) + (meow-setup-indicator) + (meow-global-mode 1)) + +(setq jrk/mpv-cmd "mpv") +(setq jrk/ytdlp-cmd "yt-dlp") +(setq jrk/ytdlp-cmd-args '("--embed-chapters" "--sponsorblock-remove" "Sponsor" "-P" "~/videos")) + +(defun jrk/elfeed-show-running-cmd () + (let ((cmd browse-url-generic-program) + (args browse-url-generic-args) + (format-str "opening with %s") + (arg-str "")) + (dolist (arg args) + (setf arg-str (concat arg-str " " arg))) + (message (format format-str + (concat cmd arg-str))))) + +(defun jrk/clear-browse-url-progam () + (setq browse-url-generic-program nil) + (setq browse-url-generic-args nil)) + +(defun jrk/elfeed-show-open-mpv () + (interactive) + (setq browse-url-generic-program jrk/mpv-cmd) + (jrk/elfeed-show-running-cmd) + (elfeed-show-visit 1) + (jrk/clear-browse-url-progam)) + +(defun jrk/elfeed-search-open-mpv () + (interactive) + (setq browse-url-generic-program jrk/mpv-cmd) + (jrk/elfeed-show-running-cmd) + (elfeed-search-browse-url 1) + (jrk/clear-browse-url-progam)) + +(defun jrk/elfeed-show-open-ytdlp () + (interactive) + (setq browse-url-generic-program jrk/ytdlp-cmd) + (setq browse-url-generic-args jrk/ytdlp-cmd-args) + (jrk/elfeed-show-running-cmd) + (elfeed-show-visit 1) + (jrk/clear-browse-url-progam)) + +(defun jrk/elfeed-search-open-ytdlp () + (interactive) + (setq browse-url-generic-program jrk/ytdlp-cmd) + (setq browse-url-generic-args jrk/ytdlp-cmd-args) + (jrk/elfeed-show-running-cmd) + (elfeed-search-browse-url 1) + (jrk/clear-browse-url-progam)) + +(use-package elfeed + :ensure t + :bind + (("C-c r" . elfeed) + :map elfeed-show-mode-map + ("m" . jrk/elfeed-show-open-mpv) + ("d" . jrk/elfeed-show-open-ytdlp) + + :map elfeed-search-mode-map + ("m" . jrk/elfeed-search-open-mpv) + ("d" . jrk/elfeed-search-open-ytdlp) + + ) + :config + (setq elfeed-feeds + '( + ("https://www.youtube.com/feeds/videos.xml?channel_id=UCLtREJY21xRfCuEKvdki1Kw" youtube) + ("https://www.youtube.com/feeds/videos.xml?channel_id=UCqNpjt_UcMPgm_9gphZgHYA" youtube) + ("https://www.youtube.com/feeds/videos.xml?channel_id=UCk9RA3G-aVQXvp7-Q4Ac9kQ" youtube) + + ("https://suckless.org/atom.xml" suckless news) + ("https://www.gentoo.org/feeds/news.xml" gentoo news) + ) + )) + +(defun send-cmd-to-geiser-repl (cmd) + "Sends a cmd to the current geiser repl" + (geiser-repl--switch-to-repl) + (geiser-repl--send cmd)) + +(defun geiser-load-current-buffer-in-repl () + "Loads current buffer into the current geiser repl" + (interactive) + (send-cmd-to-geiser-repl (concat ",load " (buffer-file-name)))) + +;; Startup time +;; (defun efs/display-startup-time () +;; (message +;; "Emacs loaded in %s with %d garbage collections." +;; (format +;; "%.2f seconds" +;; (float-time +;; (time-subtract after-init-time before-init-time))) +;; gcs-done)) +;; (add-hook 'emacs-startup-hook #'efs/display-startup-time) -- cgit v1.2.3