;;; -*- 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))) (load-theme 'gruber-darker t) (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" . "https://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)) (use-package ef-themes :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)) (use-package orderless :ensure t :custom (completion-styles '(orderless basic)) (completion-category-overrides '((file (styles basic partial-completion))))) (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 nil :after (org) :config (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))) (use-package org-bullets :ensure t :after (org)) ;; :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))) (use-package web-mode :ensure t) ;; :hook ;; (web-mode . (lambda () ;; (setq tab-width 2 ;; web-mode-style-padding 2 ;; web-mode-script-padding 2 ;; web-mode-markup-indent-offset 2 ;; web-mode-code-indent-offset 2 ;; setq web-mode-css-indent-offset 2)))) (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 "./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)