From 43bed1f97e6f1a229553d7a25dc437741326772e Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Wed, 10 May 2023 13:08:35 -0500 Subject: Bankruptcy 10 --- init.el | 1623 ++++++++++++++++++--------------------------------------------- 1 file changed, 467 insertions(+), 1156 deletions(-) (limited to 'init.el') diff --git a/init.el b/init.el index 707125e..4648042 100644 --- a/init.el +++ b/init.el @@ -1,1163 +1,474 @@ -;;; init.el --- An Emacs of one's own -*- lexical-binding: t -*- +;;; Emacs init.el -*- lexical-binding: t; -*- +;; by Case Duckworth +;; Bankruptcy 10: "Annoyance" -;; Author: Case Duckworth , with inspo from many others -;; Homepage: https://git.acdw.net/emacs -;; Config-Requires: ((emacs "29.0")) -;; Bankruptcy: 9.4 +;;; Commentary: -;; This configuration is Free Software. Everyone is permitted to do whatever -;; they want with it, without limitation. This software comes without any -;; warranty whatsoever, but with two pieces of advice: +;; This is my Emacs configuration. There are many like it but this +;; one is mine. ;; -;; - Don't hurt others. -;; - Make good choices. - -;;; Code: - -(load (locate-user-emacs-file "basics")) ; super basic stuff - - -;;; Built-ins - -(use-package emacs ; Misc. config - :config - (setq recenter-positions '(top middle bottom) - initial-major-mode 'lisp-interaction-mode - initial-scratch-message ";; Emacs!\n\n" - ;; (format "%s\n\n" - ;; (mapconcat (lambda (s) (format ";; %s" s)) - ;; (process-lines "fortune" "-s") - ;; "\n")) - eval-expression-print-level nil - eval-expression-print-length nil - x-select-enable-clipboard-manager nil) - ;; TODO: move this ... elsewhere - (setq mode-line-format - '("%e" - mode-line-front-space - ;; (:propertize ("" mode-line-mule-info - ;; mode-line-client - ;; mode-line-modified - ;; mode-line-remote) - ;; display (min-width (5.0))) - ("" mode-line-mule-info +;; For the tenth time! + +;;; Packages + +(require 'package) +(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) +(package-initialize) + +(dolist (pkg `(consult + marginalia + visual-fill-column + adaptive-wrap + geiser + ,(when (executable-find "csi") 'geiser-chicken) + avy + zzz-to-char + hungry-delete + undohist + jinx)) + (when (and pkg (not (package-installed-p pkg))) + (unless (ignore-errors (package-install pkg)) + (package-refresh-contents) + (package-install pkg)))) + +(load (locate-user-emacs-file "definitions")) +(load (locate-user-emacs-file "packages")) +(load (locate-user-emacs-file "private")) + +(setopt custom-file (locate-user-emacs-file "custom.el")) +(load custom-file :noerror) + +;;; General keybinding changes + +(keymap-global-set "M-o" #'other-window-or-switch-buffer) + +(keymap-global-set "M-SPC" #'cycle-spacing@) + +(keymap-global-set "M-u" #'universal-argument) +(keymap-set universal-argument-map "M-u" #'universal-argument-more) + +;;; Theme + +(if (daemonp) + (add-hook 'server-after-make-frame-hook #'first-frame@set-fonts) + (run-with-idle-timer 1 nil #'first-frame@set-fonts)) + +(tool-bar-mode -1) + +(load-theme 'modus-vivendi :no-confirm :no-enable) +(load-theme 'modus-operandi :no-confirm) + +(add-hook 'text-mode-hook #'visual-line-mode) + +;;; Mode line + +(defvar mode-line-position + '("" + (:eval (if line-number-mode "%3l" "")) + (:eval (if column-number-mode + (if column-number-indicator-zero-based + "/%2c" + "/%2C") + "")) + " (" (-3 "%p") ") ")) + +(setopt mode-line-format + '(("%e" mode-line-front-space mode-line-client mode-line-modified - mode-line-remote) - mode-line-frame-identification - mode-line-buffer-identification - " " - mode-line-position - (vc-mode vc-mode) - " " - minions-mode-line-modes - mode-line-misc-info - mode-line-end-spaces)) - (keymap-global-unset "C-\\") - (keymap-global-unset "") - (setf (alist-get "\\*Compile-Log\\*" display-buffer-alist nil nil #'equal) - '(display-buffer-no-window)) - ;; (add-hook 'after-init-hook - ;; (defun global-mode-string@setup () - ;; (defvar jabber-activity-mode-string) - ;; (defvar org-mode-line-string) - ;; (defvar display-time-mode) - ;; (defvar display-time-string) - ;; (setf global-mode-string - ;; '((t jabber-activity-mode-string) - ;; org-mode-line-string - ;; (display-time-mode display-time-string))))) - (keymap-global-set "C-c t" - (define-keymap - :prefix 'toggle-map - "e" #'toggle-debug-on-error - "q" #'toggle-debug-on-quit - "c" #'column-number-mode - "l" #'line-number-mode - "L" #'display-line-numbers-mode))) - -(use-package faces - :config - (add-hook 'server-after-make-frame-hook - (defun first-frame@set-fonts () - (remove-hook 'server-after-make-frame-hook - #'first-frame@set-fonts) - (face-spec-set 'default - `((t :family ,(find-font - "Recursive Mono Casual Static" - "Comic Code" - "DejaVu Sans Mono") - :height 110))) - (face-spec-set 'fixed-pitch - `((t :family ,(find-font - "Recursive Mono Linear Static" - "Comic Code" - "DejaVu Sans Mono") - :height 1.0))) - (face-spec-set 'variable-pitch - `((t :family ,(find-font - "Recursive Sans Casual Static" - "Atkinson Hyperlegible" - "DejaVu Serif") - :height 1.0))) - (face-spec-set 'font-lock-comment-face - `((t :slant italic - :inherit variable-pitch))) - ;; Emojis - (cl-loop with ffl = (font-family-list) - for font in '("Noto Emoji" "Noto Color Emoji" - "Segoe UI Emoji" "Apple Color Emoji" - "FreeSans" "FreeMono" "FreeSerif" - "Unifont" "Symbola") - if (member font ffl) - do (set-fontset-font t 'symbol font)) - ;; International scripts - (cl-loop with ffl = (font-family-list) - for (charset . font) - in '((latin . "Noto Sans") - (han . "Noto Sans CJK SC Regular") - (kana . "Noto Sans CJK JP Regular") - (hangul . "Noto Sans CJK KR Regular") - (cjk-misc . "Noto Sans CJK KR Regular") - (khmer . "Noto Sans Khmer") - (lao . "Noto Sans Lao") - (burmese . "Noto Sans Myanmar") - (thai . "Noto Sans Thai") - (ethiopic . "Noto Sans Ethiopic") - (hebrew . "Noto Sans Hebrew") - (arabic . "Noto Sans Arabic") - (gujarati . "Noto Sans Gujarati") - (devanagari . "Noto Sans Devanagari") - (kannada . "Noto Sans Kannada") - (malayalam . "Noto Sans Malayalam") - (oriya . "Noto Sans Oriya") - (sinhala . "Noto Sans Sinhala") - (tamil . "Noto Sans Tamil") - (telugu . "Noto Sans Telugu") - (tibetan . "Noto Sans Tibetan")) - if (member font ffl) - do (set-fontset-font t charset font)))) - (unless (daemonp) - (run-with-idle-timer 1 nil #'first-frame@set-fonts))) - -(use-package text-mode - :config - (add-hook 'text-mode-hook #'abbrev-mode)) - -(use-package prog-mode - :config - ;;; TABS - (setq tab-width 8 - sh-indentation tab-width - ) - ;;; Hooks - (add-hook 'prog-mode-hook #'auto-fill-mode) - (add-hook 'prog-mode-hook - (defun prog@indent-tabs-maybe () - (indent-tabs-mode - (if (derived-mode-p 'emacs-lisp-mode - 'lisp-mode - 'scheme-mode - 'python-mode - 'haskell-mode) - -1 1)))) - (global-prettify-symbols-mode)) - -(use-package auth-source - :config - (setq auth-sources '(default "secrets:passwords")) - (add-hook 'auth-info-hook #'truncate-lines-local-mode)) - -(use-package fringe - :config - (fringe-mode '(nil . 0))) - -(use-package ispell - :config - (setq ispell-program-name (choose-executable "aspell" "ispell")) - ;; (add-hook 'before-save-hook - ;; #'+ispell-move-buffer-words-to-dir-locals-hook) - (put 'ispell-buffer-session-localwords 'safe-local-variable - '+ispell-safe-local-p)) - -(use-package dired - :bind (("C-x C-j" . dired-jump) - ([remap list-directory] . dired) - :map dired-mode-map - ("C-j" . dired-up-directory) - ("" . dired-up-directory)) - :config - (require 'dired-x) - (setq dired-recursive-copies 'always - dired-recursive-deletes 'always - dired-create-destination-dirs 'always - dired-do-revert-buffer t - dired-hide-details-hide-symlink-targets nil - dired-isearch-filenames 'dwim - delete-by-moving-to-trash t - dired-auto-revert-buffer t - dired-listing-switches "-AlFhv --group-directories-first" - ls-lisp-dirs-first t - dired-ls-F-marks-symlinks t - dired-clean-confirm-killing-deleted-buffers nil - dired-no-confirm '(byte-compile - load chgrp chmod chown - copy move hardlink symlink - shell touch) - dired-dwim-target t) - (add-hook 'dired-mode-hook #'dired-hide-details-mode) - (add-hook 'dired-mode-hook #'hl-line-mode) - (add-hook 'dired-mode-hook #'truncate-lines-local-mode)) - -(use-package dictionary - :custom - (dictionary-server (if (or (executable-find "dictd") - (file-exists-p "/usr/sbin/dictd")) ; debian - "localhost" - "dict.org")) - :bind - (("C-c w d" . dictionary-search)) - :config - (setf (alist-get "\\*Dictionary\\*" display-buffer-alist nil nil #'equal) - '(display-buffer-in-side-window - (window-width . 80) - (side . right)))) - -(use-package calendar - :custom - (diary-file (private/ "diary"))) - -(use-package mouse - :config - (setq context-menu-functions '(context-menu-undo - context-menu-region - context-menu-middle-separator - context-menu-local - context-menu-minor)) - (context-menu-mode)) - -(use-package password-cache - :config - (setq password-cache t - password-cache-expiry 3600)) - -(use-package time - :config - (setq display-time-format " %H:%M" - display-time-interval 60 - display-time-use-mail-icon t - display-time-mail-function - (defun +notmuch-new-mail-p () - (plist-get (cl-find "inbox+unread" - (ignore-errors - (notmuch-hello-query-counts notmuch-saved-searches)) - :key (lambda (l) (plist-get l :name)) - :test #'equal) - :count)) - display-time-default-load-average nil) - (with-eval-after-load 'notmuch - (add-hook 'notmuch-after-tag-hook #'display-time-update)) - ;; (display-time-mode) - ) - -(use-package tab-bar - :config - (setq tab-bar-show t - tab-bar-close-button-show t) - (setopt tab-bar-format - `(tab-bar-format-history - tab-bar-format-tabs - tab-bar-separator - tab-bar-format-add-tab - tab-bar-format-align-right - ,(defun tab-bar-extra-info () - `((global menu-item - ,(format-mode-line - '((jabber-activity-mode jabber-activity-mode-string) - (:eval (when (and (fboundp 'org-clocking-p) - (org-clocking-p)) - (format " %s" - (truncate-string-to-width - org-mode-line-string - 16 - nil - nil - (truncate-string-ellipsis))))) - (:eval (tmr-mode-line)) - (display-time-mode - (:eval (format " %s" (string-trim display-time-string)))) - ("" " "))) - ignore)))) - mode-line-misc-info (cl-delete-if (lambda (x) - (eq (car x) 'global-mode-string)) - mode-line-misc-info)) - (if (daemonp) - (add-hook 'server-after-make-frame-hook - (defun after-frame@tab-bar () - (tab-bar-mode) - (remove-hook 'server-after-make-frame-hook - #'after-frame@tab-bar))) - (run-with-idle-timer 2 nil #'tab-bar-mode))) - -(use-package info - :preface - (defun Info-copy-current-node-name-0 () - "Call `Info-copy-current-node-name' with a 0 prefix arg." - (interactive) - (Info-copy-current-node-name 0)) - :bind (:map Info-mode-map - ("w" . Info-copy-current-node-name-0) - ("c" . Info-copy-current-node-name))) - -(use-package make-mode - :defer t - :config - (add-hook 'makefile-mode-hook - (defun make-mode@setup () - (remove-hook 'write-file-functions - #'makefile-warn-suspicious-lines t) - (remove-hook 'write-file-functions - #'makefile-warn-continuations t)))) - -(use-package eglot - :preface - (defun +eglot-eldoc () - ;; https://www.masteringemacs.org/article/seamlessly-merge-multiple-documentation-sources-eldoc - (setq eldoc-documentation-strategy #'eldoc-documentation-compose-eagerly)) - :hook - ((bash-ts-mode . eglot-ensure) - (scheme-mode . eglot-ensure)) - :config - (add-to-list 'eglot-server-programs - '(scheme-mode . ("chicken-lsp-server"))) - (add-hook 'eglot-managed-mode #'+eglot-eldoc)) - -(use-package eldoc - :config - (setq eldoc-documentation-strategy #'eldoc-documentation-compose-eagerly) - (setf (alist-get "^\\*eldoc for" display-buffer-alist nil nil #'equal) - '(display-buffer-at-bottom - (window-height . 4))) - (eldoc-add-command-completions "paredit-")) - -(use-package pulse - :config - (setq pulse-flag nil - pulse-delay 1 - pulse-iterations 1)) - -(use-package flyspell - :hook (org-mode-hook)) - -;; (use-package display-fill-column-indicator -;; :hook (prog-mode-hook)) - -(use-package package - :config - (defun package-update-async-in-progress (&rest _) - (message "Package async update in progress.")) - - (defun package-update-all-async () - "Update packages asyncronously." - (interactive) - (let ((message "Package update (async)...") - (disable-fns '(package-update - package-update-all - package-update-all-async))) - (dolist (fn disable-fns) - (advice-add fn :override #'package-update-async-in-progress)) - (message "%s" message) - (unwind-protect - (async-start - `(lambda () - (package-initialize) - (package-update-all)) - `(lambda (result) - (message "%s %s" ,message result))) - (dolist (fn ',disable-fns) - (advice-remove fn 'package-update-async-in-progress)))))) - -(use-package ielm - ;; https://www.n16f.net/blog/making-ielm-more-comfortable/ - :preface - (defun +ielm-init-history () - (let ((path (etc/ "ielm/history" t))) - (setq-local comint-input-ring-file-name path)) - (setq-local comint-input-ring-size 10000) - (setq-local comint-input-ignoredups t) - (ignore-errors (comint-read-input-ring))) - (defun +ielm-write-history (&rest _args) - (with-file-modes #o600 - (comint-write-input-ring))) - (defun +ielm (&optional buf-name) - "Interactively evaluate Emacs Lisp expressions. -Switches to the buffer named BUF-NAME if provided (`*ielm*' by default), -or creates it if it does not exist. -See `inferior-emacs-lisp-mode' for details." - (interactive) - (let (old-point - (buf-name (or buf-name "*ielm*"))) - (unless (comint-check-proc buf-name) - (with-current-buffer (get-buffer-create buf-name) - (unless (zerop (buffer-size)) (setq old-point (point))) - (inferior-emacs-lisp-mode))) - (pop-to-buffer buf-name) - (when old-point (push-mark old-point)))) - :bind (:map emacs-lisp-mode-map - ("C-c C-z" . +ielm)) - :config - (add-hook 'ielm-mode-hook #'eldoc-mode) - (add-hook 'ielm-mode-hook #'+ielm-init-history) - (advice-add 'ielm-send-input :after #'+ielm-write-history)) - -(use-package elec-pair - :config - (setopt electric-pair-skip-whitespace 'chomp) - (electric-pair-mode)) - -(use-package bookmark - :config - (setopt bookmark-save-flag 1)) - -(use-package sh-script - :config - (sh-electric-here-document-mode -1)) - -(use-package cc-mode - :config - (setopt c-basic-offset 8)) - - -;;; Applications - -(use-package acdw-mail - :load-path "lisp/" - :demand t - :bind (("C-c n" . +notmuch-goto))) - -(use-package acdw-org - :load-path "lisp/" - :config - (global-set-key [f8] #'org-clock-out)) - -(use-package acdw-shell - :load-path "lisp/") - -(use-package acdw-web - :load-path "lisp/") - -(use-package acdw-chat - :load-path "lisp/") - -(use-package _work - :load-path "~/sync/emacs/private/") - - -;;; Locally-developed packages - -(use-package +scratch - :load-path "lisp/" - :config - (setq +scratch-save-dir (sync/ "emacs/scratch.d/" t)) - (add-hook 'kill-buffer-query-functions #'+scratch@immortal) - (add-hook 'kill-emacs-hook #'+scratch-save-on-exit) - (with-current-buffer (get-scratch-buffer-create) - (local-set-key (kbd "C-x C-s") #'+scratch-save)) - ;; Save *scratch* every hour - (run-at-time t (* 60 60) #'+scratch-save "%FT%H%z") - ;; Clean old *scratch* saves every day - (run-at-time t (* 60 60 24) #'+scratch-clean)) - -(use-package pulse-location - :load-path "~/src/pulse-location.el/" - :config - (pulse-location-mode)) - -(use-package emacs ; `modus-themes' isn't a package ... - :config - (setopt modus-themes-mixed-fonts t) - (add-hook 'modus-themes-after-load-theme-hook - (defun +reset-faces () - (dolist (face '(font-lock-regexp-face - font-lock-variable-name-face - font-lock-preprocessor-face - font-lock-remove-face - font-lock-delimiter-face - font-lock-label-face - font-lock-operator-face - font-lock-property-face - font-lock-builtin-face - font-lock-number-face - font-lock-set-face - font-lock-warning-face - font-lock-punctuation-face - font-lock-constant-face - font-lock-type-face - font-lock-function-name-face - font-lock-reference-face - font-lock-negation-char-face - font-lock-misc-punctuation-face - font-lock-escape-face - font-lock-bracket-face)) - (face-spec-set face '((t :foreground unspecified - :background unspecified)))) - (face-spec-set 'font-lock-keyword-face - '((t :foreground unspecified - :background unspecified - :weight bold))) - (face-spec-set 'font-lock-doc-face - '((t :slant italic))))) - (add-hook 'after-init-hook - (defun modus@load () - (+reset-faces) - (pcase (string-trim (shell-command-to-string "darkman get")) - ("light" (load-theme 'modus-operandi t)) - ("dark" (load-theme 'modus-vivendi t)))))) - -(use-package electric-cursor - :load-path "~/src/electric-cursor.el/" - :config - (setq electric-cursor-alist '((overwrite-mode . box) - (t . bar))) - (electric-cursor-mode)) - -(use-package mode-line-bell - :load-path "~/src/mode-line-bell.el/" - :config - (setq mode-line-bell-flash-time 0.25) - (mode-line-bell-mode)) - -(use-package titlecase - :load-path "~/src/titlecase.el/" - :preface - (defun +titlecase-sentence-style-dwim (&optional arg) - "Titlecase a sentence. -With prefix ARG, toggle the value of -`titlecase-downcase-sentences' before sentence-casing." - (interactive "P") - (let ((titlecase-downcase-sentences (if arg (not titlecase-downcase-sentences) - titlecase-downcase-sentences))) - (titlecase-dwim 'sentence))) - (defun +titlecase-org-headings () - (interactive) - (require 'org) - (save-excursion - (goto-char (point-min)) - ;; See also `org-map-tree'. I'm not using that function because I want to - ;; skip the first headline. A better solution would be to patch - ;; `titlecase-line' to ignore org-mode metadata (TODO cookies, tags, etc). - (let ((level (funcall outline-level)) - (org-special-ctrl-a/e t)) - (while (and (progn (outline-next-heading) - (> (funcall outline-level) level)) - (not (eobp))) - (titlecase-region (progn (org-beginning-of-line) (point)) - (progn (org-end-of-line) (point))))))) - :config - (with-eval-after-load 'scule - (keymap-set scule-map "M-t" #'titlecase-dwim))) - -(use-package scule - :load-path "~/src/scule.el/" - :bind-keymap ("M-c" . scule-map) - :init - ;; Use M-u for prefix keys - (keymap-global-set "M-u" #'universal-argument) - (keymap-set universal-argument-map "M-u" #'universal-argument-more)) - -(use-package filldent - :load-path "~/src/filldent.el/" - :bind ("M-q" . filldent-dwim) - :config - (setq filldent-fill-modes '(web-mode))) - -(use-package frowny - :load-path "~/src/frowny.el/" - :config - (global-frowny-mode)) - -(use-package keepassxc-shim - :load-path "~/src/keepassxc-shim.el/" - :config - (keepassxc-shim-activate)) - -(use-package hippie-completing-read - :load-path "~/src/hippie-completing-read.el/" - :bind (("M-/" . hippie-completing-read))) - - -;;; External packages - -(use-package async - :ensure t - :config - ;; https://github.com/jwiegley/emacs-async/issues/64 - ;; (setq message-send-mail-function #'async-smtpmail-send-it) - (dired-async-mode) - (async-bytecomp-package-mode)) - -(use-package trashed - :ensure t) - -(use-package form-feed - :ensure t - :hook (prog-mode-hook)) - -;; (use-package clean-kill-ring -;; :vc (:url "https://github.com/NicholasBHubbard/clean-kill-ring.el") -;; :config -;; (setq clean-kill-ring-prevent-duplicates t) -;; (clean-kill-ring-mode)) - -(use-package minions - :ensure t - :config (minions-mode)) - -(use-package visual-fill-column - :preface - (defcustom visual-fill-column-widen-amount 4 - "Amount to widen `fill-column' by in `visual-fill-column-mode'." - :type 'natnum - :group 'visual-fill-column) - (defun visual-fill-column--widen/narrow-handle-arg (cols) - (cond - ((null cols) visual-fill-column-widen-amount) - ((listp cols) (* visual-fill-column-widen-amount - (1+ (/ (car cols) 4)))) - ((eq '- cols) (- visual-fill-column-widen-amount)) - (:else cols))) - (defun visual-fill-column-widen (&optional cols) - "Widen `fill-column' by COLS, and re-display. -If COLS is missing or nil, widen by -`visual-fill-column-widen-amount'. When called with a plain -\\[universal-argument], multiply that amount by 1 + the amount of -\\[universal-argument]s. If called with a numerical prefix -argument, widen by that number of columns." - (interactive "P") - (let ((cols (visual-fill-column--widen/narrow-handle-arg cols))) - (cl-incf fill-column cols) - (visual-fill-column-adjust) - (message "Fill-column: %s" fill-column))) - (defun visual-fill-column-narrow (&optional cols) - "Narrow `fill-column' by COLS, then redisplay. -The prefix argument is as in `visual-fill-column-widen' but negated." - (interactive "P") - (let ((cols (visual-fill-column--widen/narrow-handle-arg cols))) - (cl-decf fill-column cols) - (visual-fill-column-adjust) - (message "Fill-column: %s" fill-column))) - :ensure t - :config - (setopt visual-fill-column-center-text t - visual-fill-column-extra-text-width '(3 . 3) - visual-fill-column-width (+ fill-column 4)) - (keymap-set toggle-map "v" #'visual-fill-column-mode) - (keymap-set visual-fill-column-mode-map "C-x C->" #'visual-fill-column-widen) - (keymap-set visual-fill-column-mode-map "C-x C-<" #'visual-fill-column-narrow) - (add-hook 'visual-fill-column-mode-hook #'visual-line-mode) - (add-hook 'eww-mode-hook #'visual-fill-column-mode) - (advice-add 'text-scale-adjust :after #'visual-fill-column-adjust)) - -(use-package mlscroll - :ensure t :defer 1 - :after modus-themes - :preface - (define-advice load-theme (:after (&rest _) mlscroll) - (mlscroll-mode -1) - (when (seq-intersection '(modus-vivendi modus-operandi) - custom-enabled-themes) - (modus-themes-with-colors - (setq mlscroll-in-color fg-dim - mlscroll-out-color bg-inactive))) - (run-with-idle-timer 1 nil #'mlscroll-mode)) - :config - (load-theme@mlscroll)) - -(use-package cape - :ensure t - :config - (add-hook 'completion-at-point-functions #'cape-file 90) - (add-hook 'completion-at-point-functions #'cape-dabbrev 91) - (advice-add 'emacs-completion-at-point - :around #'cape-wrap-nonexclusive)) - -(use-package wgrep - :ensure t - :config - (setq wgrep-enable-key (kbd "C-x C-q")) - :bind (:map grep-mode-map - ("C-x C-q" . wgrep-change-to-wgrep-mode))) - -(use-package avy - :ensure t - :bind (("M-j" . avy-goto-char-timer) - :map isearch-mode-map - ("M-j" . avy-isearch)) - :config - (setq avy-background t - avy-keys (string-to-list "asdfghjklqwertyuiopzxcvbnm"))) - -(use-package zzz-to-char - :ensure t - :bind (("M-z" . zzz-to-char))) - -(use-package anzu - :ensure t - :bind (("M-%" . anzu-query-replace-regexp) - ("C-M-%" . anzu-query-replace))) - -(use-package isearch-mb - :ensure t - :config - (setq isearch-lazy-count t - isearch-regexp-lax-whitespace t - search-whitespace-regexp "\\W+" - search-default-mode t ; Search regexp by default - isearch-wrap-pause 'no) - (define-advice isearch-cancel (:before (&rest _) add-search-to-history) - "Add search string to history when canceling." - (unless (equal "" isearch-string) - (isearch-update-ring isearch-string isearch-regexp))) - (define-advice perform-replace (:around (orig &rest r) no-anykey-exit) - "Don't exit replace for any key that's not in `query-replace-map'." - (save-window-excursion - (cl-letf* ((lookup-key-orig (symbol-function 'lookup-key)) - ((symbol-function 'lookup-key) - (lambda (map key &optional accept-default) - (or (apply lookup-key-orig map key accept-default) - (when (eq map query-replace-map) 'help))))) - (apply orig r)))) - ;; Consult - (autoload 'consult-line "consult" nil t) - (autoload 'consult-isearch-history "consult" nil t) - (add-to-list 'isearch-mb--after-exit #'consult-line) - (add-to-list 'isearch-mb--with-buffer #'consult-isearch-history) - (keymap-set isearch-mb-minibuffer-map "M-s l" #'consult-line) - (keymap-set isearch-mb-minibuffer-map "M-r" #'consult-isearch-history) - ;; Anzu - (autoload 'anzu-isearch-query-replace "anzu" nil t) - (autoload 'anzu-isearch-query-replace-regexp "anzu" nil t) - (add-to-list 'isearch-mb--after-exit #'anzu-isearch-query-replace) - (add-to-list 'isearch-mb--after-exit #'anzu-isearch-query-replace-regexp) - (keymap-set isearch-mb-minibuffer-map - "M-%" #'anzu-isearch-query-replace-regexp) - (keymap-set isearch-mb-minibuffer-map - "C-M-%" #'anzu-isearch-query-replace) - (isearch-mb-mode)) - -;; (use-package paredit -;; :ensure t -;; :hook ( emacs-lisp-mode-hook ielm-mode-hook -;; eval-expression-minibuffer-setup-hook -;; lisp-interaction-mode-hook -;; lisp-mode-hook scheme-mode-hook -;; fennel-mode-hook fennel-repl-mode-hook -;; geiser-mode-hook geiser-repl-mode-hook) -;; :config -;; (keymap-set paredit-mode-map "C-j" -;; (defun +paredit-newline () -;; (interactive) -;; (call-interactively -;; (if (derived-mode-p 'lisp-interaction-mode) -;; #'eval-print-last-sexp #'paredit-newline)))) -;; (keymap-unset paredit-mode-map "RET" t) -;; (keymap-unset paredit-mode-map "M-s" t) -;; (keymap-unset paredit-mode-map "M-r" t) -;; (add-to-list 'paredit-space-for-delimiter-predicates -;; (defun paredit@dont-space-@ (endp delimiter) -;; "Don't add a space after @ in `paredit-mode'." -;; (let ((point (point))) -;; (or endp -;; (seq-every-p -;; (lambda (prefix) -;; (and (> point (length prefix)) -;; (let ((start (- point (length prefix))) -;; (end point)) -;; (not (string= (buffer-substring start end) -;; prefix))))) -;; ;; Add strings to this list to inhibit adding a space -;; ;; after them. -;; '(",@"))))))) - -(use-package hungry-delete - :ensure t - :config - (setq hungry-delete-chars-to-skip " \t" + mode-line-remote " " + mode-line-buffer-identification + (vc-mode vc-mode) + " " + (mode-line-position mode-line-position) + mode-line-modes + mode-line-misc-info + mode-line-end-spaces))) + +;; Remove modes from mode-line +(dolist (minor-mode '(frowny-mode + whitespace-mode + hungry-delete-mode)) + (setf (alist-get minor-mode minor-mode-alist) (list "")) + (add-hook (intern (format "%s-hook" minor-mode)) + (lambda () + (setf (alist-get minor-mode minor-mode-alist) (list ""))))) + +;;; Completion & minibuffer + +(setopt icomplete-in-buffer t + icomplete-tidy-shadowed-file-names t) +(fido-vertical-mode) + +(setopt completion-auto-help (not icomplete-mode) + completion-auto-select 'second-tab + completions-header-format nil + completions-max-height 12 + completions-format 'one-column + completion-styles '(basic partial-completion flex) + completion-ignore-case t + read-buffer-completion-ignore-case t + read-file-name-completion-ignore-case t + completions-detailed t + enable-recursive-minibuffers t + file-name-shadow-properties '(invisible t intangible t) + minibuffer-eldef-shorten-default t + minibuffer-prompt-properties '( read-only t + cursor-intangible t + face minibuffer-prompt) + window-resize-pixelwise t + frame-resize-pixelwise t) + +(add-hook 'completion-list-mode-hook #'truncate-lines-mode) +(add-hook 'minibuffer-setup-hook #'truncate-lines-mode) + +;; Up/down when completing in the minibuffer +(define-key minibuffer-local-map (kbd "C-p") #'minibuffer-previous-completion) +(define-key minibuffer-local-map (kbd "C-n") #'minibuffer-next-completion) + +;; Up/down when competing in a normal buffer +(define-key completion-in-region-mode-map (kbd "C-p") #'minibuffer-previous-completion) +(define-key completion-in-region-mode-map (kbd "C-n") #'minibuffer-next-completion) + +(setopt completions-sort #'renz/sort-multi-category) + +(setopt tab-always-indent 'complete) + +(file-name-shadow-mode) +(minibuffer-electric-default-mode) + +(scroll-bar-mode -1) +(menu-bar-mode -1) + +(add-hook 'prog-mode-hook #'indent-tabs-mode-maybe) + +(setopt electric-pair-skip-whitespace 'chomp) +(electric-pair-mode) + +(setopt sh-basic-offset tab-width) + +(keymap-set emacs-lisp-mode-map "C-c C-c" #'eval-defun) +(keymap-set emacs-lisp-mode-map "C-c C-k" #'eval-buffer) +(keymap-set lisp-interaction-mode-map "C-c C-c" #'eval-defun) +(keymap-set lisp-interaction-mode-map "C-c C-k" #'eval-buffer) + +(advice-add 'indent-region :around #'call-with-region-or-buffer) +(advice-add 'tabify :around #'call-with-region-or-buffer) +(advice-add 'untabify :around #'call-with-region-or-buffer) + +(with-eval-after-load 'scheme + (keymap-unset scheme-mode-map "M-o" t) + ;; Comparse "keywords" --- CHICKEN (http://wiki.call-cc.org/eggref/5/comparse) + (put 'sequence* 'scheme-indent-function 1) + (put 'satisfies 'scheme-indent-function 1) + (add-hook 'scheme-mode-hook #'geiser-mode)) +(with-eval-after-load 'geiser-mode + (keymap-set geiser-mode-map "C-c C-k" #'geiser-eval-buffer-and-go) + (keymap-unset geiser-mode-map "C-." t)) + +(setopt visual-fill-column-center-text t + visual-fill-column-width (+ fill-column 2)) +(advice-add 'text-scale-adjust :after #'visual-fill-column-adjust) +(add-hook 'visual-line-mode-hook #'visual-fill-column-mode) +(add-hook 'visual-line-mode-hook #'adaptive-wrap-prefix-mode) + +(setopt major-mode + (lambda () ; guess major mode from buffer name + (unless buffer-file-name + (let ((buffer-file-name (buffer-name))) + (set-auto-mode))))) + +;; Dialogs +(unless (boundp 'use-short-answers) + (fset 'yes-or-no-p 'y-or-n-p)) + +(setopt read-answer-short t + use-dialog-box nil + use-file-dialog nil + use-short-answers t) + +(require 'savehist) +(setopt history-length 1024 + history-delete-duplicates t + ;; savehist-file (etc/ "savehist.el") + savehist-save-minibuffer-history t + savehist-autosave-interval 30) +(savehist-mode) + +;; Killing and yanking +(setopt kill-do-not-save-duplicates t + kill-read-only-ok t + ;; XXX: This setting causes an error message the first time it's + ;; called: "Selection owner couldn't convert: TIMESTAMP". I have + ;; absolutely no idea why I get this error, but it's generated in + ;; `x_get_foreign_selection'. I also can't inhibit the message or + ;; do anything else with it, so for now, I'll just live with the + ;; message. + save-interprogram-paste-before-kill t + yank-pop-change-selection t) +(delete-selection-mode) + +;; Notifying the user +(setopt echo-keystrokes 0.01 + ring-bell-function #'ignore) + +;; Point and mark +(setopt set-mark-command-repeat-pop t) + +;; The system +(setopt read-process-output-max (* 10 1024 1024)) + +;; Startup +(setopt inhibit-startup-screen t + initial-buffer-choice t + initial-scratch-message nil) + +(define-advice startup-echo-area-message (:override ()) + (if (get-buffer "*Warnings*") + ";_;" + "^_^")) + +;; Text editing +(setopt fill-column 80 + sentence-end-double-space nil + tab-width 8 + tab-always-indent 'complete) +(global-so-long-mode) + +(setopt show-paren-delay 0.01 + show-paren-style 'parenthesis + show-paren-when-point-in-periphery t + show-paren-when-point-inside-paren t) +(show-paren-mode) + + +;; Encodings +(set-language-environment "UTF-8") +(setopt buffer-file-coding-system 'utf-8-unix + coding-system-for-read 'utf-8-unix + coding-system-for-write 'utf-8-unix + default-process-coding-system '(utf-8-unix . utf-8-unix) + locale-coding-system 'utf-8-unix) +(set-charset-priority 'unicode) +(prefer-coding-system 'utf-8-unix) +(set-default-coding-systems 'utf-8-unix) +(set-terminal-coding-system 'utf-8-unix) +(set-keyboard-coding-system 'utf-8-unix) +(pcase system-type + ((or 'ms-dos 'windows-nt) + (set-clipboard-coding-system 'utf-16-le) + (set-selection-coding-system 'utf-16-le)) + (_ + (set-selection-coding-system 'utf-8) + (set-clipboard-coding-system 'utf-8))) + + +;; Files +(setopt auto-revert-verbose nil + global-auto-revert-non-file-buffers t + create-lockfiles nil + find-file-visit-truename t + mode-require-final-newline t + view-read-only t + save-silently t) +(global-auto-revert-mode) + +(setopt auto-save-default nil + auto-save-interval 1 + auto-save-no-message t + auto-save-timeout 1 + auto-save-visited-interval 1 + remote-file-name-inhibit-auto-save-visited t) +(add-to-list 'auto-save-file-name-transforms + `(".*" ,(locate-user-emacs-file "auto-save/") t)) +(auto-save-visited-mode) + +(setopt backup-by-copying t + version-control t + kept-new-versions 8 + kept-old-versions 8 + delete-old-versions t) +(setq-default backup-directory-alist + `(("^/dev/shm" . nil) + ("^/tmp" . nil) + (,(getenv "XDG_RUNTIME_DIR") . nil) + ("." . ,(locate-user-emacs-file "backup")))) + +(require 'recentf) +(setopt + recentf-max-menu-items 500 + recentf-max-saved-items nil ; Save the whole list + recentf-auto-cleanup 'mode + recentf-case-fold-search t) +;; (add-to-list 'recentf-exclude etc/) +(add-to-list 'recentf-exclude "-autoloads.el\\'") +(add-hook 'buffer-list-update-hook #'recentf-track-opened-file) +(add-hook 'after-save-hook #'recentf-save-list) +(recentf-mode) + +(require 'saveplace) +(setopt + save-place-forget-unreadable-files (eq system-type + 'gnu/linux)) +(save-place-mode) + +(require 'uniquify) +(setq uniquify-after-kill-buffer-p t + uniquify-buffer-name-style 'forward + uniquify-ignore-buffers-re "^\\*" + uniquify-separator path-separator) + +(setq-local vc-follow-symlinks t + vc-make-backup-files t) + +;; Whitespace +(require 'whitespace) +(setopt whitespace-style + '(face trailing tabs tab-mark)) +(global-whitespace-mode) +(add-hook 'before-save-hook #'delete-trailing-whitespace-except-current-line) + +;; Native compilation +(setopt native-comp-async-report-warnings-errors 'silent + native-comp-deferred-compilation t + native-compile-target-directory + (locate-user-emacs-file "eln")) +(when (boundp 'native-comp-eln-load-path) + (add-to-list 'native-comp-eln-load-path native-compile-target-directory)) +(when (fboundp 'startup-redirect-eln-cache) + (startup-redirect-eln-cache native-compile-target-directory)) + +(global-goto-address-mode) + +;; Winner +(winner-mode) + +;;; Hooks +(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p) +(add-hook 'find-file-not-found-functions #'create-missing-directories) +(add-hook 'find-file-hook #'vc-remote-off) +(add-hook 'dired-mode-hook #'hl-line-mode) +(add-hook 'org-agenda-mode-hook #'hl-line-mode) + +;;; Tab bar + +(defun tab-bar-end-space () + `((end menu-item " " ignore))) + +(setopt tab-bar-show t) +(add-to-list 'tab-bar-format 'tab-bar-format-align-right :append) +(add-to-list 'tab-bar-format 'tab-bar-format-global :append) +(add-to-list 'tab-bar-format 'tab-bar-end-space :append) +(tab-bar-mode) + +;;; Org mode + +(keymap-global-set "C-c a" #'org-agenda) +(setopt org-clock-clocked-in-display 'frame-title + org-clock-frame-title-format + '("%b" " - " (t org-mode-line-string))) + +;;; Spelling + +(defun list-of-strings-p (x) + "Is X a list of strings?" + (and x + (listp x) + (cl-every #'stringp x))) + +(put 'ispell-local-words 'safe-local-variable + 'list-of-strings-p) + +(add-hook 'text-mode-hook #'jinx-mode) +(with-eval-after-load 'jinx + (keymap-set jinx-mode-map "M-$" #'jinx-correct) + (keymap-set jinx-mode-map "C-M-$" #'jinx-languages)) + +;;; Copy rich text to the keyboard + +;; Thanks to Oleh Krehel: +;; https://emacs.stackexchange.com/questions/54292/copy-results-of-org-export-directly-to-clipboard +;; So. Emacs can't do this itself because it doesn't support sending clipboard +;; or selection contents as text/html. We have to use xclip instead. +;; (defun org-to-html-to-clipboard (&rest org-export-args) +;; "Export current org buffer to HTML, then copy it to the clipboard. +;; ORG-EXPORT-ARGS are passed to `org-export-to-file'." +;; (let ((f (make-temp-file "org-html-export"))) +;; (apply #'org-export-to-file 'html f org-export-args) +;; (start-process "xclip" " *xclip*" +;; "xclip" "-verbose" "-i" f +;; "-t" "text/html" "-selection" "clipboard") +;; (message "HTML pasted to clipboard."))) + +;; Wayland version.. TODO: make it work for both +(defun org-to-html-to-clipboard (&rest org-export-args) + "Export current org buffer to HTML, then copy it to the clipboard. +ORG-EXPORT-ARGS are passed to `org-export-to-file'." + (let ((buf (generate-new-buffer "*org-html-clipboard*" t))) + (apply #'org-export-to-buffer 'html buf org-export-args) + (with-current-buffer buf + (call-process-region (point-min) (point-max) + "wl-copy" nil nil nil + "-t" "text/html") + (kill-buffer-and-window)) + (message "HTML copied to clipboard."))) + +(defun org-subtree-to-html-to-clipboard () + "Export current subtree to HTML." + (interactive) + (org-to-html-to-clipboard nil :subtree)) + +(undohist-initialize) + +(require 'hungry-delete) +(setopt hungry-delete-chars-to-skip " \t" hungry-delete-skip-regexp (format "[%s]" hungry-delete-chars-to-skip) hungry-delete-join-reluctantly nil) - (add-to-list 'hungry-delete-except-modes 'eshell-mode) - (add-to-list 'hungry-delete-except-modes 'nim-mode) - (add-to-list 'hungry-delete-except-modes 'python-mode) - ;; Keys - (with-eval-after-load 'paredit - (define-key paredit-mode-map [remap paredit-backward-delete] - (defun paredit/hungry-delete-backward (arg) - (interactive "*p") - (if (looking-back hungry-delete-skip-regexp) - (hungry-delete-backward (or arg 1)) - (paredit-backward-delete arg)))) - (define-key paredit-mode-map [remap paredit-forward-delete] - (defun paredit/hungry-delete-forward (arg) - (interactive "*p") - (if (looking-at hungry-delete-skip-regexp) - (hungry-delete-forward (or arg 1)) - (paredit-forward-delete arg))))) - ;; Mode - (global-hungry-delete-mode)) - -(use-package macrostep - :ensure t - :after elisp-mode - :bind ( :map emacs-lisp-mode-map - ("C-c e" . macrostep-expand) - :map lisp-interaction-mode-map - ("C-c e" . macrostep-expand))) - -(use-package package-lint - :ensure t) - -(use-package sly - :ensure t - :when inferior-lisp-program - :preface - (setq inferior-lisp-program (choose-executable "sbcl")) - (defun +sly-start-or-mrepl () - (interactive) - (if (ignore-errors (sly-connection)) - (sly-mrepl (lambda (buf) - (display-buffer-pop-up-window buf nil))) - (call-interactively #'sly))) - :config - (autoload 'sly-mrepl "sly-mrepl" nil t) - (keymap-set sly-mode-map "C-c C-z" #'+sly-start-or-mrepl) - (setq sly-net-coding-system 'utf-8-unix) - (sly-symbol-completion-mode -1)) - -(use-package pdf-tools - :ensure t - :mode ("\\.[pP][dD][fF]\\'" . pdf-view-mode) - :magic ("%PDF" . pdf-view-mode) - :config - (pdf-tools-install)) - -(use-package keychain-environment - :ensure t - :when (executable-find "keychain") - :hook (after-init-hook . keychain-refresh-environment)) - -(use-package web-mode - :ensure t - :mode ("\\.phtml\\'" - "\\.tpl\\.php\\'" - "\\.[agj]sp\\'" - "\\.as[cp]x\\'" - "\\.erb\\'" - "\\.mustache\\'" - "\\.djhtml\\'" - "\\.html?\\'") - :config - (add-hook 'web-mode-hook - (defun web-mode@setup () - (indent-tabs-mode -1)))) - -(use-package nginx-mode - :ensure t - :mode "/nginx/sites-\\(?:available\\|enabled\\)/") - -(use-package markdown-mode - :ensure t - :mode "\\.\\(?:md\\|markdown\\|mkd\\|mdown\\|mkdn\\|mdwn\\)\\'" - :config - (setq markdown-command (choose-executable - '("pandoc" "--from=markdown" "--to=html5") - "markdown")) - (add-hook 'markdown-mode-hook #'visual-fill-column-mode)) - -(use-package pandoc-mode - :ensure t - :hook ((markdown-mode-hook . pandoc-mode) - (pandoc-mode-hook . pandoc-load-default-settings))) - -(use-package edit-indirect - :ensure - :bind (("C-c '" . edit-indirect-region))) - -(use-package transpose-frame - :ensure t - :bind (("C-x 5 t" . transpose-frame) - ("C-x 5 h" . flop-frame) ; horizontal - ("C-x 5 v" . flip-frame) ; vertical - )) - -(use-package magit - :pin melpa-stable - :ensure t - :bind ("C-x g" . magit)) - -(use-package git-modes - :ensure t) - -(use-package eradio - :ensure t - :preface - (defun eradio-toggle|play (&optional arg) - "Run `eradio-toggle', or `eradio-play' with prefix ARG." - (interactive "P") - (if arg (eradio-play) (eradio-toggle))) - :bind (("C-c r p" . eradio-toggle|play) - ("C-c r s" . eradio-stop)) - :config - (setq eradio-player '("mpv" "--no-video" "--no-terminal") - eradio-channels - ;; (name . url) - '(("Nightwave Plaza" . "http://radio.plaza.one/ogg") - ("Radio Paradise - Main Mix" . - "http://stream.radioparadise.com/rp_192m.ogg") - ("Radio Paradise - Mellow Mix" . - "http://stream.radioparadise.com/mellow-96m.ogg") - ("Radio Paradise - Rock Mix" . - "http://stream.radioparadise.com/rock-96m.ogg") - ("Radio Paradise - Global Mix" . - "http://stream.radioparadise.com/global-96m.ogg") - ("KLSU" . "http://130.39.238.143:8010/stream.mp3")) - ;; At some point I should actually ... write this in to this file or - ;; something. But until I decide to quit using radish altogether, this - ;; what I got. - ;; (with-current-buffer (find-file-noselect "~/etc/radish/stations") - ;; (let (chans) - ;; (dolist (line (string-split (buffer-substring-no-properties - ;; (point-min) (point-max)) - ;; "\n") - ;; chans) - ;; (unless (string-match-p "^#" line) - ;; (let* ((ll (string-split line "\t")) - ;; (url (cl-first ll)) - ;; (name (cl-second ll)) - ;; (tags (cl-third ll))) - ;; (when (and name - ;; (string-match-p "[^ \n\t]*://[^ \n\t]*" url)) - ;; (push (cons (format "%s - %s" name tags) url) - ;; chans))))))) - )) - -(use-package wiki-abbrev - :after org ; Don't need abbrevs til I load org. - :load-path "~/src/wiki-abbrev.el/" - :config - (setq wiki-abbrev-file (etc/ "wiki-abbrevs")) - (wiki-abbrev-insinuate)) - -(use-package flyspell-correct - :ensure t - :preface - (defun +flyspell-correct-buffer (&optional prefix) - "Run `flyspell-correct-wrapper' on all misspelled words in the buffer. -With PREFIX, prompt to change the current dictionary." - (interactive "P") - (flyspell-buffer) - (when prefix - (let ((current-prefix-arg nil)) - (call-interactively #'ispell-change-dictionary))) - (flyspell-correct-move (point-min) :forward :rapid)) - :after flyspell - :bind (("" . +flyspell-correct-buffer) - (:map flyspell-mode-map - ("C-;" . flyspell-correct-wrapper))) - :config - (setq flyspell-correct--cr-key ";") - (keymap-unset flyspell-mode-map "C-," t) - (keymap-unset flyspell-mode-map "C-." t)) - -(use-package dired-subtree - :ensure t - :after dired - :bind (:map dired-mode-map - (("TAB" . dired-subtree-cycle) - ("i" . dired-subtree-toggle)))) - -(use-package dired-hide-dotfiles - ;; I could maybe use a more general package for this ... see - ;; https://emacs.grym.io/#orgbbda609 - :ensure t - :bind (:map dired-mode-map - ("." . dired-hide-dotfiles-mode))) - -(use-package dired-git-info - :ensure t - :bind (:map dired-mode-map - (")" . dired-git-info-mode)) - :config - (setq dgi-auto-hide-details-p nil)) - -(use-package expand-region ; needed for embrace anyway - :ensure t - :bind (("C-=" . er/expand-region))) - -(use-package embrace - :ensure t - :preface - (defmacro org-insert-or-embrace (char) - "Define a function to insert CHAR, or `embrace' the region with it." - (let* ((fn-name (intern (format "org-insert-or-embrace-%s" char))) - (char (cond ((characterp char) char) - ((stringp char) (string-to-char char)) - (t (user-error "Bad format for char: %S" char))))) - `(defun ,fn-name (n) - ,(format "Insert N %ss, or surround the region with them." - (char-to-string char)) - (interactive "p") - (if (region-active-p) - (dotimes (_ n) - (embrace--add-internal (region-beginning) (region-end) ,char) - (forward-char 1)) - (self-insert-command n ,char))))) - (with-eval-after-load 'org - (require 'embrace) - (keymap-set org-mode-map "*" (org-insert-or-embrace "*")) - (keymap-set org-mode-map "/" (org-insert-or-embrace "/")) - (keymap-set org-mode-map "_" (org-insert-or-embrace "_")) - (keymap-set org-mode-map "=" (org-insert-or-embrace "=")) - (keymap-set org-mode-map "~" (org-insert-or-embrace "~")) - (keymap-set org-mode-map "+" (org-insert-or-embrace "+"))) - :bind (("C-'" . embrace-commander)) - :hook ((org-mode-hook . embrace-org-mode-hook) - (ruby-mode-hook . embrace-ruby-mode-hook) - (emacs-lisp-mode-hook . embrace-emacs-lisp-mode-hook) - (latex-mode-hook . embrace-LaTeX-mode-hook))) - -(use-package apheleia - :ensure t - :config - (setq apheleia-hide-log-buffers t) - (setf (alist-get 'shfmt apheleia-formatters) - '("shfmt" "--case-indent")) - (global-set-key (kbd "M-C-\\") - (defun +apheleia-format|indent-buffer () - (interactive) - (if-let ((formatters (apheleia--get-formatters))) - (apheleia-format-buffer - formatters - (lambda () - (with-demoted-errors "Apheleia: %s" - (when buffer-file-name - (let ((apheleia--format-after-save-in-progress t)) - (apheleia--save-buffer-silently))) - (run-hooks 'apheleia-post-format-hook)))) - (indent-region (point-min) (point-max)) - (when buffer-file-name - (save-buffer)))))) - -(use-package php-mode - :ensure t) - -(use-package rec-mode - :ensure t) - - -(use-package geiser - :ensure t - :config - (when (executable-find "guile") - (use-package geiser-guile :ensure t)) - (when (executable-find "chicken") - (use-package geiser-chicken :ensure t)) - (when (or (prog1 (executable-find "chez") - (setopt geiser-chez-binary - (executable-find "chez"))) - (executable-find "petite") - (executable-find "scheme")) - (use-package geiser-chez :ensure t)) - (when (executable-find "gambit") - (use-package geiser-gambit :ensure t)) - (when (executable-find "chibi-scheme") - (use-package geiser-chibi :ensure t)) - (use-package macrostep-geiser - :ensure t - :config - (eval-after-load 'geiser-mode - '(add-hook 'geiser-mode-hook #'macrostep-geiser-setup)) - (eval-after-load 'geiser-repl - '(add-hook 'geiser-repl-mode-hook #'macrostep-geiser-setup))) - (with-eval-after-load 'geiser-mode - (keymap-set geiser-mode-map "C-c C-k" #'geiser-eval-buffer-and-go) - (keymap-unset geiser-mode-map "C-." t) - (keymap-unset scheme-mode-map "M-o" t))) - -(use-package detached - :when (executable-find "dtach") - :ensure t - :init - (add-hook 'after-init-hook #'detached-init) - :bind (([remap async-shell-command] . detached-shell-command) - ([remap compile] . detached-compile) - ([remap recompile] . detached-compile-recompile)) - :config - (setf detached-terminal-data-command system-type) - (with-eval-after-load 'consult - (global-set-key [remap detached-open-session] #'detached-consult-session))) - -(use-package lin - :ensure t - :config - (setq lin-face 'lin-cyan - lin-mode-hooks - '(dired-mode-hook - ;; bongo-mode-hook - ;; elfeed-search-mode-hook - git-rebase-mode-hook - grep-mode-hook - ibuffer-mode-hook - ilist-mode-hook - ;; ledger-report-mode-hook - log-view-mode-hook - magit-log-mode-hook - ;; mu4e-headers-mode-hook - notmuch-search-mode-hook - notmuch-tree-mode-hook - occur-mode-hook - org-agenda-mode-hook - pdf-outline-buffer-mode-hook - proced-mode-hook - tabulated-list-mode-hook)) - (lin-global-mode)) - -(use-package gcmh - :ensure t - :config - (setq gcmh-idle-delay 'auto - gcmh-verbose nil) - (gcmh-mode)) - -(use-package tmr - :ensure t - :preface - (defun tmr-mode-line () - (if (seq-find (lambda (tmr) - (not (tmr--timer-finishedp tmr))) - tmr--timers) - (propertize "⏲" 'face 'font-lock-warning-face) - "")) - ;; (add-to-list 'global-mode-string - ;; '("" (:eval (tmr-mode-line))) - ;; 'append) - ) - -(use-package dumb-jump - :ensure t - :hook ((xref-backend-functions . dumb-jump-xref-activate))) - -(use-package le-thesaurus - :ensure t - :bind (("C-c w s" . le-thesaurus-get-synonyms) - ("C-c w a" . le-thesaurus-get-antonyms))) - -(use-package devdocs - :ensure t - ;; not sure what to bind anything to yet ... so M-x it is - ) - -(use-package comment-dwim-2 - :ensure t - :bind (("M-;" . comment-dwim-2) - :map org-mode-map - ("M-;" . org-comment-dwim-2))) +(add-to-list 'hungry-delete-except-modes 'eshell-mode) +(add-to-list 'hungry-delete-except-modes 'nim-mode) +(add-to-list 'hungry-delete-except-modes 'python-mode) +(global-hungry-delete-mode) + +(setopt avy-background t + avy-keys (string-to-list "asdfghjklqwertyuiopzxcvbnm")) +(keymap-global-set "M-j" #'avy-goto-char-timer) +(keymap-set isearch-mode-map "M-j" #'avy-isearch) +(keymap-global-set "M-z" #'zzz-to-char) + +(marginalia-mode) + +(keymap-global-set "C-x b" #'consult-buffer) +(keymap-global-set "C-x 4 b" #'consult-buffer-other-window) +(keymap-global-set "C-x 5 b" #'consult-buffer-other-frame) +(keymap-global-set "C-x r b" #'consult-bookmark) +(keymap-global-set "M-y" #'consult-yank-pop) +(keymap-global-set "M-g g" #'consult-goto-line) +(keymap-global-set "M-g M-g" #'consult-goto-line) +(keymap-global-set "M-g o" #'consult-outline) +(keymap-global-set "M-g m" #'consult-mark) +(keymap-global-set "M-g i" #'consult-imenu) +(keymap-global-set "M-s d" #'consult-find) +(keymap-global-set "M-s D" #'consult-locate) +(keymap-global-set "M-s g" #'consult-grep) +(keymap-global-set "M-s G" #'consult-git-grep) +(keymap-global-set "M-s r" #'consult-ripgrep) +(keymap-global-set "M-s l" #'consult-line) +(keymap-global-set "M-s k" #'consult-keep-lines) +(keymap-global-set "M-s u" #'consult-focus-lines) + +(keymap-global-set "M-s e" #'consult-isearch-history) +(keymap-set isearch-mode-map "M-e" #'consult-isearch-history) +(keymap-set isearch-mode-map "M-s e" #'consult-isearch-history) +(keymap-set isearch-mode-map "M-s l" #'consult-line) + +(keymap-set minibuffer-local-map "M-n" #'consult-history) +(keymap-set minibuffer-local-map "M-p" #'consult-history) + +(setopt completion-in-region-function #'consult-completion-in-region + xref-show-xrefs-function #'consult-xref + xref-show-definitions-function #'consult-xref) + +(setopt initial-scratch-message ";;; Emacs!\n\n") + +(keymap-global-set "C-x C-b" #'ibuffer) +(add-hook 'ibuffer-hook #'hl-line-mode) -- cgit 1.4.1-21-gabe81