From 5380cfb76277c64dd264d5312f5146d6cac96f97 Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Wed, 15 Sep 2021 23:32:16 -0500 Subject: Re-sort init.el --- init.el | 1972 +++++++++++++++++++++++++++++----------------------------- lisp/acdw.el | 21 +- 2 files changed, 1010 insertions(+), 983 deletions(-) diff --git a/init.el b/init.el index 4a4c57c..7c40722 100644 --- a/init.el +++ b/init.el @@ -20,10 +20,50 @@ ;; NOTE that some of the names in `setup' forms are arbitrary. -(setup (:straight (0x0 - :host gitlab - :repo "willvaughn/emacs-0x0")) - (:option 0x0-default-server 'ttm)) +(setup (:require auth-source) + (:option auth-sources '("~/.authinfo" "~/.authinfo.gpg"))) + +(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 (:require goto-addr) + (if (fboundp #'global-goto-address-mode) + (global-goto-address-mode) + (add-hook 'after-change-major-mode-hook #'goto-address-mode))) + +(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 (: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 (:require server) + (unless (server-running-p) + (server-start))) (setup Info (:hook #'variable-pitch-mode @@ -51,79 +91,45 @@ (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!!!" +In short, 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"))) + (sort-sexps + (point-min) (point-max) + (lambda (sexp) + (format "%S" (cadr sexp))) + (lambda (s1 s2) ; oh god, this is worse. + (let* ((s1 (cdr s1)) (s2 (cdr s2)) ; for the strings themselves + (s1-require (string-match ":require" s1)) + (s2-require (string-match ":require" s2)) + (s1-straight (string-match ":straight" s1)) + (s2-straight (string-match ":straight" s2)) + (s1-bare (not (or s1-require s1-straight))) + (s2-bare (not (or s2-require s2-straight)))) + (cond + ;; if both are the same, sort regular style + ((or (and s1-require s2-require) + (and s1-bare s2-bare)) + (string< s1 s2)) + ((and s1-straight s2-straight) + (let* ((r (rx ":straight" (? "-if") (* space) (? "("))) + (s1 (replace-regexp-in-string r "" s1)) + (s2 (replace-regexp-in-string r "" s2))) + (message "'%S' '%S'" s1 s2) + (string< s1 s2))) + ;; requires should go first + ((and s1-require (not s2-require)) t) + ((and (not s1-require) s2-require) nil) + ;; straights should go last + ((and s1-straight (not s2-straight)) nil) + ((and (not s1-straight) s2-straight) t) + ;; else, just sort em. + (t (string< s1 s2))))))))) (setup autorevert (:option global-auto-revert-non-file-buffers t auto-revert-verbose nil) (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) @@ -186,146 +192,6 @@ AKA, DO NOT USE THIS FUNCTION!!!" (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 'message - 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" - "#emacs") - :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")) - ("Pissnet" :host "piss.hmm.st" :port 6697 :use-tls t - :channels ("#i-just-peed") - :sasl-username ,circe-default-nick - :sasl-password ,(acdw/make-password-fetcher - :host "piss.hmm.st")) - ;; TODO: irc.chat.twitch.tv - ) - circe-reduce-lurker-spam t - circe-server-auto-join-default-type :after-auth) - - ;; (:face circe-nick-highlight-face - ;; ((t (:inherit (modus-themes-hl-line))))) - - (:bind "C-c C-p" #'circe-command-PART - "C-l" #'lui-track-jump-to-indicator) - - (:advise circe-command-PART :after - (defun circe-part@kill-buffer (&rest _) - (let ((circe-channel-killed-confirmation nil)) - (kill-buffer))) - - circe-command-QUIT :after - (defun circe-quit@kill-buffer (&rest _) - ;; `circe-server-killed-confirmation' set to nil, and manually - ;; deleting all chat buffers, pending Github issue #402 - ;; (https://github.com/emacs-circe/circe/issues/402) - (let ((circe-server-killed-confirmation nil)) - (with-circe-server-buffer - (dolist (buf (circe-server-chat-buffers)) - (let ((circe-channel-killed-confirmation nil)) - (kill-buffer buf))) - (kill-buffer)))) - - circe-command-GQUIT :after - (defun circe-gquit@kill-buffer (&rest _) - ;; `circe-server-killed-confirmation' set to nil, and manually - ;; deleting all chat buffers, pending Github issue #402 - ;; (https://github.com/emacs-circe/circe/issues/402) - (let ((circe-server-killed-confirmation nil)) - (dolist (buf (circe-server-buffers)) - (with-current-buffer buf - (dolist (buf (circe-server-chat-buffers)) - (let ((circe-channel-killed-confirmation nil)) - (kill-buffer buf))) - (message "%s: %s" buf circe-server-killed-confirmation) - (kill-buffer)))))) - - (defun circe-command-SHORTEN (url) - "Shorten URL using `0x0-shorten-uri'." - (interactive "sURL to shorten: ") - ;; TODO: enable /shorten URL comment syntax - (let ((short-url (0x0-shorten-uri (0x0--choose-server) url))) - (circe-command-SAY short-url))) - - (:with-mode circe-chat-mode - (:hook #'acdw/stop-paren-annoyances - #'enable-circe-color-nicks - #'enable-circe-display-images - #'enable-circe-new-day-notifier - (defun circe-chat@set-prompt () - (lui-set-prompt - (concat - (propertize - (acdw-irc/margin-format (buffer-name) "" ">") - 'face 'circe-prompt-face - 'read-only t - 'intangible t - 'cursor-intangible t) - " "))))) - - (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) - - (:local-set 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) - - (:hook #'enable-lui-track))) - (setup completion (:option completion-ignore-case t read-buffer-completion-ignore-case t @@ -336,104 +202,6 @@ AKA, DO NOT USE THIS FUNCTION!!!" (:global "M-/" #'hippie-expand)) -(setup (:straight (consult - :host github - :repo "minad/consult")) - - (:require acdw-consult) - (:autoload consult-register-preview) - - ;; 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)) - - (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))) - - (:option register-preview-delay 0 - register-preview-function #'consult-register-format - xref-show-xrefs-function #'consult-xref - xref-show-definitions-function #'consult-xref - consult-project-root-function #'vc-root-dir - completion-in-region-function #'acdw-consult/complete-in-region - completion-cycle-threshold 3 - consult-preview-key (kbd "M-.") - tab-always-indent 'complete) - - (:advise register-preview :override #'consult-register-window) - - ;; Completing-read-multple - (if (fboundp #'consult-completing-read-multiple) - (:advise completing-read-multple :override - #'consult-completing-read-multiple) - (:advise completing-read-multiple :filter-args - (defun crm-indicator (args) - (cons (concat "[CRM] " (car args)) (cdr args))))) - - (with-eval-after-load 'orderless - (:option consult--regexp-compiler - #'consult--orderless-regexp-compiler)) - - (with-eval-after-loads (vertico consult) - (:with-map consult-crm-map - (:bind "RET" (defun +vertico-crm-exit () - (interactive) - (run-at-time 0 nil #'vertico-exit) - (funcall #'vertico-exit)) - "TAB" #'vertico-exit)))) - -(setup (:straight crux) - (:global "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) - - (crux-reopen-as-root-mode +1)) - (setup cursor (:option cursor-type 'bar cursor-in-non-selected-windows 'hollow @@ -482,50 +250,6 @@ AKA, DO NOT USE THIS FUNCTION!!!" (setup debugger (:hook visual-line-mode)) -(setup (:straight-if (define-repeat-map - :host nil - :repo "https://tildegit.org/acdw/define-repeat-map.el") - (acdw/system :home)) - - (defun acdw/other-window-or-switch-buffer-backward () - (interactive) - (setq repeat-map 'other-window-repeat-map) - (acdw/other-window-or-switch-buffer -1)) - - (define-repeat-map other-window - ("o" acdw/other-window-or-switch-buffer - "O" acdw/other-window-or-switch-buffer-backward)) - - (define-repeat-map case - ("c" capitalize-word - "u" upcase-dwim - "l" downcase-dwim) - (:continue "f" forward-word - "b" backward-word) - (:enter capitalize-dwim - upcase-dwim - downcase-dwim)) - - (define-repeat-map page-navigation - ("]" forward-page - "[" backward-page)) - - (define-repeat-map windmove - (;; moving - "" windmove-left - "" windmove-right - "" windmove-up - "" windmove-down - ;; swapping - "" windmove-swap-states-left - "" windmove-swap-states-right - "" windmove-swap-states-up - "" windmove-swap-states-down)) - - (define-repeat-map winner-mode - ("/" winner-undo - "?" winner-redo))) - (setup dired (:also-load dired-x) (:straight dired-subtree @@ -617,70 +341,10 @@ AKA, DO NOT USE THIS FUNCTION!!!" ;; https://oremacs.com/2015/01/17/setting-up-ediff/ (add-hook 'ediff-after-quit-hook-internal #'winner-undo)) -(setup (:straight edit-indirect)) - -;; requires extension: -;; https://addons.mozilla.org/en-US/firefox/addon/edit-with-emacs1/ -(setup (:straight edit-server) - (:require edit-server) - (edit-server-start) - - (:option edit-server-default-major-mode 'text-mode - edit-server-url-major-mode-alist - (list (cons (rx (| "reddit.com" - "tildes.net")) - 'markdown-mode) - (cons (rx "github.com") - 'gfm-mode))) - - (: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 (:straight (electric-cursor - :host github - :repo "duckwork/electric-cursor")) - (electric-cursor-mode +1)) - -(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) - (:advise elfeed :after - (defun elfeed@protocol-update (&rest _) - (elfeed-search-fetch nil))) - - (:face message-header-subject - ((t (:height 1.5)))) - - (:with-mode elfeed-show-mode - (:hook #'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 (:with-mode emacs-lisp-mode ;; -_- (:option eval-expression-print-length nil @@ -714,35 +378,6 @@ AKA, DO NOT USE THIS FUNCTION!!!" "C-c C-k" #'acdw/eval-region-or-buffer "C-c C-z" #'ielm))) -(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 #'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 emacs ;; "Et cetera" settings ;; This should stay as /minimal/ as possible. Anything that can go somewhere @@ -807,29 +442,6 @@ AKA, DO NOT USE THIS FUNCTION!!!" (unless (bound-and-true-p edit-server-frame-p) (toggle-frame-maximized frame))))) -(setup (:straight embark) - (:global "C-." #'embark-act) - (:option prefix-help-command #'embark-prefix-help-command - (append display-buffer-alist) - `(,(rx (seq bos "*Embark Collect " - (group (| "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)) - embark-action-indicator - (lambda (map _target) - (which-key--show-keymap "Embark" map nil nil 'no-paging) - #'which-key--hide--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 @@ -854,61 +466,10 @@ AKA, DO NOT USE THIS FUNCTION!!!" (_ (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://azuracast.tilderadio.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 - lisp-interaction-mode)) - -(setup eshell - (:also-load acdw-eshell - em-smart - em-tramp) +(setup eshell + (:also-load acdw-eshell + em-smart + em-tramp) (:option eshell-aliases-file (acdw/dir "eshell/aliases" t) eshell-destroy-buffer-when-process-dies t @@ -951,19 +512,6 @@ AKA, DO NOT USE THIS FUNCTION!!!" (:hook #'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)) - -(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)) @@ -1018,32 +566,912 @@ specific to most general, they are these: - `flymake-inhibit': a file-local-variable -- `flymake-inhibit-buffer-name-regexps': a list of regexps to - match the buffer name against. If one of them matches, inhibit - `flymake-mode'. +- `flymake-inhibit-buffer-name-regexps': a list of regexps to + match the buffer name against. If one of them matches, inhibit + `flymake-mode'. + +- `flymake-inhibit-file-name-regexps': a list of regexps to match + the filename against. If one of them matches, inhibit + `flymake-mode'. + +- `flymake-inhibit-major-modes': a list of major-modes in which + to inhibit `flymake-mode'. Really only useful if you want to + generally add `flymake-mode' to `prog-mode-hook'." + (unless (or (bound-and-true-p flymake-inhibit) ; file-local variable + (list-string-match-p (buffer-name) + flymake-inhibit-buffer-name-regexps) + (list-string-match-p (buffer-file-name) + flymake-inhibit-file-name-regexps) + (apply #'derived-mode-p flymake-inhibit-major-modes)) + (flymake-mode-on))) + + (add-hook 'prog-mode-hook #'flymake-unless) + + (:bind "M-n" #'flymake-goto-next-error + "M-p" #'flymake-goto-prev-error)) + +(setup flyspell + (:hook-into text-mode)) + +(setup frames + (:option frame-title-format '("%b@" + (:eval + (or (file-remote-p default-directory 'host) + system-name)) + " %+%* GNU Emacs" + (:eval (when (frame-parameter nil 'client) + " Client"))) + window-resize-pixelwise t)) + +(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") + (mode . erc-mode) + (mode . circe-server-mode) + (mode . circe-channel-mode))) + ("shell" (or (mode . eshell-mode) + (mode . shell-mode) + (mode . vterm-mode))) + ("web" (or (mode . elpher-mode) + (mode . gemini-mode) + (mode . eww-mode)))))) + + (:global "C-x C-b" #'ibuffer) + + (:hook (defun ibuffer@filter-to-default () + (ibuffer-switch-to-saved-filter-groups "default")))) + +(setup ielm + (:hook #'turn-on-eldoc-mode)) + +(setup imenu + (:option imenu-auto-rescan t)) + +(setup isearch + (:option search-default-mode t)) + +(setup lines + (:option fill-column 79 + word-wrap t + truncate-lines nil) + + (global-display-fill-column-indicator-mode +1) + (global-so-long-mode +1) + + (add-hook 'visual-line-mode-hook + (defun acdw/disable-fill-column-indicator () + (display-fill-column-indicator-mode + (if visual-line-mode -1 +1)))) + + ;; `acdw/kill-line-and-join-advice' cribs from `crux-kill-and-join-forward'. + ;; I can't simply advise `kill-line' with an override from crux because crux + ;; itself calls `kill-line', leading to a infinite nesting situation. + (advice-add 'kill-line :around + (defun kill-line@join (fn &rest args) + (if (and (eolp) + (not (bolp))) + (delete-indentation 1) + (apply fn args))))) + +(setup minibuffer + (:option 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) + read-answer-short t + read-extended-command-predicate ; used on >28 + #'command-completion-default-include-p) + + (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode) + + (add-hook 'minibuffer-setup-hook #'acdw/gc-disable) + (add-hook 'minibuffer-exit-hook #'acdw/gc-enable) + + (minibuffer-depth-indicate-mode +1) + (file-name-shadow-mode +1) + (minibuffer-electric-default-mode +1) + + (if (version< emacs-version "28") + (fset 'yes-or-no-p #'y-or-n-p) + (setq use-short-answers t))) + +(setup mouse-avoidance + (mouse-avoidance-mode 'exile)) + +(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) + + (:hook show-paren-mode + electric-pair-local-mode + acdw/setup-fringes + + (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 repeat + ;; new for Emacs 28! + (:only-if (fboundp #'repeat-mode)) + + (:option repeat-exit-key "g" + repeat-exit-timeout 5) + + (repeat-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") + ) + + (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) + + (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 + tildify-mode + 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'... + (: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 view + (:option view-read-only t) + + (:hook (defun acdw/read-view-mode () + (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))) + 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 (:straight (0x0 + :host gitlab + :repo "willvaughn/emacs-0x0")) + (:option 0x0-default-server 'ttm)) + +(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 (: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 'message + 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" + "#emacs") + :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")) + ("Pissnet" :host "piss.hmm.st" :port 6697 :use-tls t + :channels ("#i-just-peed") + :sasl-username ,circe-default-nick + :sasl-password ,(acdw/make-password-fetcher + :host "piss.hmm.st")) + ;; TODO: irc.chat.twitch.tv + ) + circe-reduce-lurker-spam t + circe-server-auto-join-default-type :after-auth) + + ;; (:face circe-nick-highlight-face + ;; ((t (:inherit (modus-themes-hl-line))))) + + (:bind "C-c C-p" #'circe-command-PART + "C-l" #'lui-track-jump-to-indicator) + + (:advise circe-command-PART :after + (defun circe-part@kill-buffer (&rest _) + (let ((circe-channel-killed-confirmation nil)) + (kill-buffer))) + + circe-command-QUIT :after + (defun circe-quit@kill-buffer (&rest _) + ;; `circe-server-killed-confirmation' set to nil, and manually + ;; deleting all chat buffers, pending Github issue #402 + ;; (https://github.com/emacs-circe/circe/issues/402) + (let ((circe-server-killed-confirmation nil)) + (with-circe-server-buffer + (dolist (buf (circe-server-chat-buffers)) + (let ((circe-channel-killed-confirmation nil)) + (kill-buffer buf))) + (kill-buffer)))) + + circe-command-GQUIT :after + (defun circe-gquit@kill-buffer (&rest _) + ;; `circe-server-killed-confirmation' set to nil, and manually + ;; deleting all chat buffers, pending Github issue #402 + ;; (https://github.com/emacs-circe/circe/issues/402) + (let ((circe-server-killed-confirmation nil)) + (dolist (buf (circe-server-buffers)) + (with-current-buffer buf + (dolist (buf (circe-server-chat-buffers)) + (let ((circe-channel-killed-confirmation nil)) + (kill-buffer buf))) + (message "%s: %s" buf circe-server-killed-confirmation) + (kill-buffer)))))) + + (defun circe-command-SHORTEN (url) + "Shorten URL using `0x0-shorten-uri'." + (interactive "sURL to shorten: ") + ;; TODO: enable /shorten URL comment syntax + (let ((short-url (0x0-shorten-uri (0x0--choose-server) url))) + (circe-command-SAY short-url))) + + (:with-mode circe-chat-mode + (:hook #'acdw/stop-paren-annoyances + #'enable-circe-color-nicks + #'enable-circe-display-images + #'enable-circe-new-day-notifier + (defun circe-chat@set-prompt () + (lui-set-prompt + (concat + (propertize + (acdw-irc/margin-format (buffer-name) "" ">") + 'face 'circe-prompt-face + 'read-only t + 'intangible t + 'cursor-intangible t) + " "))))) + + (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) + + (:local-set 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) + + (:hook #'enable-lui-track))) + +(setup (:straight (consult + :host github + :repo "minad/consult")) + + (:require acdw-consult) + (:autoload consult-register-preview) + + ;; 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)) + + (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))) + + (:option register-preview-delay 0 + register-preview-function #'consult-register-format + xref-show-xrefs-function #'consult-xref + xref-show-definitions-function #'consult-xref + consult-project-root-function #'vc-root-dir + completion-in-region-function #'acdw-consult/complete-in-region + completion-cycle-threshold 3 + consult-preview-key (kbd "M-.") + tab-always-indent 'complete) + + (:advise register-preview :override #'consult-register-window) + + ;; Completing-read-multple + (if (fboundp #'consult-completing-read-multiple) + (:advise completing-read-multple :override + #'consult-completing-read-multiple) + (:advise completing-read-multiple :filter-args + (defun crm-indicator (args) + (cons (concat "[CRM] " (car args)) (cdr args))))) + + (with-eval-after-load 'orderless + (:option consult--regexp-compiler + #'consult--orderless-regexp-compiler)) + + (with-eval-after-loads (vertico consult) + (:with-map consult-crm-map + (:bind "RET" (defun +vertico-crm-exit () + (interactive) + (run-at-time 0 nil #'vertico-exit) + (funcall #'vertico-exit)) + "TAB" #'vertico-exit)))) + +(setup (:straight crux) + (:global "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) + + (crux-reopen-as-root-mode +1)) + +(setup (:straight-if (define-repeat-map + :host nil + :repo "https://tildegit.org/acdw/define-repeat-map.el") + (acdw/system :home)) + + (defun acdw/other-window-or-switch-buffer-backward () + (interactive) + (setq repeat-map 'other-window-repeat-map) + (acdw/other-window-or-switch-buffer -1)) + + (define-repeat-map other-window + ("o" acdw/other-window-or-switch-buffer + "O" acdw/other-window-or-switch-buffer-backward)) + + (define-repeat-map case + ("c" capitalize-word + "u" upcase-dwim + "l" downcase-dwim) + (:continue "f" forward-word + "b" backward-word) + (:enter capitalize-dwim + upcase-dwim + downcase-dwim)) + + (define-repeat-map page-navigation + ("]" forward-page + "[" backward-page)) + + (define-repeat-map windmove + (;; moving + "" windmove-left + "" windmove-right + "" windmove-up + "" windmove-down + ;; swapping + "" windmove-swap-states-left + "" windmove-swap-states-right + "" windmove-swap-states-up + "" windmove-swap-states-down)) + + (define-repeat-map winner-mode + ("/" winner-undo + "?" winner-redo))) + +(setup (:straight edit-indirect)) + +;; requires extension: +;; https://addons.mozilla.org/en-US/firefox/addon/edit-with-emacs1/ +(setup (:straight edit-server) + (:require edit-server) + (edit-server-start) + + (:option edit-server-default-major-mode 'text-mode + edit-server-url-major-mode-alist + (list (cons (rx (| "reddit.com" + "tildes.net")) + 'markdown-mode) + (cons (rx "github.com") + 'gfm-mode))) + + (:advise edit-server-make-frame :before + (defun edit-server@set-a-variable (&rest _) + (setq-local edit-server-frame-p t)))) + +(setup (:straight (electric-cursor + :host github + :repo "duckwork/electric-cursor")) + (electric-cursor-mode +1)) + +(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) + (:advise elfeed :after + (defun elfeed@protocol-update (&rest _) + (elfeed-search-fetch nil))) + + (:face message-header-subject + ((t (:height 1.5)))) + + (:with-mode elfeed-show-mode + (:hook #'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 (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 #'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) + `(,(rx (seq bos "*Embark Collect " + (group (| "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)) + embark-action-indicator + (lambda (map _target) + (which-key--show-keymap "Embark" map nil nil 'no-paging) + #'which-key--hide--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))) + +;; 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://azuracast.tilderadio.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 + )) -- `flymake-inhibit-file-name-regexps': a list of regexps to match - the filename against. If one of them matches, inhibit - `flymake-mode'. +(setup (:straight eros) + (:hook-into emacs-lisp-mode + lisp-interaction-mode)) -- `flymake-inhibit-major-modes': a list of major-modes in which - to inhibit `flymake-mode'. Really only useful if you want to - generally add `flymake-mode' to `prog-mode-hook'." - (unless (or (bound-and-true-p flymake-inhibit) ; file-local variable - (list-string-match-p (buffer-name) - flymake-inhibit-buffer-name-regexps) - (list-string-match-p (buffer-file-name) - flymake-inhibit-file-name-regexps) - (apply #'derived-mode-p flymake-inhibit-major-modes)) - (flymake-mode-on))) +(setup (:straight-if exec-path-from-shell + (acdw/system :home)) + (when (daemonp) + (exec-path-from-shell-initialize))) - (add-hook 'prog-mode-hook #'flymake-unless) - - (:bind "M-n" #'flymake-goto-next-error - "M-p" #'flymake-goto-prev-error)) +(setup (:straight expand-region) + (:global "C-=" #'er/expand-region)) -(setup flyspell - (:hook-into text-mode)) +(setup (:straight-if fennel-mode + (executable-find "fennel")) + (:autoload (fennel-repl :interactive t)) + (:file-match (rx ".fnl" eos))) (setup (:straight flyspell-correct) (:option flyspell-correct-interface #'flyspell-correct-completing-read @@ -1070,16 +1498,6 @@ specific to most general, they are these: '("tildegit.org" "tildegit.org/api/v1" "tildegit.org" forge-gitea-repository)))) -(setup frames - (:option frame-title-format '("%b@" - (:eval - (or (file-remote-p default-directory 'host) - system-name)) - " %+%* GNU Emacs" - (:eval (when (frame-parameter nil 'client) - " Client"))) - window-resize-pixelwise t)) - (setup (:straight gcmh) (:option gcmh-idle-delay 'auto) (gcmh-mode +1)) @@ -1120,23 +1538,12 @@ specific to most general, they are these: (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 (:straight gitattributes-mode)) (setup (:straight gitconfig-mode)) (setup (:straight gitignore-mode)) -(setup (:require goto-addr) - (if (fboundp #'global-goto-address-mode) - (global-goto-address-mode) - (add-hook 'after-change-major-mode-hook #'goto-address-mode))) - (setup (:straight helpful) (:require-after 3) @@ -1187,62 +1594,12 @@ specific to most general, they are these: (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") - (mode . erc-mode) - (mode . circe-server-mode) - (mode . circe-channel-mode))) - ("shell" (or (mode . eshell-mode) - (mode . shell-mode) - (mode . vterm-mode))) - ("web" (or (mode . elpher-mode) - (mode . gemini-mode) - (mode . eww-mode)))))) - - (:global "C-x C-b" #'ibuffer) - - (:hook (defun ibuffer@filter-to-default () - (ibuffer-switch-to-saved-filter-groups "default")))) - -(setup ielm - (:hook #'turn-on-eldoc-mode)) - -(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 (kaomoji-insert :host nil :repo "https://tildegit.org/acdw/kaomoji-insert")) @@ -1262,29 +1619,6 @@ specific to most general, they are these: (setup (:straight-if ledger-mode (executable-find "ledger"))) -(setup lines - (:option fill-column 79 - word-wrap t - truncate-lines nil) - - (global-display-fill-column-indicator-mode +1) - (global-so-long-mode +1) - - (add-hook 'visual-line-mode-hook - (defun acdw/disable-fill-column-indicator () - (display-fill-column-indicator-mode - (if visual-line-mode -1 +1)))) - - ;; `acdw/kill-line-and-join-advice' cribs from `crux-kill-and-join-forward'. - ;; I can't simply advise `kill-line' with an override from crux because crux - ;; itself calls `kill-line', leading to a infinite nesting situation. - (advice-add 'kill-line :around - (defun kill-line@join (fn &rest args) - (if (and (eolp) - (not (bolp))) - (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 @@ -1369,29 +1703,6 @@ browser defined in `browse-url-secondary-browser-function'." (:hook #'hl-line-mode #'reading-mode)) -(setup minibuffer - (:option 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) - read-answer-short t - read-extended-command-predicate ; used on >28 - #'command-completion-default-include-p) - - (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode) - - (add-hook 'minibuffer-setup-hook #'acdw/gc-disable) - (add-hook 'minibuffer-exit-hook #'acdw/gc-enable) - - (minibuffer-depth-indicate-mode +1) - (file-name-shadow-mode +1) - (minibuffer-electric-default-mode +1) - - (if (version< emacs-version "28") - (fset 'yes-or-no-p #'y-or-n-p) - (setq use-short-answers t))) - (setup (:straight (modus-themes :host gitlab :repo "protesilaos/modus-themes")) @@ -1406,9 +1717,6 @@ browser defined in `browse-url-secondary-browser-function'." (acdw/sunrise-sunset #'modus-themes-load-operandi #'modus-themes-load-vivendi)) -(setup mouse-avoidance - (mouse-avoidance-mode 'exile)) - (setup (:straight mwim) (:global "C-a" #'mwim-beginning "C-e" #'mwim-end)) @@ -1572,35 +1880,6 @@ browser defined in `browse-url-secondary-browser-function'." (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)) @@ -1638,63 +1917,25 @@ browser defined in `browse-url-secondary-browser-function'." (: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 (:straight prism) - (dolist (mode lispy-modes) - (add-hook (intern (format "%s-hook" mode)) #'prism-mode))) - -(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 prog-mode@auto-fill () - (setq-local comment-auto-fill-only-comments t) - (turn-on-auto-fill))) + (persistent-scratch-setup-default) - (add-hook 'after-save-hook - #'executable-make-buffer-file-executable-if-script-p)) + (mapc (lambda (buf) + (with-current-buffer buf + (when (funcall persistent-scratch-scratch-buffer-p-function) + (persistent-scratch-mode +1)))) -(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)) + (buffer-list))) - (:advise dired-rename-file :after #'rjs/recentf-rename-notify) - - (recentf-mode +1)) +(setup (:straight-if pkgbuild-mode + (executable-find "makepkg")) + (:file-match "PKGBUILD")) -(setup repeat - ;; new for Emacs 28! - (:only-if (fboundp #'repeat-mode)) +(setup (:straight powerthesaurus) + (:global "C-c l t" #'powerthesaurus-lookup-word-dwim)) - (:option repeat-exit-key "g" - repeat-exit-timeout 5) - - (repeat-mode +1)) +(setup (:straight prism) + (dolist (mode lispy-modes) + (add-hook (intern (format "%s-hook" mode)) #'prism-mode))) (setup (:straight restart-emacs) (defun emacs-upgrade (&optional update-packages) @@ -1706,93 +1947,6 @@ browser defined in `browse-url-secondary-browser-function'." (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") - ) - - (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) - - (delete-selection-mode +1)) - -(setup (:require server) - (unless (server-running-p) - (server-start))) - -(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 (:straight (shell-command+ :host nil :repo "https://git.sr.ht/~pkal/shell-command-plus")) @@ -1801,14 +1955,6 @@ browser defined in `browse-url-secondary-browser-function'." (:bind "M-!" shell-command+)) (:global "M-!" shell-command+)) -(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) (:also-load acdw-modeline) @@ -1897,11 +2043,6 @@ browser defined in `browse-url-secondary-browser-function'." (setup (:straight-if systemd (executable-find "systemd"))) -(setup text - (:hook turn-on-auto-fill - tildify-mode - acdw/setup-fringes)) - (setup (:straight (topsy :host github :repo "alphapapa/topsy.el")) @@ -1965,20 +2106,6 @@ If used with a numeric prefix argument N, N backticks will be inserted." (save-some-buffers t)) #'garbage-collect))) -(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" @@ -2016,12 +2143,6 @@ If used with a numeric prefix argument N, N backticks will be inserted." " ") cand)))) -(setup view - (:option view-read-only t) - - (:hook (defun acdw/read-view-mode () - (reading-mode (if view-mode +1 -1))))) - (setup (:straight visual-regexp) (:global "M-%" #'vr/query-replace)) @@ -2033,15 +2154,6 @@ If used with a numeric prefix argument N, N backticks will be inserted." (eshell-vterm-mode +1) (defalias 'eshell/v 'eshell-exec-visual)) -(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) @@ -2072,101 +2184,9 @@ If used with a numeric prefix argument N, N backticks will be inserted." (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))) - 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 (:straight winum) (:option winum-scope 'frame-local winum-auto-setup-mode-line nil diff --git a/lisp/acdw.el b/lisp/acdw.el index 0790f2e..472b4ab 100644 --- a/lisp/acdw.el +++ b/lisp/acdw.el @@ -265,10 +265,16 @@ With a prefix argument N, (un)comment that many sexps." ;; from https://github.com/alphapapa/unpackaged.el#sort-sexps ;; and https://github.com/alphapapa/unpackaged.el/issues/20 -(defun sort-sexps (beg end &optional key) +(defun sort-sexps (beg end &optional key-fn sort-fn) "Sort sexps between BEG and END. -Comments stay with the code below. KEY is a function to sort by, -e.g. (lambda (sexp) (symbol-name (car sexp)))" +Comments stay with the code below. + +Optional argument KEY-FN will determine where in each sexp to +start sorting. e.g. (lambda (sexp) (symbol-name (car sexp))) + +Optional argument SORT-FN will determine how to sort two sexps' +strings. It's passed to `sort'. By default, it sorts the sexps +with `string<' starting with the key determined by KEY-FN." (interactive "r") (cl-flet ((skip-whitespace () (while (looking-at (rx (1+ (or space "\n")))) (goto-char (match-end 0)))) @@ -298,8 +304,8 @@ e.g. (lambda (sexp) (symbol-name (car sexp)))" (save-excursion (goto-char (marker-position start)) (skip-both) - (if key - (funcall key sexp) + (if key-fn + (funcall key-fn sexp) (buffer-substring (point) (marker-position end))))) @@ -307,8 +313,9 @@ e.g. (lambda (sexp) (symbol-name (car sexp)))" collect (cons start end) into markers finally return (list sexps markers)) - (setq sexps (sort sexps (lambda (a b) - (string< (cdr a) (cdr b))))) + (setq sexps (sort sexps (if sort-fn sort-fn + (lambda (a b) + (string< (cdr a) (cdr b)))))) (cl-loop for (real . sort) in sexps for (start . end) in markers do (progn -- cgit 1.4.1-21-gabe81