From 06770985d7539afe97747ae4fff7211e6abea94e Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Sat, 4 Sep 2021 10:38:06 -0500 Subject: Sort init.el by package --- init.el | 2813 +++++++++++++++++++++++++++++----------------------------- lisp/acdw.el | 19 +- 2 files changed, 1433 insertions(+), 1399 deletions(-) diff --git a/init.el b/init.el index 60caeaf..4326433 100644 --- a/init.el +++ b/init.el @@ -16,42 +16,12 @@ ;;; Code: -;;; Built-ins ;; NOTE that some of the names in `setup' forms are arbitrary. -(setup (:require auth-source) - (:option auth-sources '("~/.authinfo" "~/.authinfo.gpg"))) - -(setup (:require recentf) - (:option recentf-save-file (acdw/dir "recentf.el") - recentf-max-menu-items 100 - recentf-max-saved-items nil - recentf-auto-cleanup 'mode - (append recentf-exclude) (acdw/dir)) - - (advice-add 'dired-rename-file :after #'rjs/recentf-rename-notify) - - (recentf-mode +1)) - -(setup (:require savehist) - (:option history-length t - history-delete-duplicates t - savehist-autosave-interval 60 - savehist-file (acdw/dir "savehist.el")) - - (dolist (var '(extended-command-history - global-mark-ring - kill-ring - regexp-search-ring - search-ring - mark-ring)) - (add-to-list 'savehist-additional-variables var)) - - (savehist-mode +1)) - -(setup (:require server) - (unless (server-running-p) - (server-start))) +(setup (:straight (0x0 + :host gitlab + :repo "willvaughn/emacs-0x0")) + (:option 0x0-default-server 'ttm)) (setup Info (:hook variable-pitch-mode @@ -73,12 +43,83 @@ (when-let ((default-directory (expand-file-name-exists-p "pkg/" user-emacs-directory))) - (normal-top-level-add-subdirs-to-load-path))) + (normal-top-level-add-subdirs-to-load-path)) + + (defun acdw/sort-setups () + "Sort `setup' forms in the current buffer. +Actually sorts all forms, but based on the logic of `setup'. +AKA, DO NOT USE THIS FUNCTION!!!" + (save-excursion + (sort-sexps (point-min) (point-max) + (lambda (sexp) + (let ((name (cadr sexp))) + (symbol-name (if (listp name) ; this is /terrible/! + (if (keywordp (car name)) + (let ((feature (cadr name))) + (if (listp feature) + (car feature) + feature)) + (car name)) + name)))))))) + +(setup (:straight-if affe + (and (or (executable-find "fd") + (executable-find "find")) + (executable-find "rg"))) + ;; Keys are bound in `acdw/sensible-grep' and `acdw/sensible-find' + (:option affe-regexp-compiler + (defun affe-orderless-regexp-compiler (input _type) + (setq input (orderless-pattern-compiler input)) + (cons input (lambda (str) (orderless--highlight input str)))))) + +(setup (:straight-if ahk-mode + (acdw/system :work))) + +(setup (:straight alert) + (:option alert-default-style (acdw/system + (:home 'libnotify) + (_ 'message)))) + +(setup (:straight (apheleia + :host github + :repo "raxod502/apheleia")) + + (apheleia-global-mode +1) + + ;; Use a dumb formatter on modes that `apheleia' doesn't work for. + (add-hook 'before-save-hook + (defun before-save@dumb-auto-format () + (setq stupid-modes '(makefile-mode + org-mode)) + ;; If there's no apheleia formatter for the mode, just indent the + ;; buffer. + (unless (or (apply #'derived-mode-p stupid-modes) + (and (fboundp 'apheleia--get-formatter-command) + (apheleia--get-formatter-command))) + (indent-region (point-min) (point-max)))))) + +(setup (:straight async) + (dired-async-mode +1) + + (:with-feature dired + (:hook (defun dired@disable-dired-async-mode-line () + (autoload 'dired-async--modeline-mode "dired-async" nil t) + (dired-async--modeline-mode -1))))) + +(setup (:require auth-source) + (:option auth-sources '("~/.authinfo" "~/.authinfo.gpg"))) (setup autorevert (:option global-auto-revert-non-file-buffers t) (global-auto-revert-mode +1)) +(setup (:straight avy) + (:global "C-:" #'avy-goto-char-timer + "C-c C-j" #'avy-resume) + + (:with-feature isearch + (:bind "C-'" #'avy-isearch))) + (setup browse-url (:require acdw-browse-url) @@ -127,6 +168,106 @@ (setup calendar (:option calendar-week-start-day 1)) +(setup (:straight circe) + (require 'circe) + (require 'acdw-irc) + + (:option acdw-irc/left-margin 12 + acdw-irc/post-my-nick "-> " + circe-channel-killed-confirmation nil + circe-color-nicks-everywhere t + circe-default-nick "acdw" + circe-default-part-message "See You, Space Cowpokes . . ." + circe-default-user "acdw" + circe-format-action + (lambda (&rest plist) + (concat + (acdw-irc/margin-format "" "*" "*" t) + " " (plist-get plist :nick) " " (plist-get plist :body))) + circe-format-say + (lambda (&rest plist) + (concat + (acdw-irc/margin-format (plist-get plist :nick) "" " |" t) + " " (plist-get plist :body))) + circe-format-self-action + (lambda (&rest plist) + (concat + (acdw-irc/margin-format "" "-*" " *" t) + " " (plist-get plist :nick) " " (plist-get plist :body))) + circe-format-self-say + (lambda (&rest plist) + (concat + (acdw-irc/margin-format (plist-get plist :nick) "-" " >" t) + " " (plist-get plist :body))) + circe-highlight-nick-type 'sender + circe-network-options + `(("Libera Chat" + :channels ("#emacs" "#systemcrafters" "##webpals") + :sasl-username circe-default-nick + :sasl-password ,(acdw/make-password-fetcher + :host "libera.chat")) + ("Tilde Chat" :host "irc.tilde.chat" :port 6697 :use-tls t + :channels ("#meta" "#bread" "#dadjokes" "#team") + :sasl-username circe-default-nick + :sasl-password ,(acdw/make-password-fetcher + :host "tilde.chat")) + ("Casa" :host "m455.casa" :port 6697 :use-tls t + :channels ("#basement") + :sasl-username circe-default-nick + :sasl-password ,(acdw/make-password-fetcher + :host "m455.casa")) + ("Piss" :host "piss.hmm.st" :port 6697 :use-tls t)) + circe-reduce-lurker-spam t + circe-server-auto-join-default-type :after-auth) + + (custom-set-faces '(circe-nick-highlight-face + ((t (:inherit (modus-themes-hl-line)))) + :now)) + + (:bind "C-c C-p" #'circe-command-PART) + + (:advise circe-command-PART :after + (defun circe-command-PART@kill-buffer (&rest _) + (let ((circe-channel-killed-confirmation nil)) + (kill-buffer)))) + + (:with-mode circe-chat-mode + (:hook #'acdw/stop-paren-annoyances + (defun circe-chat@setup () + (lui-set-prompt + (concat (propertize (acdw-irc/margin-format (buffer-name) + "" + ">") + 'face 'circe-prompt-face + 'read-only t 'intangible t + 'cursor-intangible t) + " ")) + (enable-circe-color-nicks) + (enable-circe-display-images) + (enable-circe-new-day-notifier)))) + + (autoload 'circe-nick-color-reset "circe-color-nicks") + (add-hook 'modus-themes-after-load-theme-hook + #'circe-nick-color-reset) + + (:with-mode lui-mode + (:option lui-fill-column fill-column + lui-fill-type (repeat-string acdw-irc/left-margin " ") + lui-time-stamp-position 'right-margin + lui-time-stamp-format "%H:%M" + lui-track-behavior 'before-switch-to-buffer + lui-track-indicator 'fringe) + + (:hook (defun lui-mode@setup () + (setq-local fringes-outside-margins t + right-margin-width 5 + scroll-margin 0 + word-wrap t + wrap-prefix (repeat-string + acdw-irc/left-margin " ") + line-number-mode nil) + (enable-lui-track))))) + (setup completion (:option completion-ignore-case t read-buffer-completion-ignore-case t @@ -137,78 +278,226 @@ (:global "M-/" #'hippie-expand)) -(setup cursor - (:option cursor-type 'bar - cursor-in-non-selected-windows 'hollow - blink-cursor-blinks 1) - (blink-cursor-mode +1)) - -(setup cus-edit - (:option custom-file null-device ; don't store customizations - custom-magic-show nil - custom-magic-show-button t - custom-raised-buttons nil - custom-unlispify-tag-names nil - custom-variable-default-form 'lisp) - - ;; `Custom-mode-hook' fires /before/ the widgets are built, so I have to - ;; install advice after the widgets are made. - (:advise custom-buffer-create :after - (defun custom-buffer@expand-widgets (&rest _) - "Expand descriptions in `Custom-mode' buffers." - (interactive) - ;; "More/Hide" widgets (thanks alphapapa!) - (widget-map-buttons (lambda (widget _) - (pcase (widget-get widget :off) - ("More" (widget-apply-action widget))) - nil)) - ;; "Show Value" widgets (the little triangles) - (widget-map-buttons (lambda (widget _) - (pcase (widget-get widget :off) - ("Show Value" - (widget-apply-action widget))) - nil)))) - - (:with-mode Custom-mode - (:hook (defun custom-mode@imenu () ; thanks u/oantolin! - "Build `imenu' for `Custom-mode'." - (setq - imenu-generic-expression - '(("Faces" (rx (seq bol - (or "Show" "Hide") " " - (group (zero-or-more nonl)) - " face: [sample]")) - 1) - ("Variables" (rx (seq bol - (or "Show Value" "Hide") " " - (group (zero-or-more - (not (any "\n:")))))) - 1))))))) - -(setup debugger - (:hook visual-line-mode)) - -(setup dired - (:also-load dired-x) - (setq-default dired-recursive-copies 'always - dired-recursive-deletes 'always - delete-by-moving-to-trash t - dired-listing-switches "-Al" - ls-lisp-dirs-first t - dired-ls-F-marks-symlinks t - dired-no-confirm '(byte-compile - chgrp chmod chown copy - hardlink load move - shell touch symlink) - dired-dwim-target t) +(setup (:straight (consult + :host github + :repo "minad/consult")) + (require 'acdw-consult) - (:hook dired-hide-details-mode - hl-line-mode) - - (:global "C-x C-j" #'dired-jump) + (setq consult--regexp-compiler #'consult--orderless-regexp-compiler) - (with-eval-after-load 'dired - (acdw/system + ;; Bindings + (:global + ;; C-c bindings (`mode-specific-map') + ;; I don't use any of these right now. + ;; "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 + ;; M-g bindings (`goto-map') + "M-g e" #'consult-compile-error + "M-g g" #'consult-goto-line + "M-g M-g" #'consult-goto-line + "M-g o" #'consult-outline + "M-g m" #'consult-mark + "M-g k" #'consult-global-mark + "M-g i" #'consult-imenu + "M-g I" #'consult-project-imenu + ;; M-s bindings (`search-map') + "M-s g" #'acdw-consult/sensible-grep + "M-s f" #'acdw-consult/sensible-find + "M-s l" #'consult-line + "M-s m" #'consult-multi-occur + "M-s k" #'consult-keep-lines + "M-s u" #'consult-focus-lines + ;; Other bindings + "M-y" #'consult-yank-pop + " a" #'consult-apropos + ;; Isearch integration + "M-s e" #'consult-isearch) + (:with-map isearch-mode-map + (:bind "M-e" #'consult-isearch + "M-s e" #'consult-isearch + "M-s l" #'consult-line)) + + ;; see https://github.com/oantolin/completing-history + (defmacro consult-history-to-modes (map-hook-alist) + (let (defuns) + (dolist (map-hook map-hook-alist) + (let ((map-name (symbol-name (car map-hook))) + (key-defs `(progn (define-key + ,(car map-hook) + (kbd "M-r") + (function consult-history)) + (define-key ,(car map-hook) + (kbd "M-s") nil)))) + (push (if (cdr map-hook) + `(add-hook ',(cdr map-hook) + (defun + ,(intern (concat map-name + "@consult-history-bind")) + nil + ,(concat + "Bind `consult-history' to M-r in " + map-name ".\n" + "Defined by `consult-history-to-modes'.") + ,key-defs)) + key-defs) + defuns))) + `(progn ,@ (nreverse defuns)))) + + (consult-history-to-modes ((minibuffer-local-map . nil) + (shell-mode-map . shell-mode-hook) + (term-mode-map . term-mode-hook) + (term-raw-map . term-mode-hook) + (comint-mode-map . comint-mode-hook) + (sly-mrepl-mode-map . sly-mrepl-hook))) + + + + ;; Registers + (:autoload consult-register-preview) + (:option register-preview-delay 0 + register-preview-function #'consult-register-format) + (:advise register-preview :override #'consult-register-window) + + ;; Xref + (:option xref-show-xrefs-function #'consult-xref + xref-show-definitions-function #'consult-xref) + + ;; Projects + (:option consult-project-root-function #'vc-root-dir) + + ;; Competion-at-point (complete-region) + (:option completion-in-region-function #'acdw-consult/complete-in-region + completion-cycle-threshold 3 + tab-always-indent 'complete) + + ;; Completing-read-multple + (if (fboundp #'consult-completing-read-multiple) + (:advise completing-read-multple + :override #'consult-completing-read-multiple) + ;; else + (defun crm-indicator (args) + (cons (concat "[CRM] " (car args)) (cdr args))) + (:advise completing-read-multiple + :filter-args #'crm-indicator)) + + (with-eval-after-loads (vertico consult) + (when (boundp 'consult-crm-map) + (define-key consult-crm-map "\r" #'+vertico-crm-exit) + (define-key consult-crm-map "\t" #'vertico-exit) + (defun +vertico-crm-exit () + (interactive) + (run-at-time 0 nil #'vertico-exit) + (funcall #'vertico-exit))))) + +(setup (:straight crux) + + (:global "C-x o" #'acdw/other-window-or-switch-buffer + "C-o" #'crux-smart-open-line + "M-o" #'crux-smart-open-line-above + "C-M-\\" #'crux-cleanup-buffer-or-region + "C-x 4 t" #'crux-transpose-windows) + + (when (fboundp 'repeat-mode) + (unless (boundp 'other-window-repeat-map) + (defvar other-window-repeat-map (make-sparse-keymap) + "A map for repeating `other-window' keys.")) + + (define-key other-window-repeat-map "o" + #'acdw/other-window-or-switch-buffer) + (define-key other-window-repeat-map "O" + (defun acdw/other-window-or-switch-buffer-backward () + (interactive) + (setq repeat-map 'other-window-repeat-map) + (acdw/other-window-or-switch-buffer -1))) + + (put 'acdw/other-window-or-switch-buffer + 'repeat-map 'other-window-repeat-map)) + + (crux-reopen-as-root-mode +1)) + +(setup cursor + (:option cursor-type 'bar + cursor-in-non-selected-windows 'hollow + blink-cursor-blinks 1) + (blink-cursor-mode +1)) + +(setup cus-edit + (:option custom-file null-device ; don't store customizations + custom-magic-show nil + custom-magic-show-button t + custom-raised-buttons nil + custom-unlispify-tag-names nil + custom-variable-default-form 'lisp) + + ;; `Custom-mode-hook' fires /before/ the widgets are built, so I have to + ;; install advice after the widgets are made. + (:advise custom-buffer-create :after + (defun custom-buffer@expand-widgets (&rest _) + "Expand descriptions in `Custom-mode' buffers." + (interactive) + ;; "More/Hide" widgets (thanks alphapapa!) + (widget-map-buttons (lambda (widget _) + (pcase (widget-get widget :off) + ("More" (widget-apply-action widget))) + nil)) + ;; "Show Value" widgets (the little triangles) + (widget-map-buttons (lambda (widget _) + (pcase (widget-get widget :off) + ("Show Value" + (widget-apply-action widget))) + nil)))) + + (:with-mode Custom-mode + (:hook (defun custom-mode@imenu () ; thanks u/oantolin! + "Build `imenu' for `Custom-mode'." + (setq + imenu-generic-expression + '(("Faces" (rx (seq bol + (or "Show" "Hide") " " + (group (zero-or-more nonl)) + " face: [sample]")) + 1) + ("Variables" (rx (seq bol + (or "Show Value" "Hide") " " + (group (zero-or-more + (not (any "\n:")))))) + 1))))))) + +(setup debugger + (:hook visual-line-mode)) + +(setup dired + (:also-load dired-x) + (setq-default dired-recursive-copies 'always + dired-recursive-deletes 'always + delete-by-moving-to-trash t + dired-listing-switches "-Al" + ls-lisp-dirs-first t + dired-ls-F-marks-symlinks t + dired-no-confirm '(byte-compile + chgrp chmod chown copy + hardlink load move + shell touch symlink) + dired-dwim-target t) + + (:hook dired-hide-details-mode + hl-line-mode) + + (:global "C-x C-j" #'dired-jump) + + (with-eval-after-load 'dired + (acdw/system (:work (:straight w32-browser) (autoload #'dired-w32-browser "w32-browser" nil t) (:bind "RET" #'dired-w32-browser)) @@ -280,38 +569,135 @@ (:option ediff-window-setup-function #'ediff-setup-windows-plain ediff-split-window-function #'split-window-horizontally)) +;; requires extension: +;; https://addons.mozilla.org/en-US/firefox/addon/edit-with-emacs1/ +(setup (:straight edit-server) + (when (and (daemonp) + (require 'edit-server nil :noerror)) + (edit-server-start) + + (:advise edit-server-make-frame :before + (defun edit-server@set-a-variable (&rest _) + (setq-local edit-server-frame-p t))))) + (setup eldoc (:option eldoc-idle-delay 0.1 eldoc-echo-area-use-multiline-p nil)) -(setup elisp-mode - (:option eval-expression-print-length nil - eval-expression-print-level nil - lisp-indent-function #'lisp-indent-function) +(setup (:straight (electric-cursor + :host github + :repo "duckwork/electric-cursor")) + (electric-cursor-mode +1)) - (:with-mode emacs-lisp-mode - (:hook #'checkdoc-minor-mode - #'turn-on-eldoc-mode - - (defun emacs-lisp@enforce-lexical-binding () - (setq-local lexical-binding t)) +(setup (:straight elfeed + elfeed-protocol) + (:option elfeed-use-curl t + elfeed-feeds `(("fever+https://acdw@mf.acdw.net" + :api-url "https://mf.acdw.net/fever/" + :password ,(acdw/make-password-fetcher + :host "mf.acdw.net")))) - (defun emacs-lisp@imenu-add-setup () - (add-to-list 'imenu-generic-expression - '("Setup" - "\\(^\\s-*(setup +(?\\)\\(\\_<.+\\_>\\)" 2)))) + (elfeed-protocol-enable) - ;; Emulate slime's eval binds - (:bind "C-c C-c" #'eval-defun - "C-c C-k" #'acdw/eval-region-or-buffer - "C-c C-z" #'ielm)) - - ;; Add advice to pulse evaluated regions - (:advise eval-region :around - (defun eval-region@pulse (fn beg end &rest args) - (pulse-momentary-highlight-region beg end) + (:with-mode elfeed-show-mode + (:hook (defun elfeed-show@setup () + (acdw/reading-mode))) + + ;; see https://irreal.org/blog/?p=8885 + (:bind "SPC" (defun elfeed-scroll-up-command (&optional arg) + "Scroll up or go to next feed item in Elfeed" + (interactive "^P") + (let ((scroll-error-top-bottom nil)) + (condition-case-unless-debug nil + (scroll-up-command arg) + (error (elfeed-show-next))))) + "S-SPC" (defun elfeed-scroll-down-command (&optional arg) + "Scroll up or go to next feed item in Elfeed" + (interactive "^P") + (let ((scroll-error-top-bottom nil)) + (condition-case-unless-debug nil + (scroll-down-command arg) + (error (elfeed-show-prev)))))))) + +(setup elisp-mode + (:option eval-expression-print-length nil + eval-expression-print-level nil + lisp-indent-function #'lisp-indent-function) + + (:with-mode emacs-lisp-mode + (:hook #'checkdoc-minor-mode + #'turn-on-eldoc-mode + + (defun emacs-lisp@enforce-lexical-binding () + (setq-local lexical-binding t)) + + (defun emacs-lisp@imenu-add-setup () + (:option (append imenu-generic-expression) + '("Setup" + "\\(^\\s-*(setup +(?\\)\\(\\_<.+\\_>\\)" 2)))) + + ;; Emulate slime's eval binds + (:bind "C-c C-c" #'eval-defun + "C-c C-k" #'acdw/eval-region-or-buffer + "C-c C-z" #'ielm)) + + ;; Add advice to pulse evaluated regions + (:advise eval-region :around + (defun eval-region@pulse (fn beg end &rest args) + (pulse-momentary-highlight-region beg end) (apply fn start end args)))) +(setup (:straight elisp-slime-nav) + (:hook-into emacs-lisp-mode + ielm-mode)) + +(setup (:straight (elpher + :host nil + :repo "git://thelambdalab.xyz/elpher.git")) + (:option elpher-ipv4-always t + elpher-certificate-directory (acdw/dir "elpher/") + elpher-gemini-max-fill-width fill-column) + + (:bind "n" #'elpher-next-link + "p" #'elpher-prev-link + "o" #'elpher-follow-current-link + "G" #'elpher-go-current) + + (:hook acdw/reading-mode) + + (:autoload (elpher-bookmarks :interactive t) + (elpher-go :interactive t)) + + ;; Make `eww' gemini/gopher aware. From Emacswiki. + ;; (define-advice eww-browse-url (:around (fn url &rest args) gemini-elpher) + ;; (cond ((string-match-p "\\`\\(gemini\\|gopher\\)://" url) + ;; (require 'elpher) + ;; (elpher-go url)) + ;; (t (apply fn url args)))) + ) + +(setup (:straight embark) + (:global "C-." #'embark-act) + (:option prefix-help-command #'embark-prefix-help-command + (append display-buffer-alist) + '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*" + nil + (window-parameters (mode-line-format . none))) + embark-prompter #'embark-keymap-prompter + embark-verbose-indicator-display-action + '(display-buffer-at-bottom (window-height . fit-window-to-buffer))) + + (setq embark-action-indicator + (lambda (map _target) + (which-key--show-keymap "Embark" map nil nil 'no-paging) + #'which-key--hide-popup-ignore-command) + embark-become-indicator embark-action-indicator) + + (with-eval-after-loads (embark consult) + (:straight embark-consult) + (add-hook 'embark-collect-mode-hook + #'consult-preview-at-point-mode))) + (setup encoding (:option locale-coding-system 'utf-8-unix coding-system-for-read 'utf-8-unix @@ -336,6 +722,60 @@ (_ (set-selection-coding-system 'utf-8) (set-clipboard-coding-system 'utf-8)))) +(setup (:straight epithet) + (dolist (hook '(Info-selection-hook + eww-after-render-hook + help-mode-hook + occur-mode-hook)) + (add-hook hook #'epithet-rename-buffer))) + +;; TODO: look into emms or something related for this +(setup (:straight-if eradio + (executable-find "mpv")) + (:option + eradio-player '("mpv" "--no-video" "--no-terminal") + eradio-channels `(("KLSU" . + "http://130.39.238.143:8010/stream.mp3") + ("Soma FM Synphaera" . + "https://somafm.com/synphaera256.pls") + ("SomaFM BAGel Radio" . + "https://somafm.com/bagel.pls") + ("SomaFM Boot Liquor" . + "https://somafm.com/bootliquor320.pls") + ("SomaFM Deep Space One" . + "https://somafm.com/deepspaceone.pls") + ("SomaFM Fluid" . + "https://somafm.com/fluid.pls") + ("SomaFM Underground 80s" . + "https://somafm.com/u80s256.pls") + ("WBRH: Jazz & More" . + "http://wbrh.streamguys1.com/wbrh-mp3") + ("KBRH Blues & Rhythm Hits" . + "http://wbrh.streamguys1.com/kbrh-mp3") + ("WRKF HD-2" . + ,(concat "https://playerservices.streamtheworld.com/" + "api/livestream-redirect/WRKFHD2.mp3")) + ("WRKF: NPR for the Capital Region" . + ,(concat "https://playerservices.streamtheworld.com/" + "api/livestream-redirect/WRKFFM.mp3")) + ("BadRadio: 24/7 PHONK" . + "https://s2.radio.co/s2b2b68744/listen") + ("tilderadio" . + "https://radio.tildeverse.org/radio/8000/radio.ogg") + ("vantaradio" . + "https://vantaa.black/radio"))) + (:global "C-c r r" #'eradio-play ; mnemonic: radio + "C-c r s" #'eradio-stop ; mnemonic: stop + "C-c r p" #'eradio-toggle ; mnemonic: play/pause + )) + +(setup (:straight eros) + (:hook-into emacs-lisp-mode)) + +(setup (:straight esh-autosuggest) + (:autoload esh-autosuggest-mode) + (:hook-into eshell-mode)) + (setup eshell (:also-load acdw-eshell em-smart) @@ -371,6 +811,41 @@ (:hook acdw/reading-mode)) +(setup (:straight-if exec-path-from-shell + (acdw/system :home)) + (when (daemonp) + (exec-path-from-shell-initialize))) + +(setup (:straight expand-region) + (:global "C-=" #'er/expand-region + "C-SPC" + (defun acdw/set-mark-or-expand-region (arg) + "Set mark at point and activate, jump to mark, or expand region. +See `set-mark-command' and `expand-region'. + +With no prefix argument, either run `set-mark-command' on first +invocation and `er/expand-region' on each successive invocation. + +With any prefix argument +(e.g., \\[universal-argument] \\[set-mark-command]), act as with +`set-mark-command' (i.e., pop the mark). Don't care about +successive invocations." + (interactive "P") + (cond + ((or arg + (and set-mark-command-repeat-pop + (eq last-command 'pop-to-mark-command))) + (setq this-command 'set-mark-command) + (set-mark-command arg)) + ((eq last-command 'acdw/set-mark-or-expand-region) + (er/expand-region 1)) + (t (set-mark-command arg)))))) + +(setup (:straight-if fennel-mode + (executable-find "fennel")) + (:autoload (fennel-repl :interactive t)) + (:file-match (rx ".fnl" eos))) + (setup files (:option auto-save-file-name-transforms `((".*" ,(acdw/dir "auto-save/" t) t)) @@ -400,6 +875,12 @@ (setup flyspell (add-hook 'text-mode-hook #'flyspell-mode)) +(setup (:straight flyspell-correct) + (:with-mode flyspell-mode + (:hook (defun flyspell@correct () + (:bind "C-;" #'flyspell-correct-wrapper) + (:unbind "C-," "C-." "C-M-i"))))) + (setup frames (:option frame-title-format '("%b@" (:eval @@ -412,34 +893,110 @@ (add-hook 'unfocused-hook #'garbage-collect)) +(setup (:straight gcmh) + (:option gcmh-idle-delay 'auto) + (gcmh-mode +1)) + +(setup (:straight-if geiser + (progn + (defvar acdw/schemes + (let (schemes) + (dolist (scheme '(("scheme" . geiser-chez) ; chez + ("petite" . geiser-chez) ; petite + ("csi" . geiser-chez) ; chicken + ("gsi" . geiser-gambit) + ("gosh" . geiser-gauche) + ("guile" . geiser-guile) + ("kawa" . geiser-kawa) + ("mit-scheme" . geiser-mit) + ("racket" . geiser-racket) + ("stklos" . geiser-stklos))) + (when-let (binary (executable-find (car scheme))) + (push binary schemes) + ;; and install the proper helper package + (straight-use-package (cdr scheme)))) + (nreverse schemes))) + acdw/schemes)) + (:file-match (rx ".rkt" eos) + (rx ".scm" eos))) + +(setup (:straight (gemini-mode + :host nil + :repo "https://git.carcosa.net/jmcbray/gemini.el.git")) + (:file-match (rx (seq "." (or "gemini" "gmi") eos))) + (:hook turn-off-auto-fill)) + +(setup (:straight (gemini-write + :host nil + :repo "https://alexschroeder.ch/cgit/gemini-write" + :branch "main")) + (with-eval-after-load 'elpher + (require 'gemini-write))) + +(setup (:require gforth) + (:autoload forth-mode + forth-block-mode) + (add-to-list 'auto-mode-alist '("\\.fs\\'" . forth-mode)) + (add-to-list 'auto-mode-alist '("\\.fb\\'" . forth-block-mode))) + (setup goto-addr (if (fboundp #'global-goto-address-mode) (global-goto-address-mode) (add-hook 'after-change-major-mode-hook #'goto-address-mode))) -(setup ibuffer - (:also-load ibuf-ext) - (:option ibuffer-expert t - ibuffer-show-empty-filter-groups nil - ibuffer-saved-filter-groups - '(("default" - ("dired" (mode . dired-mode)) - ("customize" (mode . Custom-mode)) - ("emacs" (or (name . "^\\*scratch\\*$") - (name . "^\\*Messages\\*$") - (name . "^\\*Warnings\\*$") - (name . "^\\*straight-process\\*$") - (name . "^\\*Calendar\\*$"))) - ("git" (or (name . "^\*magit") - (name . "^\magit"))) - ("help" (or (mode . help-mode) - (mode . Info-mode) - (mode . helpful-mode))) - ("messaging" (or (mode . message-mode) - (mode . bbdb-mode) - (mode . mail-mode) - (mode . gnus-group-mode) - (mode . gnus-summary-mode) + +;; TODO: figure out a popper.el / shackle.el ... thing to fix this +(setup (:straight helpful) + (:option helpful-max-buffers 5) + (:global " f" #'helpful-callable + " v" #'helpful-variable + " k" #'helpful-key + " o" #'helpful-symbol)) + +(setup (:straight hungry-delete) + (:option hungry-delete-chars-to-skip " \t" + hungry-delete-join-reluctantly nil) + + (global-hungry-delete-mode +1) + + (:with-feature paredit + (:bind [remap paredit-backward-delete] + (defun acdw/paredit-hungry-delete-backward (arg) + (interactive "P") + (if (looking-back "[ \t]" 1) + (hungry-delete-backward (or arg 1)) + (paredit-backward-delete arg))) + + [remap paredit-forward-delete] + (defun acdw/paredit-hungry-delete-forward (arg) + (interactive "P") + (if (looking-at "[ \t]") + (hungry-delete-forward (or arg 1)) + (paredit-forward-delete arg)))))) + +(setup ibuffer + (:also-load ibuf-ext) + (:option ibuffer-expert t + ibuffer-show-empty-filter-groups nil + ibuffer-saved-filter-groups + '(("default" + ("dired" (mode . dired-mode)) + ("customize" (mode . Custom-mode)) + ("emacs" (or (name . "^\\*scratch\\*$") + (name . "^\\*Messages\\*$") + (name . "^\\*Warnings\\*$") + (name . "^\\*straight-process\\*$") + (name . "^\\*Calendar\\*$"))) + ("git" (or (name . "^\*magit") + (name . "^\magit"))) + ("help" (or (mode . help-mode) + (mode . Info-mode) + (mode . helpful-mode))) + ("messaging" (or (mode . message-mode) + (mode . bbdb-mode) + (mode . mail-mode) + (mode . gnus-group-mode) + (mode . gnus-summary-mode) (mode . gnus-article-mode) (name . "^\\.bbdb$") (name . "^\\.newsrc-dribble") @@ -464,9 +1021,21 @@ (setup imenu (:option imenu-auto-rescan t)) +(setup (:straight iscroll) + (define-globalized-minor-mode global-iscroll-mode iscroll-mode + (lambda () (iscroll-mode +1))) + + (global-iscroll-mode +1)) + (setup isearch (:option search-default-mode t)) +(setup (:straight lacarte) + (:global "" #'lacarte-execute-menu-command)) + +(setup (:straight-if ledger-mode + (executable-find "ledger"))) + (setup lines (:option fill-column 79 word-wrap t @@ -490,6 +1059,80 @@ (delete-indentation 1) (apply fn args))))) +(setup (:straight link-hint) + ;; Browse web URLs with a browser with a prefix argument. + (dolist (type '(gnus-w3m-image-url + gnus-w3m-url + markdown-link + mu4e-attachment + mu4e-url + notmuch-hello + nov-link + org-link + shr-url + text-url + w3m-link + w3m-message-link)) + (link-hint-define-type type + :open-secondary browse-url-secondary-browser-function)) + + (:option link-hint-avy-style 'at) + (:global "C-;" + (defun acdw/link-hint-open-link (arg) + "Open a link using `link-hint-open-link', prefix-aware. +That is, a prefix argument (\\[universal-argument]) will open the +browser defined in `browse-url-secondary-browser-function'." + (interactive "P") + (avy-with link-hint-open-link + (link-hint--one (if arg :open-secondary :open)))))) + +(setup (:straight lua-mode) + (:file-match (rx ".lua" eos))) + +(setup (:straight macrostep) + + (:with-mode emacs-lisp-mode + (:bind "C-c e" #'macrostep-expand))) + +(setup (:straight magit) + (:global "C-c g" #'magit-status) + + (:option magit-display-buffer-function + (defun magit-display-buffer-same-window (buffer) + "Display BUFFER in the selected window like God intended." + (display-buffer buffer '(display-buffer-same-window))) + magit-popup-display-buffer-action '((display-buffer-same-window)) + magit-refresh-status-buffer nil)) + +(setup (:straight marginalia) + (:option marginalia-annotators '(marginalia-annotators-heavy + marginalia-annotators-light)) + (marginalia-mode +1)) + +(setup (:straight markdown-mode) + (:file-match (rx ".md" eos) + (rx ".markdown" eos)) + + (:with-mode gfm-mode + (:file-match (rx "README.md" eos))) + + (when (executable-find "markdownfmt") + (with-eval-after-load 'apheleia + (:option (append apheleia-formatters) '(markdownfmt . ("markdownfmt")) + (append apheleia-mode-alist) '(markdown-mode . markdownfmt) + (append apheleia-mode-alist) '(gfm-mode . markdownfmt))))) + +(setup (:straight (mastodon + :host github + :repo "mooseyboots/mastodon.el") + request) + (:option mastodon-instance-url "https://writing.exchange" + mastodon-auth-source-file (car auth-sources) + mastodon-client--token-file (acdw/dir "mastodon.plstore")) + + (:hook #'hl-line-mode + #'acdw/reading-mode)) + (setup minibuffer (:option enable-recursive-minibuffers t file-name-shadow-properties '(invisible t intangible t) @@ -510,1046 +1153,94 @@ (minibuffer-electric-default-mode +1) (fset 'yes-or-no-p #'y-or-n-p)) -(setup page - (:option page-delimiter - (rx bol (or "\f" ";;;") - (not (any "#")) (* not-newline) "\n" - (* (* blank) (opt ";" (* not-newline)) "\n"))) - - (defun recenter-to-top (&rest _) - "Recenter the cursor to the top of the window." - (when (called-interactively-p 'any) - (recenter (if (or (null scroll-margin) - (zerop scroll-margin)) - 3 - scroll-margin)))) - - (:advise forward-page :after #'recenter-to-top - backward-page :after #'recenter-to-top) - - ;; I'm not sure where this is in /my/ version of Emacs - (defvar page-navigation-repeat-map - (let ((map (make-sparse-keymap))) - (define-key map "]" #'forward-page) - (define-key map "[" #'backward-page) - map) - "Keymap to repeat page navigation key sequences. Used in `repeat-mode'.") - - (put 'forward-page 'repeat-map 'page-navigation-repeat-map) - (put 'backward-page 'repeat-map 'page-navigation-repeat-map)) - -(setup prog - (:option show-paren-delay 0 - show-paren-style 'mixed - show-paren-when-point-inside-paren t - show-paren-when-point-in-periphery t - smie-indent-basic tab-width) +(setup (:straight (modus-themes + :host gitlab + :repo "protesilaos/modus-themes")) + (:option modus-themes-slanted-constructs t + modus-themes-bold-constructs t + modus-themes-region 'bg-only + modus-themes-org-blocks 'grayscale + modus-themes-headings '((1 . section) + (t . no-color)) + modus-themes-mode-line nil) - (:hook show-paren-mode - electric-pair-local-mode - acdw/setup-fringes - - (defun flymake-mode-except () - "Turn on flymake mode, except in some modes." - (let ((no-flymake-modes '(emacs-lisp-mode))) - (unless (or (member major-mode no-flymake-modes) - (apply #'derived-mode-p no-flymake-modes)) - (flymake-mode-on)))) - - (defun prog-mode@auto-fill () - (setq-local comment-auto-fill-only-comments t) - (turn-on-auto-fill))) + (acdw/sunrise-sunset #'modus-themes-load-operandi + #'modus-themes-load-vivendi)) - (add-hook 'after-save-hook - #'executable-make-buffer-file-executable-if-script-p)) +(setup (:straight mwim) + (:global "C-a" #'mwim-beginning + "C-e" #'mwim-end)) -(setup repeat - ;; new for Emacs 28! - (:only-if (fboundp #'repeat-mode)) +(setup (:straight nov) + (:option nov-text-width fill-column) + (:file-match (rx ".epub" eos))) - (:option repeat-exit-key "g" - repeat-exit-timeout 5) +(setup (:straight olivetti) + (:option olivetti-body-width (+ fill-column 4) + olivetti-minimum-body-width fill-column) - (repeat-mode +1)) + (:hook (defun olivetti-mode@setup () + (if olivetti-mode + (setq-local indicate-empty-lines nil + indicate-buffer-boundaries nil) + (acdw/setup-fringes))))) -(setup saveplace - (:option save-place-file (acdw/dir "places.el") - save-place-forget-unreadable-files (acdw/system :home)) +(setup (:straight (orderless + :host github + :repo "oantolin/orderless")) + (require 'orderless) - (save-place-mode +1)) + (:option (append completion-styles) 'orderless + orderless-component-separator #'orderless-escapable-split-on-space + orderless-style-dispatchers '(acdw/orderless-dispatch)) -(setup scratch - (:option inhibit-startup-screen t - initial-buffer-choice t - initial-scratch-message "" - ;; (concat ";; Howdy, " - ;; (nth 0 (split-string - ;; user-full-name)) - ;; "! " - ;; "Welcome to GNU Emacs.\n\n") - initial-major-mode 'emacs-lisp-mode) - - (add-hook 'kill-buffer-query-functions - (defun kill-buffer-query@immortal-scratch () - (if (eq (current-buffer) (get-buffer "*scratch*")) - (progn (bury-buffer) - nil) - t)))) + (:advise orderless-regexp :filter-args + (defun fix-dollar (args) + (if (string-suffix-p "$" (car args)) + (list (concat (substring (car args) 0 -1) + "[\x100000-\x10FFFD]*$")) + args))) -(setup scrolling - (:option auto-window-vscroll nil - fast-but-imprecise-scrolling t - scroll-margin 3 - scroll-conservatively 101 - scroll-preserve-screen-position 1)) - -(setup selection - (:option save-interprogram-paste-before-kill t - yank-pop-change-selection t - x-select-enable-clipboard t - x-select-enable-primary t - mouse-drag-copy-region t - kill-do-not-save-duplicates t) - - (delete-selection-mode +1)) - -(setup sh-mode - (:option sh-basic-offset tab-width - sh-indent-after-case 0 - sh-indent-for-case-alt '+ - sh-indent-for-case-label 0) - - (:local-set indent-tabs-mode t) - - (when (executable-find "shfmt") - (with-eval-after-load 'apheleia - (:option (append apheleia-formatters) '(shfmt . ("shfmt")) - (append apheleia-mode-alist) '(sh-mode . shfmt)))) - - (when (executable-find "shellcheck") - (:straight flymake-shellcheck) - (:hook flymake-mode - flymake-shellcheck-load))) - -(setup shell-command - (:option shell-command-switch (acdw/system - ;; I should be testing on some variable - (:home "-csi") - (:work "-c")) - shell-command-prompt-show-cwd t - shell-command-default-error-buffer "*shell-command-errors*")) - -(setup shr - (:option shr-width fill-column - shr-max-width fill-column - shr-max-image-proportion 0.6 - shr-image-animate t - shr-discard-aria-hidden t - shr-folding-mode t)) - -(setup text - (:hook turn-on-auto-fill - acdw/setup-fringes)) - -(setup uniquify - (:option uniquify-buffer-name-style 'forward - uniquify-separator path-separator - uniquify-after-kill-buffer-p t - uniquify-ignore-buffers-re "^\\*")) - -(setup variable-pitch-mode - - ;; I might want to change this to `buffer-face-mode-hook'... - (advice-add 'variable-pitch-mode :after - (defun variable-pitch-mode@setup (&rest _) - "Set up `variable-pitch-mode' with my customizations." - (display-fill-column-indicator-mode (if buffer-face-mode - -1 - +1))))) - -(setup view - (:option view-read-only t) - - (:hook (defun acdw/read-view-mode () - (acdw/reading-mode (if view-mode +1 -1))))) - -(setup w32 - (:option w32-allow-system-shell t - w32-pass-lwindow-to-system nil - w32-lwindow-modifier 'super - w32-pass-rwindow-to-system nil - w32-rwindow-modifier 'super - w32-pass-apps-to-system nil - w32-apps-modifier 'hyper)) - -(setup whitespace - (:option whitespace-style - '(empty indentation space-before-tab space-after-tab) - indent-tabs-mode nil - tab-width 4 - backward-delete-char-untabify-method 'hungry) - - (:global "M-SPC" #'cycle-spacing)) - -(setup windmove - (:option windmove-wrap-around t) - (:global - ;; moving - "C-x 4 " #'windmove-left - "C-x 4 " #'windmove-right - "C-x 4 " #'windmove-up - "C-x 4 " #'windmove-down - ;; swapping - "C-x 4 S-" #'windmove-swap-states-left - "C-x 4 S-" #'windmove-swap-states-right - "C-x 4 S-" #'windmove-swap-states-up - "C-x 4 S-" #'windmove-swap-states-down) - - (when (fboundp 'repeat-mode) - (defvar windmove-repeat-map - (let ((map (make-sparse-keymap))) - ;; moving - (define-key map [left] #'windmove-left) - (define-key map [right] #'windmove-right) - (define-key map [up] #'windmove-up) - (define-key map [down] #'windmove-down) - ;; swapping - (define-key map [S-left] #'windmove-swap-states-left) - (define-key map [S-right] #'windmove-swap-states-right) - (define-key map [S-up] #'windmove-swap-states-up) - (define-key map [S-down] #'windmove-swap-states-down) - map) - "Keymap to repeat various `windmove' sequences. Used in `repeat-mode'.") - - (dolist (sym '(windmove-left - windmove-right - windmove-up - windmove-down - windmove-swap-states-left - windmove-swap-states-right - windmove-swap-states-up - windmove-swap-states-down)) - (put sym 'repeat-map 'windmove-repeat-map)))) - -(setup window - (require 'acdw-bell) - (:option Man-notify-method 'pushy - display-buffer-alist ; from FrostyX - '(("shell.*" (display-buffer-same-window) ()) - (".*" (display-buffer-reuse-window - display-buffer-same-window) - (reusable-frames . t))) - recenter-positions '(top middle bottom) - ring-bell-function (lambda () - (acdw-bell/flash-mode-line - (acdw/system :home))) - tab-bar-show 1 - use-dialog-box nil - use-file-dialog nil - visible-bell nil) - - (tooltip-mode -1)) - -(setup winner - ;; see https://lists.gnu.org/archive/html/emacs-devel/2021-08/msg00888.html - (:global "C-x 4 C-/" #'winner-undo - "C-x 4 /" #'winner-undo - "C-x 4 C-?" #'winner-redo - "C-x 4 ?" #'winner-redo) - - ;; add `winner-undo' and `winner-redo' to `repeat-mode' - (when (fboundp 'repeat-mode) - (defvar winner-mode-repeat-map - (let ((map (make-sparse-keymap))) - (define-key map "/" #'winner-undo) - (define-key map "?" #'winner-redo) - map) - "Keymap to repeat `winner-mode' sequences. Used in `repeat-mode'.") - - (put 'winner-undo 'repeat-map 'winner-mode-repeat-map) - (put 'winner-redo 'repeat-map 'winner-mode-repeat-map)) - - (winner-mode +1)) - -(setup x-emacs - ;; "Et cetera" settings - ;; This should stay as /minimal/ as possible. Anything that can go somewhere - ;; else /should/ go there. - (:option - attempt-orderly-shutdown-on-fatal-signal nil - attempt-stack-overflow-recovery nil - echo-keystrokes 0.01 - find-function-C-source-directory (acdw/find-emacs-source) - kill-read-only-ok t - load-prefer-newer t - native-comp-async-report-warnings-errors nil - set-mark-command-repeat-pop t) - - (when (fboundp 'command-completion-default-include-p) - (setq read-extended-command-predicate - #'command-completion-default-include-p)) - - (defvar case-map (make-sparse-keymap) - "A keymap for setting case in various ways.") - (global-set-key (kbd "C-c c") case-map) - - (defvar lookup-map (make-sparse-keymap) - "A keymap for looking up things.") - (global-set-key (kbd "C-c l") lookup-map) - - (:global "M-=" #'count-words - "C-w" #'kill-region-or-backward-word - "C-c c c" #'capitalize-dwim - "C-c c t" #'titlecase-dwim - "C-c c u" #'upcase-dwim - "C-c c l" #'downcase-dwim - "C-c d" #'acdw/insert-iso-date - "M-`" nil) - - ;; toggle bindings - (defvar toggle-map (make-sparse-keymap) - "A keymap for toggling!") - (global-set-key (kbd "C-c t") toggle-map) - - (:with-map toggle-map - (:bind "c" #'column-number-mode - "l" #'display-line-numbers-mode - "d" #'toggle-debug-on-error)) - - (defalias 'forward-word-with-case 'forward-word - "Alias for `forward-word' for use in `case-repeat-map'.") - (defalias 'backward-word-with-case 'backward-word - "Alias for `backward-word for use in `case-repeat-map'.") - - (defvar case-repeat-map - (let ((map (make-sparse-keymap))) - (define-key map "c" #'capitalize-word) - (define-key map "u" #'upcase-word) - (define-key map "l" #'downcase-word) - ;; movement - (define-key map "f" #'forward-word-with-case) - (define-key map "b" #'backward-word-with-case) - map) - "A map to repeat word-casing commands. For use with `repeat-mode'.") - - (dolist (command '(capitalize-word - capitalize-dwim - upcase-word - upcase-dwim - downcase-word - downcase-dwim - forward-word-with-case - backward-word-with-case)) - (put command 'repeat-map 'case-repeat-map)) - - (add-hook 'after-make-frame-functions - (defun after-make-frame@maximize (frame) - (unless (bound-and-true-p edit-server-frame-p) - (toggle-frame-maximized frame))))) - - -;;; Packages - -(setup (:require gforth) - (:autoload forth-mode - forth-block-mode) - (add-to-list 'auto-mode-alist '("\\.fs\\'" . forth-mode)) - (add-to-list 'auto-mode-alist '("\\.fb\\'" . forth-block-mode))) - -(setup (:straight (0x0 :host gitlab - :repo "willvaughn/emacs-0x0")) - (:option 0x0-default-server 'ttm)) - -(setup (:straight (apheleia :host github - :repo "raxod502/apheleia")) - - (apheleia-global-mode +1) - - ;; Use a dumb formatter on modes that `apheleia' doesn't work for. - (add-hook 'before-save-hook - (defun before-save@dumb-auto-format () - (setq stupid-modes '(makefile-mode - org-mode)) - ;; If there's no apheleia formatter for the mode, just indent the - ;; buffer. - (unless (or (apply #'derived-mode-p stupid-modes) - (and (fboundp 'apheleia--get-formatter-command) - (apheleia--get-formatter-command))) - (indent-region (point-min) (point-max)))))) - -(setup (:straight (consult - :host github - :repo "minad/consult")) - (require 'acdw-consult) - - (setq consult--regexp-compiler #'consult--orderless-regexp-compiler) - - ;; Bindings - (:global - ;; C-c bindings (`mode-specific-map') - ;; I don't use any of these right now. - ;; "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 - ;; M-g bindings (`goto-map') - "M-g e" #'consult-compile-error - "M-g g" #'consult-goto-line - "M-g M-g" #'consult-goto-line - "M-g o" #'consult-outline - "M-g m" #'consult-mark - "M-g k" #'consult-global-mark - "M-g i" #'consult-imenu - "M-g I" #'consult-project-imenu - ;; M-s bindings (`search-map') - "M-s g" #'acdw-consult/sensible-grep - "M-s f" #'acdw-consult/sensible-find - "M-s l" #'consult-line - "M-s m" #'consult-multi-occur - "M-s k" #'consult-keep-lines - "M-s u" #'consult-focus-lines - ;; Other bindings - "M-y" #'consult-yank-pop - " a" #'consult-apropos - ;; Isearch integration - "M-s e" #'consult-isearch) - (:with-map isearch-mode-map - (:bind "M-e" #'consult-isearch - "M-s e" #'consult-isearch - "M-s l" #'consult-line)) - - ;; see https://github.com/oantolin/completing-history - (defmacro consult-history-to-modes (map-hook-alist) - (let (defuns) - (dolist (map-hook map-hook-alist) - (let ((map-name (symbol-name (car map-hook))) - (key-defs `(progn (define-key - ,(car map-hook) - (kbd "M-r") - (function consult-history)) - (define-key ,(car map-hook) - (kbd "M-s") nil)))) - (push (if (cdr map-hook) - `(add-hook ',(cdr map-hook) - (defun - ,(intern (concat map-name - "@consult-history-bind")) - nil - ,(concat - "Bind `consult-history' to M-r in " - map-name ".\n" - "Defined by `consult-history-to-modes'.") - ,key-defs)) - key-defs) - defuns))) - `(progn ,@ (nreverse defuns)))) - - (consult-history-to-modes ((minibuffer-local-map . nil) - (shell-mode-map . shell-mode-hook) - (term-mode-map . term-mode-hook) - (term-raw-map . term-mode-hook) - (comint-mode-map . comint-mode-hook) - (sly-mrepl-mode-map . sly-mrepl-hook))) - - - - ;; Registers - (:autoload consult-register-preview) - (:option register-preview-delay 0 - register-preview-function #'consult-register-format) - (:advise register-preview :override #'consult-register-window) - - ;; Xref - (:option xref-show-xrefs-function #'consult-xref - xref-show-definitions-function #'consult-xref) - - ;; Projects - (:option consult-project-root-function #'vc-root-dir) - - ;; Competion-at-point (complete-region) - (:option completion-in-region-function #'acdw-consult/complete-in-region - completion-cycle-threshold 3 - tab-always-indent 'complete) - - ;; Completing-read-multple - (if (fboundp #'consult-completing-read-multiple) - (:advise completing-read-multple - :override #'consult-completing-read-multiple) - ;; else - (defun crm-indicator (args) - (cons (concat "[CRM] " (car args)) (cdr args))) - (:advise completing-read-multiple - :filter-args #'crm-indicator)) - - (with-eval-after-loads (vertico consult) - (when (boundp 'consult-crm-map) - (define-key consult-crm-map "\r" #'+vertico-crm-exit) - (define-key consult-crm-map "\t" #'vertico-exit) - (defun +vertico-crm-exit () - (interactive) - (run-at-time 0 nil #'vertico-exit) - (funcall #'vertico-exit))))) - -(setup (:straight (electric-cursor - :host github - :repo "duckwork/electric-cursor")) - (electric-cursor-mode +1)) - -(setup (:straight (elpher :host nil - :repo "git://thelambdalab.xyz/elpher.git")) - (:option elpher-ipv4-always t - elpher-certificate-directory (acdw/dir "elpher/") - elpher-gemini-max-fill-width fill-column) - - (:bind "n" #'elpher-next-link - "p" #'elpher-prev-link - "o" #'elpher-follow-current-link - "G" #'elpher-go-current) - - (:hook acdw/reading-mode) - - (:autoload (elpher-bookmarks :interactive t) - (elpher-go :interactive t)) - - ;; Make `eww' gemini/gopher aware. From Emacswiki. - ;; (define-advice eww-browse-url (:around (fn url &rest args) gemini-elpher) - ;; (cond ((string-match-p "\\`\\(gemini\\|gopher\\)://" url) - ;; (require 'elpher) - ;; (elpher-go url)) - ;; (t (apply fn url args)))) - ) - -(setup (:straight (gemini-mode - :host nil - :repo "https://git.carcosa.net/jmcbray/gemini.el.git")) - (:file-match (rx (seq "." (or "gemini" "gmi") eos))) - (:hook turn-off-auto-fill)) - -(setup (:straight (gemini-write - :host nil - :repo "https://alexschroeder.ch/cgit/gemini-write" - :branch "main")) - (with-eval-after-load 'elpher - (require 'gemini-write))) - -(setup (:straight (mastodon - :host github - :repo "mooseyboots/mastodon.el") - request) - (:option mastodon-instance-url "https://writing.exchange" - mastodon-auth-source-file (car auth-sources) - mastodon-client--token-file (acdw/dir "mastodon.plstore")) - - (:hook #'hl-line-mode - #'acdw/reading-mode)) - -(setup (:straight (modus-themes - :host gitlab - :repo "protesilaos/modus-themes")) - (:option modus-themes-slanted-constructs t - modus-themes-bold-constructs t - modus-themes-region 'bg-only - modus-themes-org-blocks 'grayscale - modus-themes-headings '((1 . section) - (t . no-color)) - modus-themes-mode-line nil) - - (acdw/sunrise-sunset #'modus-themes-load-operandi - #'modus-themes-load-vivendi)) - -(setup (:straight (orderless - :host github - :repo "oantolin/orderless")) - (require 'orderless) - - (:option (append completion-styles) 'orderless - orderless-component-separator #'orderless-escapable-split-on-space - orderless-style-dispatchers '(acdw/orderless-dispatch)) - - (:advise orderless-regexp :filter-args - (defun fix-dollar (args) - (if (string-suffix-p "$" (car args)) - (list (concat (substring (car args) 0 -1) - "[\x100000-\x10FFFD]*$")) - args))) - - (defun acdw/orderless-dispatch (pattern _index _total) - "My custom dispatcher for `orderless'." - (cond - ;; Ensure that $ works with Consult commands, which add disambiguation - ;; suffixes -- see `fix-dollar' - ((string-suffix-p "$" pattern) - `(orderless-regexp . ,(concat (substring pattern 0 -1) - "[\x100000-\x10FFFD]*$"))) - ;; File extensions - ((string-match-p "\\`\\.." pattern) - `(orderless-regexp . ,(concat "\\." (substring pattern 1) - "[\x100000-\x10FFFD]*$"))) - ;; Ignore single ! - ((string= "!" pattern) - `(orderless-literal . "")) - ;; Character folding - ((string-prefix-p "%" pattern) - `(char-fold-to-regexp . ,(substring pattern 1))) - ((string-suffix-p "%" pattern) - `(char-fold-to-regexp . ,(substring pattern 0 -1))) - ;; Without literal - ((string-prefix-p "!" pattern) - `(orderless-without-literal . ,(substring pattern 1))) - ((string-suffix-p "!" pattern) - `(orderless-without-literal . ,(substring pattern 0 -1))) - ;; Initialism matching - ((string-prefix-p "`" pattern) - `(orderless-initialism . ,(substring pattern 1))) - ((string-suffix-p "`" pattern) - `(orderless-initialism . ,(substring pattern 0 -1))) - ;; Literal matching - ((string-prefix-p "=" pattern) - `(orderless-literal . ,(substring pattern 1))) - ((string-suffix-p "=" pattern) - `(orderless-literal . ,(substring pattern 0 -1))) - ;; Flex matching - ((string-prefix-p "~" pattern) - `(orderless-flex . ,(substring pattern 1))) - ((string-suffix-p "~" pattern) - `(orderless-flex . ,(substring pattern 0 -1)))))) - -(setup (:straight (topsy - :host github - :repo "alphapapa/topsy.el")) - (:hook-into prog-mode)) - -(setup (:straight (unfocused - :host github - :repo "duckwork/unfocused")) - (unfocused-mode +1)) - -(setup (:straight (vertico - :host github - :repo "minad/vertico" - :files ("*" "extensions/*" - (:exclude ".git")))) - - (:option resize-mini-windows 'grow-only - vertico-count-format nil - vertico-cycle t) - - (:with-map vertico-map - (:bind "" - (defun up-directory (arg) - "Move up a directory (delete backwards to /)." - (interactive "p") - (if (string-match-p "/." (minibuffer-contents)) - (zap-up-to-char (- arg) ?/) - (backward-kill-word arg))))) - - (if (boundp 'comp-deferred-compilation-deny-list) - (add-to-list 'comp-deferred-compilation-deny-list "vertico")) - - (vertico-mode +1) - - ;; Extensions! - (:also-load vertico-mouse) - (vertico-mouse-mode +1) - - ;; Prefix the current candidate with "> ". From Vertico wiki. - - (:advise vertico--format-candidate :around - (defun vertico-format@add-arrow (orig cand pref suf index start) - (setq cand (funcall orig cand pref suf index start)) - (concat (if (= vertico--index index) - (propertize "> " 'face 'vertico-current) - " ") - cand)))) - -(setup (:straight alert) - (:option alert-default-style (acdw/system - (:home 'libnotify) - (_ 'message)))) - -(setup (:straight async) - (:autoload (dired-async-mode :interactive t)) - (dired-async-mode +1) - - (add-hook 'dired-mode - (defun dired@disable-dired-async-mode-line () - (autoload 'dired-async--modeline-mode "dired-async.el" nil t) - (dired-async--modeline-mode -1)))) - -(setup (:straight avy) - (:global "C-:" #'avy-goto-char-timer - "C-c C-j" #'avy-resume) - - (:with-feature isearch - (:bind "C-'" #'avy-isearch))) - -(setup (:straight circe) - (require 'circe) - (require 'acdw-irc) - - (:option acdw-irc/left-margin 12 - acdw-irc/post-my-nick "-> " - circe-channel-killed-confirmation nil - circe-color-nicks-everywhere t - circe-default-nick "acdw" - circe-default-part-message "See You, Space Cowpokes . . ." - circe-default-user "acdw" - circe-format-action - (lambda (&rest plist) - (concat - (acdw-irc/margin-format "" "*" "*" t) - " " (plist-get plist :nick) " " (plist-get plist :body))) - circe-format-say - (lambda (&rest plist) - (concat - (acdw-irc/margin-format (plist-get plist :nick) "" " |" t) - " " (plist-get plist :body))) - circe-format-self-action - (lambda (&rest plist) - (concat - (acdw-irc/margin-format "" "-*" " *" t) - " " (plist-get plist :nick) " " (plist-get plist :body))) - circe-format-self-say - (lambda (&rest plist) - (concat - (acdw-irc/margin-format (plist-get plist :nick) "-" " >" t) - " " (plist-get plist :body))) - circe-highlight-nick-type 'sender - circe-network-options - `(("Libera Chat" - :channels ("#emacs" "#systemcrafters" "##webpals") - :sasl-username circe-default-nick - :sasl-password ,(acdw/make-password-fetcher - :host "libera.chat")) - ("Tilde Chat" :host "irc.tilde.chat" :port 6697 :use-tls t - :channels ("#meta" "#bread" "#dadjokes" "#team") - :sasl-username circe-default-nick - :sasl-password ,(acdw/make-password-fetcher - :host "tilde.chat")) - ("Casa" :host "m455.casa" :port 6697 :use-tls t - :channels ("#basement") - :sasl-username circe-default-nick - :sasl-password ,(acdw/make-password-fetcher - :host "m455.casa")) - ("Piss" :host "piss.hmm.st" :port 6697 :use-tls t)) - circe-reduce-lurker-spam t - circe-server-auto-join-default-type :after-auth) - - (custom-set-faces '(circe-nick-highlight-face - ((t (:inherit (modus-themes-hl-line)))) - :now)) - - (:bind "C-c C-p" #'circe-command-PART) - - (:advise circe-command-PART :after - (defun circe-command-PART@kill-buffer (&rest _) - (let ((circe-channel-killed-confirmation nil)) - (kill-buffer)))) - - (:with-mode circe-chat-mode - (:hook #'acdw/stop-paren-annoyances - (defun circe-chat@setup () - (lui-set-prompt - (concat (propertize (acdw-irc/margin-format (buffer-name) - "" - ">") - 'face 'circe-prompt-face - 'read-only t 'intangible t - 'cursor-intangible t) - " ")) - (enable-circe-color-nicks) - (enable-circe-display-images) - (enable-circe-new-day-notifier)))) - - (autoload 'circe-nick-color-reset "circe-color-nicks") - (add-hook 'modus-themes-after-load-theme-hook - #'circe-nick-color-reset) - - (:with-mode lui-mode - (:option lui-fill-column fill-column - lui-fill-type (repeat-string acdw-irc/left-margin " ") - lui-time-stamp-position 'right-margin - lui-time-stamp-format "%H:%M" - lui-track-behavior 'before-switch-to-buffer - lui-track-indicator 'fringe) - - (:hook (defun lui-mode@setup () - (setq-local fringes-outside-margins t - right-margin-width 5 - scroll-margin 0 - word-wrap t - wrap-prefix (repeat-string - acdw-irc/left-margin " ") - line-number-mode nil) - (enable-lui-track))))) - -(setup (:straight crux) - - (:global "C-x o" #'acdw/other-window-or-switch-buffer - "C-o" #'crux-smart-open-line - "M-o" #'crux-smart-open-line-above - "C-M-\\" #'crux-cleanup-buffer-or-region - "C-x 4 t" #'crux-transpose-windows) - - (when (fboundp 'repeat-mode) - (unless (boundp 'other-window-repeat-map) - (defvar other-window-repeat-map (make-sparse-keymap) - "A map for repeating `other-window' keys.")) - - (define-key other-window-repeat-map "o" - #'acdw/other-window-or-switch-buffer) - (define-key other-window-repeat-map "O" - (defun acdw/other-window-or-switch-buffer-backward () - (interactive) - (setq repeat-map 'other-window-repeat-map) - (acdw/other-window-or-switch-buffer -1))) - - (put 'acdw/other-window-or-switch-buffer - 'repeat-map 'other-window-repeat-map)) - - (crux-reopen-as-root-mode +1)) - -;; requires extension: -;; https://addons.mozilla.org/en-US/firefox/addon/edit-with-emacs1/ -(setup (:straight edit-server) - (when (and (daemonp) - (require 'edit-server nil :noerror)) - (edit-server-start) - - (:advise edit-server-make-frame :before - (defun edit-server@set-a-variable (&rest _) - (setq-local edit-server-frame-p t))))) - -(setup (:straight elfeed - elfeed-protocol) - (:option elfeed-use-curl t - elfeed-feeds `(("fever+https://acdw@mf.acdw.net" - :api-url "https://mf.acdw.net/fever/" - :password ,(acdw/make-password-fetcher - :host "mf.acdw.net")))) - - (elfeed-protocol-enable) - - (:with-mode elfeed-show-mode - (:hook (defun elfeed-show@setup () - (acdw/reading-mode))) - - ;; see https://irreal.org/blog/?p=8885 - (:bind "SPC" (defun elfeed-scroll-up-command (&optional arg) - "Scroll up or go to next feed item in Elfeed" - (interactive "^P") - (let ((scroll-error-top-bottom nil)) - (condition-case-unless-debug nil - (scroll-up-command arg) - (error (elfeed-show-next))))) - "S-SPC" (defun elfeed-scroll-down-command (&optional arg) - "Scroll up or go to next feed item in Elfeed" - (interactive "^P") - (let ((scroll-error-top-bottom nil)) - (condition-case-unless-debug nil - (scroll-down-command arg) - (error (elfeed-show-prev)))))))) - -(setup (:straight elisp-slime-nav) - (:hook-into emacs-lisp-mode - ielm-mode)) - -(setup (:straight embark) - (:global "C-." #'embark-act) - (:option prefix-help-command #'embark-prefix-help-command - (append display-buffer-alist) - '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*" - nil - (window-parameters (mode-line-format . none))) - embark-prompter #'embark-keymap-prompter - embark-verbose-indicator-display-action - '(display-buffer-at-bottom (window-height . fit-window-to-buffer))) - - (setq embark-action-indicator - (lambda (map _target) - (which-key--show-keymap "Embark" map nil nil 'no-paging) - #'which-key--hide-popup-ignore-command) - embark-become-indicator embark-action-indicator) - - (with-eval-after-loads (embark consult) - (:straight embark-consult) - (add-hook 'embark-collect-mode-hook - #'consult-preview-at-point-mode))) - -(setup (:straight epithet) - (dolist (hook '(Info-selection-hook - eww-after-render-hook - help-mode-hook - occur-mode-hook)) - (add-hook hook #'epithet-rename-buffer))) - -(setup (:straight eros) - (:hook-into emacs-lisp-mode)) - -(setup (:straight esh-autosuggest) - (:autoload esh-autosuggest-mode) - (:hook-into eshell-mode)) - -(setup (:straight expand-region) - (:global "C-=" #'er/expand-region - "C-SPC" - (defun acdw/set-mark-or-expand-region (arg) - "Set mark at point and activate, jump to mark, or expand region. -See `set-mark-command' and `expand-region'. - -With no prefix argument, either run `set-mark-command' on first -invocation and `er/expand-region' on each successive invocation. - -With any prefix argument -(e.g., \\[universal-argument] \\[set-mark-command]), act as with -`set-mark-command' (i.e., pop the mark). Don't care about -successive invocations." - (interactive "P") - (cond - ((or arg - (and set-mark-command-repeat-pop - (eq last-command 'pop-to-mark-command))) - (setq this-command 'set-mark-command) - (set-mark-command arg)) - ((eq last-command 'acdw/set-mark-or-expand-region) - (er/expand-region 1)) - (t (set-mark-command arg)))))) - -(setup (:straight flyspell-correct) - (:with-mode flyspell-mode - (:hook (defun flyspell@correct () - (:bind "C-;" #'flyspell-correct-wrapper) - (:unbind "C-," "C-." "C-M-i"))))) - -(setup (:straight gcmh) - (:option gcmh-idle-delay 'auto) - (gcmh-mode +1)) - -;; TODO: figure out a popper.el / shackle.el ... thing to fix this -(setup (:straight helpful) - (:option helpful-max-buffers 5) - (:global " f" #'helpful-callable - " v" #'helpful-variable - " k" #'helpful-key - " o" #'helpful-symbol)) - -(setup (:straight hungry-delete) - (:option hungry-delete-chars-to-skip " \t" - hungry-delete-join-reluctantly nil) - - (global-hungry-delete-mode +1) - - (:with-feature paredit - (:bind [remap paredit-backward-delete] - (defun acdw/paredit-hungry-delete-backward (arg) - (interactive "P") - (if (looking-back "[ \t]" 1) - (hungry-delete-backward (or arg 1)) - (paredit-backward-delete arg))) - - [remap paredit-forward-delete] - (defun acdw/paredit-hungry-delete-forward (arg) - (interactive "P") - (if (looking-at "[ \t]") - (hungry-delete-forward (or arg 1)) - (paredit-forward-delete arg)))))) - -(setup (:straight iscroll) - (define-globalized-minor-mode global-iscroll-mode iscroll-mode - (lambda () (iscroll-mode +1))) - - (global-iscroll-mode +1)) - -(setup (:straight lacarte) - (:global "" #'lacarte-execute-menu-command)) - -(setup (:straight link-hint) - ;; Browse web URLs with a browser with a prefix argument. - (dolist (type '(gnus-w3m-image-url - gnus-w3m-url - markdown-link - mu4e-attachment - mu4e-url - notmuch-hello - nov-link - org-link - shr-url - text-url - w3m-link - w3m-message-link)) - (link-hint-define-type type - :open-secondary browse-url-secondary-browser-function)) - - (:option link-hint-avy-style 'at) - (:global "C-;" - (defun acdw/link-hint-open-link (arg) - "Open a link using `link-hint-open-link', prefix-aware. -That is, a prefix argument (\\[universal-argument]) will open the -browser defined in `browse-url-secondary-browser-function'." - (interactive "P") - (avy-with link-hint-open-link - (link-hint--one (if arg :open-secondary :open)))))) - -(setup (:straight lua-mode) - (:file-match (rx ".lua" eos))) - -(setup (:straight macrostep) - (:with-mode emacs-lisp-mode - (:bind "C-c e" #'macrostep-expand))) - -(setup (:straight magit) - (:global "C-c g" #'magit-status) - - (:option magit-display-buffer-function - (defun magit-display-buffer-same-window (buffer) - "Display BUFFER in the selected window like God intended." - (display-buffer buffer '(display-buffer-same-window))) - magit-popup-display-buffer-action '((display-buffer-same-window)) - magit-refresh-status-buffer nil)) - -(setup (:straight marginalia) - (:option marginalia-annotators '(marginalia-annotators-heavy - marginalia-annotators-light)) - (marginalia-mode +1)) - -(setup (:straight markdown-mode) - (dolist (cell '(("README\\.md\\'" . gfm-mode) - ("\\.md\\'" . markdown-mode) - ("\\.markdown\\'" . markdown-mode))) - (add-to-list 'auto-mode-alist cell)) - - (when (executable-find "markdownfmt") - (with-eval-after-load 'apheleia - (:option (append apheleia-formatters) '(markdownfmt . ("markdownfmt")) - (append apheleia-mode-alist) '(markdown-mode . markdownfmt) - (append apheleia-mode-alist) '(gfm-mode . markdownfmt))))) - -(setup (:straight mwim) - (:global "C-a" #'mwim-beginning - "C-e" #'mwim-end)) - -(setup (:straight nov) - (:option nov-text-width fill-column) - (:file-match (rx ".epub" eos))) - -(setup (:straight olivetti) - (:option olivetti-body-width (+ fill-column 4) - olivetti-minimum-body-width fill-column) - - (:hook (defun olivetti-mode@setup () - (if olivetti-mode - (setq-local indicate-empty-lines nil - indicate-buffer-boundaries nil) - (acdw/setup-fringes))))) + (defun acdw/orderless-dispatch (pattern _index _total) + "My custom dispatcher for `orderless'." + (cond + ;; Ensure that $ works with Consult commands, which add disambiguation + ;; suffixes -- see `fix-dollar' + ((string-suffix-p "$" pattern) + `(orderless-regexp . ,(concat (substring pattern 0 -1) + "[\x100000-\x10FFFD]*$"))) + ;; File extensions + ((string-match-p "\\`\\.." pattern) + `(orderless-regexp . ,(concat "\\." (substring pattern 1) + "[\x100000-\x10FFFD]*$"))) + ;; Ignore single ! + ((string= "!" pattern) + `(orderless-literal . "")) + ;; Character folding + ((string-prefix-p "%" pattern) + `(char-fold-to-regexp . ,(substring pattern 1))) + ((string-suffix-p "%" pattern) + `(char-fold-to-regexp . ,(substring pattern 0 -1))) + ;; Without literal + ((string-prefix-p "!" pattern) + `(orderless-without-literal . ,(substring pattern 1))) + ((string-suffix-p "!" pattern) + `(orderless-without-literal . ,(substring pattern 0 -1))) + ;; Initialism matching + ((string-prefix-p "`" pattern) + `(orderless-initialism . ,(substring pattern 1))) + ((string-suffix-p "`" pattern) + `(orderless-initialism . ,(substring pattern 0 -1))) + ;; Literal matching + ((string-prefix-p "=" pattern) + `(orderless-literal . ,(substring pattern 1))) + ((string-suffix-p "=" pattern) + `(orderless-literal . ,(substring pattern 0 -1))) + ;; Flex matching + ((string-prefix-p "~" pattern) + `(orderless-flex . ,(substring pattern 1))) + ((string-suffix-p "~" pattern) + `(orderless-flex . ,(substring pattern 0 -1)))))) (setup (:straight org org-contrib) @@ -1598,8 +1289,8 @@ browser defined in `browse-url-secondary-browser-function'." "C-c C-p" #'acdw/org-previous-heading-widen) (with-eval-after-load 'org-export - (add-to-list 'org-export-filter-final-output-functions - #'org-export-remove-zero-width-spaces)) + (:option (append org-export-filter-final-output-functions) + #'org-export-remove-zero-width-spaces)) (:hook variable-pitch-mode olivetti-mode @@ -1622,60 +1313,247 @@ browser defined in `browse-url-secondary-browser-function'." (setup (:straight org-appear) (:hook-into org-mode)) -(setup (:straight package-lint)) +(setup (:straight package-lint)) + +(setup (:straight package-lint-flymake)) + +(setup page + (:option page-delimiter + (rx bol (or "\f" ";;;") + (not (any "#")) (* not-newline) "\n" + (* (* blank) (opt ";" (* not-newline)) "\n"))) + + (defun recenter-to-top (&rest _) + "Recenter the cursor to the top of the window." + (when (called-interactively-p 'any) + (recenter (if (or (null scroll-margin) + (zerop scroll-margin)) + 3 + scroll-margin)))) + + (:advise forward-page :after #'recenter-to-top + backward-page :after #'recenter-to-top) + + ;; I'm not sure where this is in /my/ version of Emacs + (defvar page-navigation-repeat-map + (let ((map (make-sparse-keymap))) + (define-key map "]" #'forward-page) + (define-key map "[" #'backward-page) + map) + "Keymap to repeat page navigation key sequences. Used in `repeat-mode'.") + + (put 'forward-page 'repeat-map 'page-navigation-repeat-map) + (put 'backward-page 'repeat-map 'page-navigation-repeat-map)) + +(setup (:straight page-break-lines) + (global-page-break-lines-mode +1)) + +(setup (:straight paredit) + ;; I don't use paredit-splice-sexp much, and it stomps on isearch. + (:unbind "M-s") + + (defun paredit@setup () + "Correct weirdnesses and set up paredit mode." + (:with-map lisp-mode-shared-map + (:bind "DEL" #'paredit-backward-delete + "C-M-;" #'comment-or-uncomment-sexp + "C-" #'paredit-backward-kill-word)) + (paredit-mode +1)) + + (dolist (mode lispy-modes) + (add-hook (intern (concat (symbol-name mode) "-hook")) + #'paredit@setup)) + + (:also-load 'eldoc) + (eldoc-add-command 'paredit-backward-delete 'paredit-close-round)) + +(setup (:straight paren-face) + (dolist (mode lispy-modes) + (add-hook (intern (concat (symbol-name mode) "-hook")) #'paren-face-mode))) + +(setup (:straight-if (pdf-tools + :host github + :repo "vedang/pdf-tools") + (acdw/system :home)) + (:file-match (rx ".pdf" eos)) + (pdf-loader-install)) + +(setup (:straight persistent-scratch) + (:option persistent-scratch-backup-directory (acdw/dir "scratch" t) + persistent-scratch-keep-n-newest-backups 12) + + (persistent-scratch-setup-default) + + (mapc (lambda (buf) + (with-current-buffer buf + (when (funcall persistent-scratch-scratch-buffer-p-function) + (persistent-scratch-mode +1)))) + (buffer-list))) + +(setup (:straight-if pkgbuild-mode + (executable-find "makepkg")) + (:file-match "PKGBUILD")) + +(setup (:straight powerthesaurus) + (:global "C-c l t" #'powerthesaurus-lookup-word-dwim)) + +(setup prog + (:option show-paren-delay 0 + show-paren-style 'mixed + show-paren-when-point-inside-paren t + show-paren-when-point-in-periphery t + smie-indent-basic tab-width) + + (:hook show-paren-mode + electric-pair-local-mode + acdw/setup-fringes + + (defun flymake-mode-except () + "Turn on flymake mode, except in some modes." + (let ((no-flymake-modes '(emacs-lisp-mode))) + (unless (or (member major-mode no-flymake-modes) + (apply #'derived-mode-p no-flymake-modes)) + (flymake-mode-on)))) + + (defun prog-mode@auto-fill () + (setq-local comment-auto-fill-only-comments t) + (turn-on-auto-fill))) + + (add-hook 'after-save-hook + #'executable-make-buffer-file-executable-if-script-p)) + +(setup (:require recentf) + (:option recentf-save-file (acdw/dir "recentf.el") + recentf-max-menu-items 100 + recentf-max-saved-items nil + recentf-auto-cleanup 'mode + (append recentf-exclude) (acdw/dir)) + + (:advise dired-rename-file :after #'rjs/recentf-rename-notify) + + (recentf-mode +1)) + +(setup repeat + ;; new for Emacs 28! + (:only-if (fboundp #'repeat-mode)) + + (:option repeat-exit-key "g" + repeat-exit-timeout 5) + + (repeat-mode +1)) + +(setup (:straight restart-emacs) + (defun emacs-upgrade (&optional update-packages) + "Pull config, upgrade packages, restart Emacs." + (interactive "P") + (emacs-git-pull-config) + (when update-packages + (require 'straight-x) + (straight-x-pull-all)) + (restart-emacs))) + +(setup (:require savehist) + (:option history-length t + history-delete-duplicates t + savehist-autosave-interval 60 + savehist-file (acdw/dir "savehist.el")) + + (dolist (var '(extended-command-history + global-mark-ring + kill-ring + regexp-search-ring + search-ring + mark-ring)) + (:option (append savehist-additional-variables) var)) + + (savehist-mode +1)) + +(setup saveplace + (:option save-place-file (acdw/dir "places.el") + save-place-forget-unreadable-files (acdw/system :home)) + + (save-place-mode +1)) + +(setup scratch + (:option inhibit-startup-screen t + initial-buffer-choice t + initial-scratch-message "" + ;; (concat ";; Howdy, " + ;; (nth 0 (split-string + ;; user-full-name)) + ;; "! " + ;; "Welcome to GNU Emacs.\n\n") + initial-major-mode 'emacs-lisp-mode) + + (add-hook 'kill-buffer-query-functions + (defun kill-buffer-query@immortal-scratch () + (if (eq (current-buffer) (get-buffer "*scratch*")) + (progn (bury-buffer) + nil) + t)))) + +(setup scrolling + (:option auto-window-vscroll nil + fast-but-imprecise-scrolling t + scroll-margin 3 + scroll-conservatively 101 + scroll-preserve-screen-position 1)) + +(setup selection + (:option save-interprogram-paste-before-kill t + yank-pop-change-selection t + x-select-enable-clipboard t + x-select-enable-primary t + mouse-drag-copy-region t + kill-do-not-save-duplicates t) -(setup (:straight package-lint-flymake)) + (delete-selection-mode +1)) -(setup (:straight page-break-lines) - (global-page-break-lines-mode +1)) +(setup (:require server) + (unless (server-running-p) + (server-start))) -(setup (:straight paredit) - ;; I don't use paredit-splice-sexp much, and it stomps on isearch. - (:unbind "M-s") +(setup sh-mode + (:option sh-basic-offset tab-width + sh-indent-after-case 0 + sh-indent-for-case-alt '+ + sh-indent-for-case-label 0) - (defun paredit@setup () - "Correct weirdnesses and set up paredit mode." - (:with-map lisp-mode-shared-map - (:bind "DEL" #'paredit-backward-delete - "C-M-;" #'comment-or-uncomment-sexp - "C-" #'paredit-backward-kill-word)) - (paredit-mode +1)) - - (dolist (mode lispy-modes) - (add-hook (intern (concat (symbol-name mode) "-hook")) - #'paredit@setup)) + (:local-set indent-tabs-mode t) - (:also-load 'eldoc) - (eldoc-add-command 'paredit-backward-delete 'paredit-close-round)) + (when (executable-find "shfmt") + (with-eval-after-load 'apheleia + (:option (append apheleia-formatters) '(shfmt . ("shfmt")) + (append apheleia-mode-alist) '(sh-mode . shfmt)))) -(setup (:straight paren-face) - (dolist (mode lispy-modes) - (add-hook (intern (concat (symbol-name mode) "-hook")) #'paren-face-mode))) + (when (executable-find "shellcheck") + (:straight flymake-shellcheck) + (:hook flymake-mode + flymake-shellcheck-load))) -(setup (:straight persistent-scratch) - (:option persistent-scratch-backup-directory (acdw/dir "scratch" t) - persistent-scratch-keep-n-newest-backups 12) - - (persistent-scratch-setup-default) - - (mapc (lambda (buf) - (with-current-buffer buf - (when (funcall persistent-scratch-scratch-buffer-p-function) - (persistent-scratch-mode +1)))) - (buffer-list))) +(setup shell-command + (:option shell-command-switch (acdw/system + ;; I should be testing on some variable + (:home "-csi") + (:work "-c")) + shell-command-prompt-show-cwd t + shell-command-default-error-buffer "*shell-command-errors*")) -(setup (:straight powerthesaurus) - (:global "C-c l t" #'powerthesaurus-lookup-word-dwim)) +(setup (:straight (shell-command+ + :host nil + :repo "https://git.sr.ht/~pkal/shell-command-plus")) + (:option shell-command-prompt "$ ") + (:with-feature dired + (:bind "M-!" shell-command+)) + (:global "M-!" shell-command+)) -(setup (:straight restart-emacs) - (defun emacs-upgrade (&optional update-packages) - "Pull config, upgrade packages, restart Emacs." - (interactive "P") - (emacs-git-pull-config) - (when update-packages - (require 'straight) - (straight-pull-all)) - (restart-emacs))) +(setup shr + (:option shr-width fill-column + shr-max-width fill-column + shr-max-image-proportion 0.6 + shr-image-animate t + shr-discard-aria-hidden t + shr-folding-mode t)) (setup (:straight simple-modeline minions) @@ -1716,15 +1594,60 @@ browser defined in `browse-url-secondary-browser-function'." (simple-modeline-mode +1)) +(setup (:straight-if sly + (progn + (defvar acdw/lisps + (let (lisps) + (dolist (lisp '("sbcl" ; TODO: add more lisps + "clisp")) + (when-let (binary (executable-find lisp)) + (push binary lisps))) + (nreverse lisps))) + acdw/lisps)) + (:also-load sly-autoloads) + (:straight clhs) + + (:option inferior-lisp-program acdw/lisp-bin + sly-kill-without-query-p t) + + (:with-feature sly-mrepl + (defun sly-mrepl-return-at-end () + (interactive) + (if (<= (point-max) (point)) + (sly-mrepl-return) + (if (bound-and-true-p paredit-mode) + (paredit-newline) + (electric-newline-and-maybe-indent)))) + + (dolist (key '("RET" "")) + (:bind key #'sly-mrepl-return-at-end)) + + (:bind "C-c C-c" #'sly-mrepl-return))) + (setup (:straight ssh-config-mode) - (dolist (spec '(("/\\.ssh/config\\'" . ssh-config-mode) - ("/sshd?_config\\'" . ssh-config-mode) - ("/knownhosts\\'" . ssh-known-hosts-mode) - ("/authorized_keys2?\\'" . ssh-authorized-keys-mode))) - (add-to-list 'auto-mode-alist spec)) + (:file-match (rx "/.ssh/config" eos) + (rx "/ssh" (? "d") "_config" eos)) + + (:with-mode ssh-known-hosts-mode + (:file-match (rx "/knownhosts" eos))) + + (:with-mode ssh-authorized-keys-mode + (:file-match (rx "/authorized_keys" (? "2") eos))) (:hook #'turn-on-font-lock)) +(setup (:straight-if systemd + (executable-find "systemd"))) + +(setup text + (:hook turn-on-auto-fill + acdw/setup-fringes)) + +(setup (:straight (topsy + :host github + :repo "alphapapa/topsy.el")) + (:hook-into prog-mode)) + (setup (:straight typo) ;; Enable C-c 8 map in all buffers @@ -1747,7 +1670,6 @@ browser defined in `browse-url-secondary-browser-function'." ;; consideration, not an input consideration. (I suppose you could make ;; the argument that all of these are typographical considerations, but ;; .. bleh.) - (:bind "'" (define-typo-cycle typo-cycle-apostrophe "Cycle through apostrophe-like graphemes. If used with a numeric prefix argument N, N apostrophes will be inserted." @@ -1771,42 +1693,206 @@ If used with a numeric prefix argument N, N backticks will be inserted." (setup (:straight unfill)) +(setup (:straight (unfocused + :host github + :repo "duckwork/unfocused")) + (unfocused-mode +1)) + +(setup uniquify + (:option uniquify-buffer-name-style 'forward + uniquify-separator path-separator + uniquify-after-kill-buffer-p t + uniquify-ignore-buffers-re "^\\*")) + +(setup variable-pitch-mode + ;; I might want to change this to `buffer-face-mode-hook'... + (:advise variable-pitch-mode :after + (defun variable-pitch-mode@setup (&rest _) + "Set up `variable-pitch-mode' with my customizations." + (display-fill-column-indicator-mode (if buffer-face-mode + -1 + +1))))) + +(setup (:straight (vertico + :host github + :repo "minad/vertico" + :files ("*" "extensions/*" + (:exclude ".git")))) + + (:option resize-mini-windows 'grow-only + vertico-count-format nil + vertico-cycle t) + + (:with-map vertico-map + (:bind "" + (defun up-directory (arg) + "Move up a directory (delete backwards to /)." + (interactive "p") + (if (string-match-p "/." (minibuffer-contents)) + (zap-up-to-char (- arg) ?/) + (backward-kill-word arg))))) + + (when (boundp 'native-comp-deferred-compilation-deny-list) + (add-to-list 'native-comp-deferred-compilation-deny-list "vertico")) + + (vertico-mode +1) + + ;; Extensions! + (:also-load vertico-mouse) + (vertico-mouse-mode +1) + + ;; Prefix the current candidate with "> ". From Vertico wiki. + (:advise vertico--format-candidate :around + (defun vertico-format@add-arrow (orig cand pref suf index start) + (setq cand (funcall orig cand pref suf index start)) + (concat (if (= vertico--index index) + (propertize "> " 'face 'vertico-current) + " ") + cand)))) + +(setup view + (:option view-read-only t) + + (:hook (defun acdw/read-view-mode () + (acdw/reading-mode (if view-mode +1 -1))))) + (setup (:straight visual-regexp) (:global "M-%" #'vr/query-replace)) -(setup (:straight wc-mode) ; TODO: move some of this stuff around +(setup (:straight-if vterm + (acdw/system :home))) + +(setup w32 + (:option w32-allow-system-shell t + w32-pass-lwindow-to-system nil + w32-lwindow-modifier 'super + w32-pass-rwindow-to-system nil + w32-rwindow-modifier 'super + w32-pass-apps-to-system nil + w32-apps-modifier 'hyper)) +(setup (:straight wc-mode) (:option wc-modeline-format "[%tww]" wc-idle-wait 2) (:hook-into text-mode)) -(setup (:straight web-mode) - (:option css-level-offset 2 - js-indent-level 2 - sgml-indent-offset 2) +(setup (:straight web-mode) + (:option css-level-offset 2 + js-indent-level 2 + sgml-indent-offset 2) + + (:file-match (rx ".htm" (? "l") eos) + (rx "." (? "tpl.") "php" eos) + (rx "." (| "asp" "gsp" "jsp") eos) + (rx "." (| "ascx" "aspx") eos) + (rx ".erb" eos) + (rx ".mustache" eos))) + +(setup (:straight wgrep)) + +(setup (:straight which-key) + (:option which-key-show-early-on-C-h t + which-key-idle-delay 1 + which-key-idle-secondary-delay 0.5 + which-key-sort-order 'which-key-prefix-then-key-order) + + (:global "C-h m" #'which-key-show-major-mode) + + (which-key-setup-side-window-right-bottom) + (which-key-mode +1)) + +(setup whitespace + (:option whitespace-style + '(empty indentation space-before-tab space-after-tab) + indent-tabs-mode nil + tab-width 4 + backward-delete-char-untabify-method 'hungry) + + (:global "M-SPC" #'cycle-spacing)) + +(setup (:straight whitespace-cleanup-mode) + (global-whitespace-cleanup-mode +1)) + +(setup windmove + (:option windmove-wrap-around t) + (:global + ;; moving + "C-x 4 " #'windmove-left + "C-x 4 " #'windmove-right + "C-x 4 " #'windmove-up + "C-x 4 " #'windmove-down + ;; swapping + "C-x 4 S-" #'windmove-swap-states-left + "C-x 4 S-" #'windmove-swap-states-right + "C-x 4 S-" #'windmove-swap-states-up + "C-x 4 S-" #'windmove-swap-states-down) + + (when (fboundp 'repeat-mode) + (defvar windmove-repeat-map + (let ((map (make-sparse-keymap))) + ;; moving + (define-key map [left] #'windmove-left) + (define-key map [right] #'windmove-right) + (define-key map [up] #'windmove-up) + (define-key map [down] #'windmove-down) + ;; swapping + (define-key map [S-left] #'windmove-swap-states-left) + (define-key map [S-right] #'windmove-swap-states-right) + (define-key map [S-up] #'windmove-swap-states-up) + (define-key map [S-down] #'windmove-swap-states-down) + map) + "Keymap to repeat various `windmove' sequences. Used in `repeat-mode'.") + + (dolist (sym '(windmove-left + windmove-right + windmove-up + windmove-down + windmove-swap-states-left + windmove-swap-states-right + windmove-swap-states-up + windmove-swap-states-down)) + (put sym 'repeat-map 'windmove-repeat-map)))) + +(setup window + (require 'acdw-bell) + (:option Man-notify-method 'pushy + display-buffer-alist ; from FrostyX + '(("shell.*" (display-buffer-same-window) ()) + (".*" (display-buffer-reuse-window + display-buffer-same-window) + (reusable-frames . t))) + recenter-positions '(top middle bottom) + ring-bell-function (lambda () + (acdw-bell/flash-mode-line + (acdw/system :home))) + tab-bar-show 1 + use-dialog-box nil + use-file-dialog nil + visible-bell nil) - (:file-match "\\.\\(p\\|dj\\)?html\\'" - "\\.html?\\'" - "\\.\\(tpl\\.\\)?php\\'" - "\\.[agj]sp\\'" - "\\.as[cp]x\\'" - "\\.erb\\'" - "\\.mustache\\'")) + (tooltip-mode -1)) -(setup (:straight which-key) - (:option which-key-show-early-on-C-h t - which-key-idle-delay 1 - which-key-idle-secondary-delay 0.5 - which-key-sort-order 'which-key-prefix-then-key-order) +(setup winner + ;; see https://lists.gnu.org/archive/html/emacs-devel/2021-08/msg00888.html + (:global "C-x 4 C-/" #'winner-undo + "C-x 4 /" #'winner-undo + "C-x 4 C-?" #'winner-redo + "C-x 4 ?" #'winner-redo) - (:global "C-h m" #'which-key-show-major-mode) - - (which-key-setup-side-window-right-bottom) - (which-key-mode +1)) + ;; add `winner-undo' and `winner-redo' to `repeat-mode' + (when (fboundp 'repeat-mode) + (defvar winner-mode-repeat-map + (let ((map (make-sparse-keymap))) + (define-key map "/" #'winner-undo) + (define-key map "?" #'winner-redo) + map) + "Keymap to repeat `winner-mode' sequences. Used in `repeat-mode'.") -(setup (:straight whitespace-cleanup-mode) - (global-whitespace-cleanup-mode +1)) + (put 'winner-undo 'repeat-map 'winner-mode-repeat-map) + (put 'winner-redo 'repeat-map 'winner-mode-repeat-map)) + + (winner-mode +1)) (setup (:straight winum) (:option winum-scope 'frame-local @@ -1834,154 +1920,93 @@ If used with a numeric prefix argument N, N backticks will be inserted." (winum-mode +1)) -(setup (:straight xr)) - -(setup (:straight zzz-to-char) - - (:global "M-z" - (defun acdw/zzz-up-to-char (prefix) - "Call `zzz-up-to-char' or `zzz-to-char', PREFIX-depending." - (interactive "P") - (if prefix - (call-interactively #'zzz-to-char) - (call-interactively #'zzz-up-to-char))))) - -(setup (:straight-if (pdf-tools - :host github - :repo "vedang/pdf-tools") - (acdw/system :home)) - (:file-match (rx ".pdf" eos)) - (pdf-loader-install)) - -(setup (:straight-if affe - (and (or (executable-find "fd") - (executable-find "find")) - (executable-find "rg"))) - ;; Keys are bound in `acdw/sensible-grep' and `acdw/sensible-find' - (:option affe-regexp-compiler - (defun affe-orderless-regexp-compiler (input _type) - (setq input (orderless-pattern-compiler input)) - (cons input (lambda (str) (orderless--highlight input str)))))) - -(setup (:straight-if ahk-mode - (acdw/system :work))) - -;; TODO: look into emms or something related for this -(setup (:straight-if eradio - (executable-find "mpv")) +(setup x-emacs + ;; "Et cetera" settings + ;; This should stay as /minimal/ as possible. Anything that can go somewhere + ;; else /should/ go there. (:option - eradio-player '("mpv" "--no-video" "--no-terminal") - eradio-channels `(("KLSU" . - "http://130.39.238.143:8010/stream.mp3") - ("Soma FM Synphaera" . - "https://somafm.com/synphaera256.pls") - ("SomaFM BAGel Radio" . - "https://somafm.com/bagel.pls") - ("SomaFM Boot Liquor" . - "https://somafm.com/bootliquor320.pls") - ("SomaFM Deep Space One" . - "https://somafm.com/deepspaceone.pls") - ("SomaFM Fluid" . - "https://somafm.com/fluid.pls") - ("SomaFM Underground 80s" . - "https://somafm.com/u80s256.pls") - ("WBRH: Jazz & More" . - "http://wbrh.streamguys1.com/wbrh-mp3") - ("KBRH Blues & Rhythm Hits" . - "http://wbrh.streamguys1.com/kbrh-mp3") - ("WRKF HD-2" . - ,(concat "https://playerservices.streamtheworld.com/" - "api/livestream-redirect/WRKFHD2.mp3")) - ("WRKF: NPR for the Capital Region" . - ,(concat "https://playerservices.streamtheworld.com/" - "api/livestream-redirect/WRKFFM.mp3")) - ("BadRadio: 24/7 PHONK" . - "https://s2.radio.co/s2b2b68744/listen") - ("tilderadio" . - "https://radio.tildeverse.org/radio/8000/radio.ogg") - ("vantaradio" . - "https://vantaa.black/radio"))) - (:global "C-c r r" #'eradio-play ; mnemonic: radio - "C-c r s" #'eradio-stop ; mnemonic: stop - "C-c r p" #'eradio-toggle ; mnemonic: play/pause - )) + attempt-orderly-shutdown-on-fatal-signal nil + attempt-stack-overflow-recovery nil + echo-keystrokes 0.01 + find-function-C-source-directory (acdw/find-emacs-source) + kill-read-only-ok t + load-prefer-newer t + native-comp-async-report-warnings-errors nil + set-mark-command-repeat-pop t) -(setup (:straight-if exec-path-from-shell - (acdw/system :home)) - (when (daemonp) - (exec-path-from-shell-initialize))) + (when (fboundp 'command-completion-default-include-p) + (setq read-extended-command-predicate + #'command-completion-default-include-p)) -(setup (:straight-if fennel-mode - (executable-find "fennel")) - (:autoload (fennel-repl :interactive t)) - (:file-match (rx ".fnl" eos))) + (defvar case-map (make-sparse-keymap) + "A keymap for setting case in various ways.") + (global-set-key (kbd "C-c c") case-map) -(setup (:straight-if geiser - (progn - (defvar acdw/schemes - (let (schemes) - (dolist (scheme '(("scheme" . geiser-chez) ; chez - ("petite" . geiser-chez) ; petite - ("csi" . geiser-chez) ; chicken - ("gsi" . geiser-gambit) - ("gosh" . geiser-gauche) - ("guile" . geiser-guile) - ("kawa" . geiser-kawa) - ("mit-scheme" . geiser-mit) - ("racket" . geiser-racket) - ("stklos" . geiser-stklos))) - (when-let (binary (executable-find (car scheme))) - (push binary schemes) - ;; and install the proper helper package - (straight-use-package (cdr scheme)))) - (nreverse schemes))) - acdw/schemes)) - (:file-match (rx ".rkt" eos) - (rx ".scm" eos))) + (defvar lookup-map (make-sparse-keymap) + "A keymap for looking up things.") + (global-set-key (kbd "C-c l") lookup-map) + + (:global "M-=" #'count-words + "C-w" #'kill-region-or-backward-word + "C-c c c" #'capitalize-dwim + "C-c c t" #'titlecase-dwim + "C-c c u" #'upcase-dwim + "C-c c l" #'downcase-dwim + "C-c d" #'acdw/insert-iso-date + "M-`" nil) -(setup (:straight-if ledger-mode - (executable-find "ledger"))) + ;; toggle bindings + (defvar toggle-map (make-sparse-keymap) + "A keymap for toggling!") + (global-set-key (kbd "C-c t") toggle-map) -(setup (:straight-if pkgbuild-mode - (executable-find "makepkg")) - (:file-match "PKGBUILD")) + (:with-map toggle-map + (:bind "c" #'column-number-mode + "l" #'display-line-numbers-mode + "d" #'toggle-debug-on-error)) -(setup (:straight-if sly - (progn - (defvar acdw/lisps - (let (lisps) - (dolist (lisp '("sbcl" ; TODO: add more lisps - "clisp")) - (when-let (binary (executable-find lisp)) - (push binary lisps))) - (nreverse lisps))) - acdw/lisps)) - (:also-load sly-autoloads) - (:straight clhs) - - (:option inferior-lisp-program acdw/lisp-bin - sly-kill-without-query-p t) + (defalias 'forward-word-with-case 'forward-word + "Alias for `forward-word' for use in `case-repeat-map'.") + (defalias 'backward-word-with-case 'backward-word + "Alias for `backward-word for use in `case-repeat-map'.") - (defun sly-mrepl-return-at-end () - (interactive) - (if (<= (point-max) (point)) - (sly-mrepl-return) - (if (bound-and-true-p paredit-mode) - (paredit-newline) - (electric-newline-and-maybe-indent)))) + (defvar case-repeat-map + (let ((map (make-sparse-keymap))) + (define-key map "c" #'capitalize-word) + (define-key map "u" #'upcase-word) + (define-key map "l" #'downcase-word) + ;; movement + (define-key map "f" #'forward-word-with-case) + (define-key map "b" #'backward-word-with-case) + map) + "A map to repeat word-casing commands. For use with `repeat-mode'.") - (:with-feature sly-mrepl - (dolist (key '("RET" "")) - (:bind key #'sly-mrepl-return-at-end)) - (:bind "C-c C-c" #'sly-mrepl-return))) + (dolist (command '(capitalize-word + capitalize-dwim + upcase-word + upcase-dwim + downcase-word + downcase-dwim + forward-word-with-case + backward-word-with-case)) + (put command 'repeat-map 'case-repeat-map)) -(setup (:straight-if systemd - (executable-find "systemd"))) + (add-hook 'after-make-frame-functions + (defun after-make-frame@maximize (frame) + (unless (bound-and-true-p edit-server-frame-p) + (toggle-frame-maximized frame))))) -(setup (:straight-if vterm - (acdw/system :home))) +(setup (:straight xr)) -(setup (:straight wgrep)) +(setup (:straight zzz-to-char) + + (:global "M-z" + (defun acdw/zzz-up-to-char (prefix) + "Call `zzz-up-to-char' or `zzz-to-char', PREFIX-depending." + (interactive "P") + (if prefix + (call-interactively #'zzz-to-char) + (call-interactively #'zzz-up-to-char))))) ;;; init.el ends here diff --git a/lisp/acdw.el b/lisp/acdw.el index 8db7fea..cf8914f 100644 --- a/lisp/acdw.el +++ b/lisp/acdw.el @@ -19,7 +19,9 @@ ;; functions for me, acdw. ;;; Code: - + +(require 'cl-lib) + ;;; Variables (defconst acdw/system @@ -242,10 +244,12 @@ With a prefix argument N, (un)comment that many sexps." ;;; Sort sexps ;; from https://github.com/alphapapa/unpackaged.el#sort-sexps +;; and https://github.com/alphapapa/unpackaged.el/issues/20 -(defun sort-sexps (beg end) +(defun sort-sexps (beg end &optional key) "Sort sexps in region. -Comments stay with the code below." +Comments stay with the code below. KEY is a function to sort by, +e.g. (lambda (sexp) (symbol-name (car sexp)))" (interactive "r") (cl-flet ((skip-whitespace () (while (looking-at (rx (1+ (or space "\n")))) (goto-char (match-end 0)))) @@ -270,11 +274,16 @@ Comments stay with the code below." for end = (point-marker) while sexp ;; Collect the real string, then one used for sorting. - collect (cons (buffer-substring (marker-position start) (marker-position end)) + collect (cons (buffer-substring (marker-position start) + (marker-position end)) (save-excursion (goto-char (marker-position start)) (skip-both) - (buffer-substring (point) (marker-position end)))) + (if key + (funcall key sexp) + (buffer-substring + (point) + (marker-position end))))) into sexps collect (cons start end) into markers -- cgit 1.4.1-21-gabe81