;;; emacs init --- an init for emacs -*- lexical-binding: t; -*- ;; by C. Duckworth ;; URL: https://git.acdw.net/emacs ;; Bankruptcy: 9 ;; ;; Everyone is permitted to do whatever they like with this software ;; without limitation. This software comes without any warranty ;; whatsoever, but with two pieces of advice: ;; - Be kind to yourself. ;; - Make good choices. (yoke +emacs (locate-user-emacs-file "lisp/") (require '+emacs) ;; Settings (setq truncate-string-ellipsis "…" ring-bell-function #'ignore read-file-name-completion-ignore-case t) ;; Keys (define-keys (current-global-map) "C-x C-k" #'kill-current-buffer "C-/" #'undo-only "C-?" #'undo-redo "C-x C-c" #'+save-buffers-quit "M-SPC" #'+cycle-spacing "M-/" #'hippie-expand "M-=" #'count-words "C-x C-b" #'ibuffer "C-x 4 n" #'clone-buffer "S-" #'mouse-set-mark "C-x 0" #'+delete-window-or-bury-buffer "M-j" nil "" nil) ;; Hooks (add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p) (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode) (add-hook 'find-file-not-found-functions #'+auto-create-missing-dirs) ;; Advice (add-function :after after-focus-change-function #'+save-some-buffers-debounce) (advice-add 'keyboard-escape-quit :around #'keyboard-escape-quit-keep-window-open) (define-advice keyboard-escape-quit (:around (fn &rest r)) "Don't close quits on `keyboard-escape-quit'." (let ((buffer-quit-function #'ignore)) (apply fn r))) ;; Themes (load-theme 'modus-operandi) (set-face-attribute 'default nil :family "Comic Code" :height 100) (set-face-attribute 'variable-pitch nil :family "Comic Code" :height 100)) (yoke isearch nil (define-keys (current-global-map) "C-s" #'isearch-forward-regexp "C-r" #'isearch-backward-regexp "C-M-s" #'isearch-forward "C-M-r" #'isearch-backward)) (yoke auth-source nil (setq auth-sources `(default "secrets:passwords")) (setq-local-hook authinfo-mode-hook truncate-lines t)) (yoke consult "https://github.com/minad/consult" (require 'consult) (setq register-preview-delay 0 register-preview-function #'consult-register-format xref-show-xrefs-function #'consult-xref tab-always-indent 'complete completion-in-region-function #'consult-completion-in-region consult-narrow-key "<" consult--regexp-compiler #'consult--default-regexp-compiler) (advice-add #'register-preview :override #'consult-register-window) (define-keys (current-global-map) ;; C-c bindings (mode-specific-map) "C-c h" #'consult-history "C-c m" #'consult-mode-command "C-c b" #'consult-bookmark "C-c k" #'consult-kmacro ;; C-x bindings (ctl-x-map) "C-x M-:" #'consult-complex-command "C-x b" #'consult-buffer "C-x 4 b" #'consult-buffer-other-window "C-x 5 b" #'consult-buffer-other-frame ;; Custom M-# bindings for fast register access "M-#" #'consult-register-load "M-'" #'consult-register-store "C-M-#" #'consult-register ;; Other custom bindings "M-y" #'consult-yank-pop ;;(" a" . consult-apropos) ;; M-g bindings (goto-map) "M-g e" #'consult-compile-error "M-g f" #'consult-flymake ; or consult-flycheck "M-g g" #'consult-goto-line "M-g M-g" #'consult-goto-line "M-g o" #'consult-outline ; or consult-org-heading "M-g m" #'consult-mark "M-g k" #'consult-global-mark "M-g i" #'consult-imenu "M-g M-i" #'consult-imenu "M-g I" #'consult-imenu-multi ;; M-s bindings (search-map) "M-s f" #'consult-find "M-s F" #'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 m" #'consult-multi-occur "M-s k" #'consult-keep-lines "M-s u" #'consult-focus-lines ;; Isearch integration "M-s e" #'consult-isearch-history) (eval-after isearch-mode (define-keys isearch-mode-map "M-e" #'consult-isearch-history "M-s e" #'consult-isearch-history "M-s l" #'consult-line "M-s L" #'consult-line-multi)) (eval-after org (define-key org-mode-map (kbd "M-g o") #'consult-org-heading))) (yoke orderless "https://github.com/oantolin/orderless" (require 'orderless) (setq completion-styles '(substring orderless basic) completion-category-defaults nil completion-category-overrides '((file (styles basic partial-completion))) orderless-component-separator #'orderless-escapable-split-on-space)) (yoke vertico "https://github.com/minad/vertico" (require 'vertico) (setq resize-mini-windows 'grow-only vertico-count-format nil vertico-cycle t) (vertico-mode)) (yoke marginalia "https://github.com/minad/marginalia/" (marginalia-mode)) (yoke slime "https://github.com/slime/slime" ;; r7rs-swank (let ((r7rsloc (yoke-git "https://github.com/ecraven/r7rs-swank"))) (cond ((executable-find "chibi-scheme") (defun chibi-scheme-start-swank (file encoding) (format "%S\n\n" `(start-swank ,file))) (setq slime-lisp-implementations (cons `(chibi-scheme ("chibi-scheme" ,(format "-A%s" r7rsloc) "-m" "(chibi-swank)") :init chibi-scheme-start-swank) (bound-and-true-p slime-lisp-implementations))))))) (yoke puni "https://github.com/amaikinono/puni" (puni-global-mode) (electric-pair-mode) (define-keys puni-mode-map "C-)" #'puni-slurp-forward "C-(" #'puni-slurp-backward "C-}" #'puni-barf-forward "C-{" #'puni-barf-backward)) (yoke hungry-delete "https://github.com/nflath/hungry-delete" (setq hungry-delete-chars-to-skip " \t" hungry-delete-join-reluctantly nil) (eval-after hungry-delete (add-to-list* 'hungry-delete-except-modes 'eshell-mode 'nim-mode 'python-mode)) (defun +hungry-delete-or (hd-fn fn arg) (funcall (if (looking-back (format "[%s]" hungry-delete-chars-to-skip) arg) hd-fn fn) arg)) (define-keys puni-mode-map [remap puni-backward-delete-char] (defun puni@hungry-delete-backward (arg) (interactive "p") (+hungry-delete-or #'hungry-delete-backward #'puni-backward-delete-char arg)) [remap puni-forward-delete-char] (defun puni@hungry-delete-forward (arg) (interactive "p") (+hungry-delete-or #'hungry-delete-forward #'puni-forward-delete-char arg))) (global-hungry-delete-mode)) (yoke cape "https://github.com/minad/cape" (defun cape-insinuate () (add-to-list* 'completion-at-point-functions #'cape-dabbrev #'cape-file)) (add-hook* '(text-mode-hook prog-mode-hook) #'cape-insinuate)) (yoke minions "https://github.com/tarsius/minions" (minions-mode)) (yoke magit "https://github.com/magit/magit" :load (locate-user-emacs-file "yoke/magit/lisp") :depends ((transient "https://github.com/magit/transient" (locate-user-emacs-file "yoke/transient/lisp")) (dash "https://github.com/magnars/dash.el") (with-editor "https://github.com/magit/with-editor" (locate-user-emacs-file "yoke/with-editor/lisp"))) (autoload #'transient--with-suspended-override "transient") (autoload #'magit "magit" nil :interactive)) (yoke visual-fill-column "https://codeberg.org/joostkremers/visual-fill-column" (setq visual-fill-column-center-text t) (add-hook* 'visual-fill-column-mode-hook #'visual-line-mode) (advice-add 'text-scale-adjust :after #'visual-fill-column-adjust)) (yoke org "https://git.savannah.gnu.org/git/emacs/org-mode.git" :load (locate-user-emacs-file "yoke/org/lisp/") :depends ((org-contrib "https://git.sr.ht/~bzg/org-contrib" (locate-user-emacs-file "yoke/org-contrib/lisp"))) ;; DON'T load system org (setq load-path (cl-remove-if (lambda (path) (string-match-p "lisp/org\\'" path)) load-path)) (setq org-adapt-indentation nil org-auto-align-tags t org-archive-mark-done t org-fold-catch-invisible-edits 'show-and-error org-clock-clocked-in-display 'mode-line org-clock-frame-title-format (cons '(t org-mode-line-string) (cons " --- " frame-title-format)) org-clock-string-limit 7 ; just the clock bit ;; org-clock-string-limit 25 ; gives enough information org-clock-persist nil org-confirm-babel-evaluate nil org-cycle-separator-lines 0 org-directory (sync/ "org/" t) org-ellipsis (or truncate-string-ellipsis "…") org-fontify-done-headline t org-fontify-quote-and-verse-blocks t org-fontify-whole-heading-line t org-hide-emphasis-markers t org-html-coding-system 'utf-8-unix org-image-actual-width (list (* (window-font-width) (- fill-column 8))) org-imenu-depth 3 org-indent-indentation-per-level 0 org-indent-mode-turns-on-hiding-stars nil org-insert-heading-respect-content t org-list-demote-modify-bullet '(("-" . "+") ("+" . "-")) org-log-done 'time org-log-into-drawer t org-num-skip-commented t org-num-skip-unnumbered t org-num-skip-footnotes t org-outline-path-complete-in-steps nil org-pretty-entities t org-pretty-entities-include-sub-superscripts nil org-refile-targets '((nil . (:maxlevel . 2)) (org-agenda-files . (:maxlevel . 1))) org-refile-use-outline-path 'file org-special-ctrl-a/e t org-special-ctrl-k t org-src-fontify-natively t org-src-tab-acts-natively t org-src-window-setup 'current-window org-startup-truncated nil org-startup-with-inline-images t org-tags-column -77 ;; (- (- fill-column 1 (length org-ellipsis))) org-todo-keywords '((sequence "TODO(t)" "WAIT(w@/!)" "ONGOING(o@)" "|" "DONE(d!)" "ASSIGNED(a@/!)") (sequence "|" "CANCELED(k@)") (sequence "MEETING(m)")) org-use-speed-commands t org-emphasis-alist '(("*" org-bold) ("/" org-italic) ("_" org-underline) ("=" org-verbatim) ("~" org-code) ("+" org-strikethrough))) ;; (setq org-todo-keywords ;; '((sequence ;; "TODO(t)" ;; "NEXT(n!)" ; next action ;; "DONE(d)" ; done) ;; (sequence ;; "WAIT(w@)" ; waiting to be actionable again ;; "HOLD(h@/!)" ; actinable, but will do later ;; "IDEA(i)" ; maybe someday ;; "KILL(k@/!)" ; cancelled, aborted or is no longer applicable ;; )))))) (add-hook* 'org-mode-hook #'variable-pitch-mode #'visual-fill-column-mode #'turn-off-auto-fill #'org-indent-mode #'prettify-symbols-mode #'abbrev-mode) (eval-after org (require '+org) (define-keys org-mode-map "C-M-k" #'kill-paragraph "C-M-t" #'transpose-paragraphs) (org-clock-persistence-insinuate))) (yoke org-agenda nil (setq org-agenda-skip-deadline-if-done t org-agenda-skip-scheduled-if-done t org-agenda-span 10 org-agenda-block-separator ?─ org-agenda-time-grid '((daily today require-timed) (800 1000 1200 1400 1600 1800 2000) " ┄┄┄┄┄ " "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄") org-agenda-current-time-string "← now ─────────────────────────────────────────────────" org-agenda-include-diary nil ; I use the org-diary features org-agenda-todo-ignore-deadlines 'near org-agenda-todo-ignore-scheduled 'future org-agenda-include-deadlines t org-deadline-warning-days 0 org-agenda-show-future-repeats 'next org-agenda-window-setup 'current-window) (setq-local-hook org-agenda-mode-hook truncate-lines t) (add-hook 'org-agenda-after-show-hook #'org-narrow-to-subtree)) (yoke ox nil ; org-export (eval-after org (require 'ox)) (eval-after ox (require '+ox) (require 'ox-md nil :noerror) (+org-export-pre-hooks-insinuate)) (setq org-export-coding-system 'utf-8-unix org-export-headline-levels 8 org-export-with-drawers nil org-export-with-section-numbers nil org-export-with-smart-quotes t org-export-with-sub-superscripts t org-export-with-toc nil)) (yoke _work (sync/ "emacs/private") :depends ((+org-capture (locate-user-emacs-file "lisp")) (private (locate-user-emacs-file "lisp")) (bbdb "https://git.savannah.nongnu.org/git/bbdb.git" (locate-user-emacs-file "yoke/bbdb/lisp")) (bbdb-vcard "https://github.com/tohojo/bbdb-vcard/")) (require 'bbdb) (require 'private) (require '_work) (bbdb-initialize 'gnus 'message) (setq bbdb-complete-mail-allow-cycling t)) (yoke org-taskwise "https://codeberg.org/acdw/org-taskwise.el") (yoke titlecase "https://codeberg.org/acdw/titlecase.el" (eval-after org (require 'titlecase)) (eval-after titlecase (require '+titlecase) (add-to-list* 'titlecase-skip-words-regexps (rx word-boundary (+ (any upper digit)) word-boundary)))) (yoke flyspell-correct "https://github.com/duckwork/flyspell-correct" (eval-after flyspell (require 'flyspell-correct) (require '+flyspell-correct) (define-keys flyspell-mode-map "C-;" #'flyspell-correct-wrapper "" #'+flyspell-correct-buffer)) (add-hook 'org-mode-hook #'flyspell-mode) (setq flyspell-correct--cr-key ";"))