summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--early-init.el7
-rw-r--r--init.el212
-rw-r--r--lisp/+apheleia.el51
-rw-r--r--lisp/+avy.el40
-rw-r--r--lisp/+circe.el52
-rw-r--r--lisp/+cus-edit.el2
-rw-r--r--lisp/+emacs.el17
-rw-r--r--lisp/+flyspell-correct.el3
-rw-r--r--lisp/+modeline.el22
-rw-r--r--lisp/+nyan-mode.el39
-rw-r--r--lisp/+org-wc.el2
-rw-r--r--lisp/+org.el53
-rw-r--r--lisp/+tab-bar.el314
-rw-r--r--lisp/+window.el130
-rw-r--r--lisp/private.el4
15 files changed, 634 insertions, 314 deletions
diff --git a/early-init.el b/early-init.el index 12e2b0d..5109795 100644 --- a/early-init.el +++ b/early-init.el
@@ -44,7 +44,12 @@ restore that."
44 (set-default variable value))) 44 (set-default variable value)))
45 45
46;; Garbage collection 46;; Garbage collection
47(+set-during-startup 'gc-cons-threshold most-positive-fixnum (* 128 1024 1024)) 47(+set-during-startup 'gc-cons-threshold most-positive-fixnum)
48
49(add-hook 'minibuffer-setup-hook (defun garbage-collect@minibuffer-enter ()
50 (setq gc-cons-threshold most-positive-fixnum)))
51(add-hook 'minibuffer-exit-hook (defun garbage-collect@minibuffer-exit ()
52 (setq gc-cons-threshold 800000)))
48 53
49;; Don't prematurely re-display 54;; Don't prematurely re-display
50(unless debug-on-error 55(unless debug-on-error
diff --git a/init.el b/init.el index 2932768..f7fbe96 100644 --- a/init.el +++ b/init.el
@@ -45,7 +45,6 @@
45 "C-x 4 n" #'clone-buffer 45 "C-x 4 n" #'clone-buffer
46 "C-c v" #'visible-mode 46 "C-c v" #'visible-mode
47 "C-M-;" #'+lisp-comment-or-uncomment-sexp 47 "C-M-;" #'+lisp-comment-or-uncomment-sexp
48 "M-j" nil
49 "C-x C-o" #'+switch-to-last-buffer 48 "C-x C-o" #'+switch-to-last-buffer
50 "C-x o" #'+switch-to-last-buffer 49 "C-x o" #'+switch-to-last-buffer
51 "C-x C-l" #'+open-paragraph ; original: downcase-region 50 "C-x C-l" #'+open-paragraph ; original: downcase-region
@@ -53,7 +52,13 @@
53 "C-x C-m" #'execute-extended-command ; original: coding systems 52 "C-x C-m" #'execute-extended-command ; original: coding systems
54 "C-<backspace>" #'+backward-kill-word 53 "C-<backspace>" #'+backward-kill-word
55 "C-x TAB" #'+indent-rigidly 54 "C-x TAB" #'+indent-rigidly
55 "<f7>" #'flyspell-mode
56 "C-x C-c" #'+save-buffers-quit) 56 "C-x C-c" #'+save-buffers-quit)
57 ;; Disable bindings
58 (:global "M-j" nil
59 "<Scroll_Lock>" nil)
60 (:+leader "C-t d" #'toggle-debug-on-error
61 "C-t q" #'toggle-debug-on-quit)
57 ;; C-h deletes backward - see https://idiomdrottning.org/bad-emacs-defaults 62 ;; C-h deletes backward - see https://idiomdrottning.org/bad-emacs-defaults
58 (global-set-key (kbd "C-h") 'delete-backward-char) 63 (global-set-key (kbd "C-h") 'delete-backward-char)
59 (keyboard-translate ?\C-h ?\C-?) 64 (keyboard-translate ?\C-h ?\C-?)
@@ -81,6 +86,8 @@
81 (+with-ensure-after-init 86 (+with-ensure-after-init
82 (:hook #'+init-add-setup-to-imenu))) 87 (:hook #'+init-add-setup-to-imenu)))
83 88
89(setup (:require +window))
90
84(setup (:require auth-source) 91(setup (:require auth-source)
85 (:option auth-sources (list 'default 92 (:option auth-sources (list 'default
86 "secrets:passwords" 93 "secrets:passwords"
@@ -106,6 +113,9 @@
106 (dolist (var '(safe-local-variable-values 113 (dolist (var '(safe-local-variable-values
107 warning-suppress-types)) 114 warning-suppress-types))
108 (add-to-list '+custom-variable-allowlist var)) 115 (add-to-list '+custom-variable-allowlist var))
116 ;; Load customizations now, and after init (to capture other possible
117 ;; variables I want to load) XXX: this is dumb
118 (+custom-load-ignoring-most-customizations)
109 (+with-ensure-after-init 119 (+with-ensure-after-init
110 (+custom-load-ignoring-most-customizations)) 120 (+custom-load-ignoring-most-customizations))
111 (advice-add #'custom-buffer-create-internal :after #'+cus-edit-expand-widgets) 121 (advice-add #'custom-buffer-create-internal :after #'+cus-edit-expand-widgets)
@@ -165,15 +175,19 @@
165 auto-revert-verbose nil) 175 auto-revert-verbose nil)
166 (global-auto-revert-mode +1)) 176 (global-auto-revert-mode +1))
167 177
178(setup awk-mode
179 (:apheleia gawk '("gawk" "-f-" "-o-")))
180
168(setup bookmark 181(setup bookmark
169 (:option bookmark-save-flag 1 182 (:option bookmark-save-flag 1
170 bookmark-watch-bookmark-file 'silent)) 183 bookmark-watch-bookmark-file 'silent
184 bookmark-set-fringe-mark nil))
171 185
172(setup browse-url 186(setup browse-url
173 (:require +browse-url) 187 (:require +browse-url)
174 (:option 188 (:option
175 browse-url-browser-function #'eww-browse-url 189 browse-url-browser-function 'browse-url-default-browser
176 +browse-url-browser-function browse-url-browser-function 190 +browse-url-browser-function #'eww-browse-url
177 browse-url-generic-program (seq-some #'executable-find 191 browse-url-generic-program (seq-some #'executable-find
178 '("firefox" 192 '("firefox"
179 "chromium" 193 "chromium"
@@ -214,6 +228,7 @@
214 ;; Set up URL handlers. 228 ;; Set up URL handlers.
215 (:option browse-url-handlers 229 (:option browse-url-handlers
216 (list 230 (list
231 (cons (rx bos (or "gemini:" "gopher:")) #'elpher-browse-url-elpher)
217 (cons (rx ; images 232 (cons (rx ; images
218 "." (or "jpeg" "jpg" "png" "bmp") eos) 233 "." (or "jpeg" "jpg" "png" "bmp") eos)
219 (lambda (&rest args) 234 (lambda (&rest args)
@@ -328,7 +343,8 @@
328(setup eshell 343(setup eshell
329 (:also-load em-smart 344 (:also-load em-smart
330 em-tramp) 345 em-tramp)
331 (:require +eshell) 346 (:require +eshell
347 esh-module)
332 (+define-dir eshell/ (locate-user-emacs-file "eshell") 348 (+define-dir eshell/ (locate-user-emacs-file "eshell")
333 "Where to place Eshell-specific files.") 349 "Where to place Eshell-specific files.")
334 (:option eshell-aliases-file (eshell/ "aliases") 350 (:option eshell-aliases-file (eshell/ "aliases")
@@ -353,9 +369,11 @@
353 (* " "))) 369 (* " ")))
354 (:+leader "s" #'+eshell-here 370 (:+leader "s" #'+eshell-here
355 "C-s" #'+eshell-here) 371 "C-s" #'+eshell-here)
372 (add-to-list 'eshell-modules-list 'eshell-tramp)
356 (with-eval-after-load 'mwim 373 (with-eval-after-load 'mwim
357 (setf (alist-get 'eshell-mode mwim-beginning-of-line-function) 374 (setf (alist-get 'eshell-mode mwim-beginning-of-line-function)
358 #'eshell-bol)) 375 #'eshell-bol))
376 (:hook #'eshell-smart-initialize)
359 (+eshell-eval-after-load 377 (+eshell-eval-after-load
360 ;; Local modes 378 ;; Local modes
361 (dolist (mode '((hungry-delete-mode . -1))) 379 (dolist (mode '((hungry-delete-mode . -1)))
@@ -381,7 +399,10 @@
381(setup eww 399(setup eww
382 (:also-load +eww) 400 (:also-load +eww)
383 (:option eww-search-prefix "https://duckduckgo.com/html?q=" 401 (:option eww-search-prefix "https://duckduckgo.com/html?q="
384 url-privacy-level '(email agent cookies lastloc)) 402 url-privacy-level '(email agent cookies lastloc)
403 eww-use-browse-url (rx bos (or "mailto:"
404 "gemini:"
405 "gopher:")))
385 (add-hook 'eww-after-render-hook #'reading-mode) 406 (add-hook 'eww-after-render-hook #'reading-mode)
386 (:hook #'+eww-bookmark-setup 407 (:hook #'+eww-bookmark-setup
387 #'+eww-track-readable-mode) 408 #'+eww-track-readable-mode)
@@ -390,9 +411,6 @@
390 "M-n" nil 411 "M-n" nil
391 "M-p" nil)) 412 "M-p" nil))
392 413
393(setup flyspell
394 (:hook-into org-mode))
395
396(setup hideshow 414(setup hideshow
397 (:also-load +hideshow) 415 (:also-load +hideshow)
398 (:with-mode hs-minor-mode 416 (:with-mode hs-minor-mode
@@ -422,9 +440,12 @@
422 ("help" (or (mode . help-mode) 440 ("help" (or (mode . help-mode)
423 (mode . Info-mode) 441 (mode . Info-mode)
424 (mode . helpful-mode))) 442 (mode . helpful-mode)))
425 ("irc" (or (mode . erc-mode) 443 ("chat" (or (mode . erc-mode)
426 (mode . circe-server-mode) 444 (mode . circe-server-mode)
427 (mode . circe-channel-mode))) 445 (mode . circe-channel-mode)
446 (mode . jabber-chat-mode)
447 (mode . jabber-browse-mode)
448 (mode . jabber-roster-mode)))
428 ("shell" (or (mode . eshell-mode) 449 ("shell" (or (mode . eshell-mode)
429 (mode . shell-mode) 450 (mode . shell-mode)
430 (mode . vterm-mode))) 451 (mode . vterm-mode)))
@@ -531,17 +552,25 @@
531 (add-hook 'message-send-hook #'+send-mail-dispatch) 552 (add-hook 'message-send-hook #'+send-mail-dispatch)
532 (advice-add 'notmuch-tag :filter-args #'+notmuch-correct-tags) 553 (advice-add 'notmuch-tag :filter-args #'+notmuch-correct-tags)
533 (:option notmuch-saved-searches (list 554 (:option notmuch-saved-searches (list
534 (list :name "inbox" 555 (list :name "inbox+unread"
535 :query (+notmuch-query-concat 556 :query (+notmuch-query-concat
536 "tag:inbox" 557 "tag:inbox"
537 "tag:unread" 558 "tag:unread"
538 "NOT tag:Spam") 559 "NOT tag:Spam")
539 :key "i") 560 :key "i")
540 (list :name "lists" 561 (list :name "inbox"
562 :query (+notmuch-query-concat
563 "tag:inbox"
564 "NOT tag:Spam")
565 :key "I")
566 (list :name "lists+unread"
541 :query (+notmuch-query-concat 567 :query (+notmuch-query-concat
542 "tag:/List/" 568 "tag:/List/"
543 "tag:unread") 569 "tag:unread")
544 :key "l") 570 :key "l")
571 (list :name "lists"
572 :query "tag:/List/"
573 :key "L")
545 (list :name "unread" 574 (list :name "unread"
546 :query (+notmuch-query-concat 575 :query (+notmuch-query-concat
547 "tag:unread" 576 "tag:unread"
@@ -630,7 +659,7 @@
630 org-src-window-setup 'current-window 659 org-src-window-setup 'current-window
631 org-startup-truncated nil 660 org-startup-truncated nil
632 org-startup-with-inline-images t 661 org-startup-with-inline-images t
633 org-tags-column (- (- fill-column (length org-ellipsis))) 662 org-tags-column -77 ;; (- (- fill-column 1 (length org-ellipsis)))
634 org-todo-keywords '((sequence "TODO(t)" "WAIT(w@/!)" "ONGOING(o@)" 663 org-todo-keywords '((sequence "TODO(t)" "WAIT(w@/!)" "ONGOING(o@)"
635 "|" "DONE(d!)") 664 "|" "DONE(d!)")
636 (sequence "|" "CANCELED(k@)") 665 (sequence "|" "CANCELED(k@)")
@@ -656,6 +685,7 @@
656 ;; )))) 685 ;; ))))
657 (:bind "RET" #'+org-return-dwim 686 (:bind "RET" #'+org-return-dwim
658 "<S-return>" #'+org-table-copy-down 687 "<S-return>" #'+org-table-copy-down
688 "M-RET" #'+org-meta-return
659 "C-c C-l" #'+org-insert-link-dwim 689 "C-c C-l" #'+org-insert-link-dwim
660 "C-c C-n" #'+org-next-heading-widen 690 "C-c C-n" #'+org-next-heading-widen
661 "C-c C-p" #'+org-previous-heading-widen 691 "C-c C-p" #'+org-previous-heading-widen
@@ -675,11 +705,11 @@
675 "C-c l" #'org-store-link) 705 "C-c l" #'org-store-link)
676 (+with-ensure-after-init 706 (+with-ensure-after-init
677 (:hook #'variable-pitch-mode 707 (:hook #'variable-pitch-mode
678 #'visual-fill-column-mode 708 #'visual-fill-column-mode
679 #'turn-off-auto-fill 709 #'turn-off-auto-fill
680 #'org-indent-mode 710 #'org-indent-mode ;; Needed for proper hanging indents in lists
681 #'prettify-symbols-mode 711 #'prettify-symbols-mode
682 #'+org-wrap-on-hyphens)) 712 #'+org-wrap-on-hyphens))
683 (:local-set prettify-symbols-alist '(("DEADLINE:" . ?→) 713 (:local-set prettify-symbols-alist '(("DEADLINE:" . ?→)
684 ("SCHEDULED:" . ?↷) 714 ("SCHEDULED:" . ?↷)
685 ("CLOSED:" . ?✓)) 715 ("CLOSED:" . ?✓))
@@ -716,11 +746,13 @@
716 ;; complains about "Invalid face reference: t" in org-mode buffers, because 746 ;; complains about "Invalid face reference: t" in org-mode buffers, because
717 ;; `compose-region' returns t. 747 ;; `compose-region' returns t.
718 ("^[ \t]*\\([-]\\) " 748 ("^[ \t]*\\([-]\\) "
719 (0 ;; (progn (compose-region (match-beginning 1) (match-end 1) "–") 'fixed-pitch) 749 (0 (progn (compose-region (match-beginning 1) (match-end 1) "–") 'fixed-pitch)
720 'fixed-pitch t)) 750 ;; 'fixed-pitch t
751 ))
721 ("^[ \t]*\\([+]\\) " 752 ("^[ \t]*\\([+]\\) "
722 (0 ;; (progn (compose-region (match-beginning 1) (match-end 1) "¬") 'fixed-pitch) 753 (0 (progn (compose-region (match-beginning 1) (match-end 1) "•") 'fixed-pitch)
723 'fixed-pitch t)) 754 ;; 'fixed-pitch t
755 ))
724 ("^[ \t]+\\([*]\\) " 756 ("^[ \t]+\\([*]\\) "
725 (0 ;; (progn (compose-region (match-beginning 1) (match-end 1) "→") 'fixed-pitch) 757 (0 ;; (progn (compose-region (match-beginning 1) (match-end 1) "→") 'fixed-pitch)
726 'fixed-pitch t)) 758 'fixed-pitch t))
@@ -841,10 +873,7 @@
841 org-export-with-sub-superscripts t 873 org-export-with-sub-superscripts t
842 org-export-with-toc nil) 874 org-export-with-toc nil)
843 (with-eval-after-load 'ox 875 (with-eval-after-load 'ox
844 (+org-export-pre-hooks-insinuate)) 876 (+org-export-pre-hooks-insinuate)))
845 (add-hook '+org-export-pre-hook #'+flyspell-correct-buffer)
846 (with-eval-after-load 'user-save
847 (add-hook '+org-export-pre-hook #'user-save-run-hooks)))
848 877
849(setup password-cache 878(setup password-cache
850 (:option password-cache t 879 (:option password-cache t
@@ -869,6 +898,9 @@
869 (+scratch-text-scratch)) 898 (+scratch-text-scratch))
870 (add-hook 'kill-buffer-query-functions #'+scratch-immortal)) 899 (add-hook 'kill-buffer-query-functions #'+scratch-immortal))
871 900
901(setup sh
902 (:apheleia shfmt '("shfmt")))
903
872(setup shell 904(setup shell
873 (:option shell-command-prompt-show-cwd t) 905 (:option shell-command-prompt-show-cwd t)
874 (:local-set +modeline-position-function 906 (:local-set +modeline-position-function
@@ -920,6 +952,9 @@
920 (tab-bar-mode +1) 952 (tab-bar-mode +1)
921 (display-time-mode +1)) 953 (display-time-mode +1))
922 954
955(setup text-mode
956 (:bind "C-M-k" #'kill-paragraph))
957
923(setup timer-list 958(setup timer-list
924 (:bind "d" #'timer-list-cancel) 959 (:bind "d" #'timer-list-cancel)
925 (:hook #'hl-line-mode 960 (:hook #'hl-line-mode
@@ -995,6 +1030,10 @@
995 [remap isearch-query-replace] #'anzu-isearch-query-replace 1030 [remap isearch-query-replace] #'anzu-isearch-query-replace
996 [remap isearch-query-replace-regexp] #'anzu-isearch-query-replace-regexp)) 1031 [remap isearch-query-replace-regexp] #'anzu-isearch-query-replace-regexp))
997 1032
1033(setup (:straight apheleia)
1034 (:require apheleia +apheleia)
1035 (apheleia-global-mode +1))
1036
998(setup (:straight avy) 1037(setup (:straight avy)
999 (:require avy +avy) 1038 (:require avy +avy)
1000 (:option avy-background t 1039 (:option avy-background t
@@ -1208,7 +1247,7 @@
1208 1247
1209 (:with-mode circe-chat-mode 1248 (:with-mode circe-chat-mode
1210 (:local-set lui-input-function #'+lui-filter 1249 (:local-set lui-input-function #'+lui-filter
1211 +modeline-position-function 'empty) 1250 +modeline-position-function #'ignore)
1212 (:hook #'enable-circe-color-nicks 1251 (:hook #'enable-circe-color-nicks
1213 #'enable-circe-new-day-notifier 1252 #'enable-circe-new-day-notifier
1214 #'+circe-chat@set-prompt 1253 #'+circe-chat@set-prompt
@@ -1223,6 +1262,7 @@
1223 (:with-mode lui-mode 1262 (:with-mode lui-mode
1224 (:option lui-fill-column (+ fill-column +circe-left-margin) 1263 (:option lui-fill-column (+ fill-column +circe-left-margin)
1225 lui-fill-type nil 1264 lui-fill-type nil
1265 lui-max-buffer-size (+bytes 10 :kb)
1226 lui-time-stamp-position 'right-margin 1266 lui-time-stamp-position 'right-margin
1227 lui-time-stamp-format "| %H:%M" 1267 lui-time-stamp-format "| %H:%M"
1228 lui-track-behavior 'before-switch-to-buffer 1268 lui-track-behavior 'before-switch-to-buffer
@@ -1251,6 +1291,7 @@
1251 #'enable-lui-track 1291 #'enable-lui-track
1252 #'visual-fill-column-mode 1292 #'visual-fill-column-mode
1253 #'enable-lui-autopaste 1293 #'enable-lui-autopaste
1294 (defun turn-off-+nyan-mode () (+nyan-local-mode -1))
1254 (defun turn-off-electric-pair-mode () (electric-pair-mode -1))) 1295 (defun turn-off-electric-pair-mode () (electric-pair-mode -1)))
1255 (:local-set fringes-outside-margins t 1296 (:local-set fringes-outside-margins t
1256 right-margin-width (length lui-time-stamp-format) 1297 right-margin-width (length lui-time-stamp-format)
@@ -1303,8 +1344,10 @@
1303 xref-show-xrefs-function #'consult-xref 1344 xref-show-xrefs-function #'consult-xref
1304 xref-show-definitions-function #'consult-xref 1345 xref-show-definitions-function #'consult-xref
1305 tab-always-indent 'complete 1346 tab-always-indent 'complete
1306 ;; completion-in-region-function #'consult-completion-in-region 1347 completion-in-region-function #'consult-completion-in-region
1307 ) 1348 )
1349 (:with-mode minibuffer-mode
1350 (:local-set completion-in-region-function #'consult-completion-in-region))
1308 (advice-add #'register-preview :override #'consult-register-window) 1351 (advice-add #'register-preview :override #'consult-register-window)
1309 (dolist (binding '(;; C-c bindings (mode-specific-map) 1352 (dolist (binding '(;; C-c bindings (mode-specific-map)
1310 ("C-c h" . consult-history) 1353 ("C-c h" . consult-history)
@@ -1382,19 +1425,6 @@
1382 (with-eval-after-load 'orderless 1425 (with-eval-after-load 'orderless
1383 (:option consult--regexp-compiler #'consult--orderless-regexp-compiler)))) 1426 (:option consult--regexp-compiler #'consult--orderless-regexp-compiler))))
1384 1427
1385(setup (:straight corfu)
1386 (global-corfu-mode +1))
1387
1388(setup (:straight crossword)
1389 ;; This isn't the perfect Emacs crossword puzzle, but it's the only one I
1390 ;; know.
1391 (:hook #'turn-off-+key-mode)
1392 (:option crossword-save-path (sync/ "emacs/crosswords/" t)
1393 crossword-empty-position-char "=")
1394 (:face 'crossword-grid-face '((t :inherit 'font-lock-string-face))
1395 'crossword-current-face '((t :inherit 'highlight))
1396 'crossword-other-dir-face '((t :inherit 'font-lock-keyword-face))))
1397
1398(setup (:straight crux) 1428(setup (:straight crux)
1399 ;; yes it's silly I have an addon to this addon. 1429 ;; yes it's silly I have an addon to this addon.
1400 (:require crux +crux) 1430 (:require crux +crux)
@@ -1472,6 +1502,11 @@
1472 (+with-ensure-after-init 1502 (+with-ensure-after-init
1473 (edit-server-start))) 1503 (edit-server-start)))
1474 1504
1505(setup (:straight editorconfig)
1506 (:with-mode conf-mode
1507 (:file-match (rx ".editorconfig" eos)))
1508 (editorconfig-mode +1))
1509
1475(setup (:straight electric-cursor) 1510(setup (:straight electric-cursor)
1476 (:option electric-cursor-alist '((overwrite-mode . hbar) 1511 (:option electric-cursor-alist '((overwrite-mode . hbar)
1477 (god-local-mode . box) 1512 (god-local-mode . box)
@@ -1489,7 +1524,7 @@
1489 "~/Downloads/") 1524 "~/Downloads/")
1490 if (file-exists-p dir) 1525 if (file-exists-p dir)
1491 return dir) 1526 return dir)
1492 elfeed-search-filter "@1-month-ago +unread" 1527 elfeed-search-filter "@10-days-ago +unread"
1493 elfeed-search-trailing-width 24 1528 elfeed-search-trailing-width 24
1494 elfeed-search-title-min-width 24 1529 elfeed-search-title-min-width 24
1495 elfeed-search-title-max-width 78 1530 elfeed-search-title-max-width 78
@@ -1685,10 +1720,6 @@
1685 (:option frowny-eyes (rx (any ":=") (opt "'") (? "-"))) 1720 (:option frowny-eyes (rx (any ":=") (opt "'") (? "-")))
1686 (global-frowny-mode +1)) 1721 (global-frowny-mode +1))
1687 1722
1688(setup (:straight gcmh)
1689 (:option gcmh-idle-delay 'auto)
1690 (gcmh-mode +1))
1691
1692(setup (:straight (geiser 1723(setup (:straight (geiser
1693 :type git 1724 :type git
1694 :flavor melpa 1725 :flavor melpa
@@ -1701,8 +1732,8 @@
1701 scheme-complete)) 1732 scheme-complete))
1702 (straight-use-package pkg)) 1733 (straight-use-package pkg))
1703 (:require +chicken) 1734 (:require +chicken)
1704 (setf (alist-get "\\.scm\\'" auto-mode-alist nil nil #'string=) 1735 (:with-mode scheme-mode
1705 'scheme-mode) 1736 (:file-match (rx ".scm" eos)))
1706 (setf (alist-get "\\.scm\\'" auto-insert-alist nil nil #'equal) 1737 (setf (alist-get "\\.scm\\'" auto-insert-alist nil nil #'equal)
1707 '(insert "#!/bin/sh\n#| -*- scheme -*-\nexec csi -s $0 \"$@\"\n|#\n"))) 1738 '(insert "#!/bin/sh\n#| -*- scheme -*-\nexec csi -s $0 \"$@\"\n|#\n")))
1708 1739
@@ -1855,7 +1886,8 @@
1855 ((string-match-p "hmm@" (buffer-name)) 1886 ((string-match-p "hmm@" (buffer-name))
1856 "🤔 "))) 1887 "🤔 ")))
1857 file-percentage-mode nil 1888 file-percentage-mode nil
1858 wrap-prefix (make-string +jabber-ws-prefix ?\ ))) 1889 wrap-prefix (make-string +jabber-ws-prefix ?\ )
1890 comment-start nil))
1859 (:+leader "C-j" jabber-global-keymap) 1891 (:+leader "C-j" jabber-global-keymap)
1860 (advice-add 'jabber-activity-add :after #'+jabber-tracking-add) 1892 (advice-add 'jabber-activity-add :after #'+jabber-tracking-add)
1861 (advice-add 'jabber-activity-add-muc :after #'+jabber-tracking-add-muc) 1893 (advice-add 'jabber-activity-add-muc :after #'+jabber-tracking-add-muc)
@@ -1921,7 +1953,7 @@
1921(setup (:straight (magit :host github :repo "magit/magit" 1953(setup (:straight (magit :host github :repo "magit/magit"
1922 :build (:not compile)) 1954 :build (:not compile))
1923 (:straight (transient :host github :repo "magit/transient" 1955 (:straight (transient :host github :repo "magit/transient"
1924 :build (:not compile)))) 1956 :build (:not compile))))
1925 (autoload 'transient--with-suspended-override "transient")) 1957 (autoload 'transient--with-suspended-override "transient"))
1926 1958
1927(setup (:straight marginalia) 1959(setup (:straight marginalia)
@@ -1929,9 +1961,7 @@
1929 1961
1930(setup (:straight markdown-mode) 1962(setup (:straight markdown-mode)
1931 (:option markdown-hide-markup nil) 1963 (:option markdown-hide-markup nil)
1932 (add-to-list 'auto-mode-alist (cons (rx (or ".md" ".markdown" ".mdown") 1964 (:file-match (rx (or ".md" ".markdown" ".mdown") eos))
1933 eos)
1934 'markdown-mode))
1935 (with-eval-after-load 'visual-fill-column 1965 (with-eval-after-load 'visual-fill-column
1936 (:hook #'visual-fill-column-mode)) 1966 (:hook #'visual-fill-column-mode))
1937 (with-eval-after-load 'apheleia 1967 (with-eval-after-load 'apheleia
@@ -1940,7 +1970,8 @@
1940 (setf (alist-get 'markdown-mode apheleia-mode-alist) 'markdownfmt) 1970 (setf (alist-get 'markdown-mode apheleia-mode-alist) 'markdownfmt)
1941 (setf (alist-get 'gfm-mode apheleia-mode-alist) 'markdownfmt)))) 1971 (setf (alist-get 'gfm-mode apheleia-mode-alist) 'markdownfmt))))
1942 1972
1943(setup (:straight mastodon) 1973(setup (:straight (mastodon
1974 :fork (:host nil :repo "https://codeberg.org/acdw/mastodon.el")))
1944 (:option mastodon-instance-url "https://tiny.tilde.website" 1975 (:option mastodon-instance-url "https://tiny.tilde.website"
1945 mastodon-active-user "acdw" 1976 mastodon-active-user "acdw"
1946 mastodon-client--token-file (.etc "mastodon.plstore") 1977 mastodon-client--token-file (.etc "mastodon.plstore")
@@ -1957,15 +1988,6 @@
1957 #'hl-line-mode 1988 #'hl-line-mode
1958 #'lin-mode)) 1989 #'lin-mode))
1959 1990
1960(setup (:straight md4rd
1961 :quit)
1962 ;; `md4rd' is ... a bit janky, tbh. But I'm including this here so I have it.
1963 ;; TODO: enable opening Reddit links in md4rd
1964 (:also-load _md4rd)
1965 (defalias 'reddit 'md4rd "Browse Reddit.")
1966 (with-eval-after-load 'md4rd
1967 (run-with-timer 0 (* 60 59) 'md4rd-refresh-login)))
1968
1969(setup (:straight minions) 1991(setup (:straight minions)
1970 (minions-mode +1)) 1992 (minions-mode +1))
1971 1993
@@ -2096,12 +2118,17 @@
2096 (:hook #'visual-fill-column-mode) 2118 (:hook #'visual-fill-column-mode)
2097 (:file-match (rx ".epub" eos))) 2119 (:file-match (rx ".epub" eos)))
2098 2120
2099(setup (:straight nyan-mode) 2121(setup (:straight (nyan-mode
2100 (:require) 2122 :fork (:repo "duckwork/nyan-mode")))
2101 ;; For some reason, in some modes the mode-line isn't updated after these 2123 (:require nyan-mode +nyan-mode)
2102 ;; commands. I think it might have to do with `+modeline-position-function'. 2124 (with-eval-after-load 'modus-themes
2103 (advice-add 'end-of-buffer :after #'force-mode-line-update) 2125 (add-hook 'modus-themes-after-load-theme-hook
2104 (advice-add 'beginning-of-buffer :after #'force-mode-line-update)) 2126 (defun +nyan-modus-update-colors ()
2127 (modus-themes-with-colors
2128 (set-face-attribute '+nyan-mode-line nil
2129 :background bg-special-warm))))
2130 (+nyan-modus-update-colors))
2131 (+nyan-mode +1))
2105 2132
2106(setup (:straight ol-notmuch)) 2133(setup (:straight ol-notmuch))
2107 2134
@@ -2149,19 +2176,6 @@
2149 (defun org-mime-setup@org-mode () 2176 (defun org-mime-setup@org-mode ()
2150 (local-set-key (kbd "C-c M-o") 'org-mime-org-buffer-htmlize)))) 2177 (local-set-key (kbd "C-c M-o") 'org-mime-org-buffer-htmlize))))
2151 2178
2152(setup (:straight org-modern)
2153 (:quit "I think I can do most of this myself.")
2154 (:option org-modern-hide-stars nil
2155 org-modern-star nil
2156 org-modern-list nil
2157 org-modern-progress ["..." "o.." "oo." "Oo." "Ooo" "OOo" "OOO"])
2158 (:face 'org-modern-label '((t ( :height 1.0
2159 :weight regular
2160 :underline nil
2161 :inherit fixed-pitch))))
2162 (advice-add 'org-modern--update-label-face :override #'ignore)
2163 (:hook-into org-mode))
2164
2165(setup (:straight (org-taskwise 2179(setup (:straight (org-taskwise
2166 :host github 2180 :host github
2167 :repo "duckwork/org-taskwise.el")) 2181 :repo "duckwork/org-taskwise.el"))
@@ -2235,9 +2249,8 @@
2235 (executable-find "g++"))) 2249 (executable-find "g++")))
2236 (:also-load +pdf-tools) 2250 (:also-load +pdf-tools)
2237 (:with-mode pdf-view-mode 2251 (:with-mode pdf-view-mode
2238 (:local-set +modeline-position-function #'+pdf-view-position)) 2252 (:local-set +modeline-position-function #'+pdf-view-position)
2239 (setf (alist-get "\\.pdf\\'" auto-mode-alist nil nil #'equal) 2253 (:file-match (rx ".pdf" eos)))
2240 #'pdf-view-mode)
2241 (pdf-tools-install :no-query)) 2254 (pdf-tools-install :no-query))
2242 2255
2243(setup (:straight persistent-scratch) 2256(setup (:straight persistent-scratch)
@@ -2304,8 +2317,8 @@
2304 +modeline-buffer-name 2317 +modeline-buffer-name
2305 +modeline-major-mode 2318 +modeline-major-mode
2306 (lambda () (+modeline-vc " : ")) 2319 (lambda () (+modeline-vc " : "))
2307 +modeline-anzu
2308 +modeline-nyan-on-focused 2320 +modeline-nyan-on-focused
2321 +modeline-anzu
2309 ) 2322 )
2310 ( ; right 2323 ( ; right
2311 simple-modeline-segment-process 2324 simple-modeline-segment-process
@@ -2369,7 +2382,9 @@
2369 #'describe-gnu-project 2382 #'describe-gnu-project
2370 #'suspend-frame) 2383 #'suspend-frame)
2371 (sophomore-disable-with 'confirm 2384 (sophomore-disable-with 'confirm
2372 #'save-buffers-kill-terminal) 2385 #'save-buffers-kill-terminal)
2386 (sophomore-disable-with 'confirm-y
2387 #'+save-buffers-quit)
2373 (sophomore-mode +1)) 2388 (sophomore-mode +1))
2374 2389
2375(setup (:straight (spongebob-case 2390(setup (:straight (spongebob-case
@@ -2445,9 +2460,10 @@
2445 2460
2446(setup (:straight (twtxt 2461(setup (:straight (twtxt
2447 :fork (:repo "duckwork/twtxt-el"))) 2462 :fork (:repo "duckwork/twtxt-el")))
2448 (:option twtxt-file "/sshx:hetzner:/var/www/acdw.casa/tw.txt" 2463 (:require)
2449 twtxt-following '(("acdw" "https://acdw.casa/tw.txt"))) 2464 (:also-load _twtxt)
2450 (+with-ensure-after-init (:require))) 2465 (:option twtxt-file _twtxt-file
2466 twtxt-following _twtxt-following))
2451 2467
2452(setup (:straight undo-fu) 2468(setup (:straight undo-fu)
2453 (:option undo-fu-allow-undo-in-region t) 2469 (:option undo-fu-allow-undo-in-region t)
@@ -2473,8 +2489,6 @@
2473 'undo-hl-insert '((t :underline t))) 2489 'undo-hl-insert '((t :underline t)))
2474 (:hook-into text-mode prog-mode)) 2490 (:hook-into text-mode prog-mode))
2475 2491
2476(setup (:straight unfill))
2477
2478(setup (:straight valign 2492(setup (:straight valign
2479 :quit "Doesn't work with narrowed tables.") 2493 :quit "Doesn't work with narrowed tables.")
2480 (:option valign-fancy-bar t) 2494 (:option valign-fancy-bar t)
@@ -2535,12 +2549,10 @@
2535 :repo "casouri/vundo"))) 2549 :repo "casouri/vundo")))
2536 2550
2537(setup (:straight web-mode) 2551(setup (:straight web-mode)
2538 (setf (alist-get (rx "." (or "htm" "html" "phtml" "tpl.php" 2552 (:file-match (rx "." (or "htm" "html" "phtml" "tpl.php"
2539 "asp" "gsp" "jsp" "ascx" "aspx" 2553 "asp" "gsp" "jsp" "ascx" "aspx"
2540 "erb" "mustache" "djhtml") 2554 "erb" "mustache" "djhtml")
2541 eos) 2555 eos))
2542 auto-mode-alist)
2543 'web-mode)
2544 (with-eval-after-load 'apheleia 2556 (with-eval-after-load 'apheleia
2545 (setf (alist-get 'web-mode apheleia-mode-alist) 2557 (setf (alist-get 'web-mode apheleia-mode-alist)
2546 'prettier))) 2558 'prettier)))
diff --git a/lisp/+apheleia.el b/lisp/+apheleia.el index 469232a..df651b8 100644 --- a/lisp/+apheleia.el +++ b/lisp/+apheleia.el
@@ -2,14 +2,61 @@
2 2
3;;; Code: 3;;; Code:
4 4
5(require 'apheleia)
6(require 'cl-lib)
7
5;; https://github.com/raxod502/apheleia/pull/63#issue-1077529623 8;; https://github.com/raxod502/apheleia/pull/63#issue-1077529623
6(defun +apheleia-indent-region (orig scratch callback _error) 9(cl-defun +apheleia-indent-region (&key buffer scratch formatter callback &allow-other-keys)
7 (with-current-buffer scratch 10 (with-current-buffer scratch
8 (setq-local indent-line-function 11 (setq-local indent-line-function
9 (buffer-local-value 'indent-line-function orig)) 12 (buffer-local-value 'indent-line-function buffer))
10 (indent-region (point-min) 13 (indent-region (point-min)
11 (point-max)) 14 (point-max))
12 (funcall callback))) 15 (funcall callback)))
13 16
17
18;;; `setup' integration
19
20(require 'setup)
21
22(setup-define :apheleia
23 (lambda (name formatter &optional mode -pend)
24 (let* ((mode (or mode (setup-get 'mode)))
25 (current-formatters (and -pend
26 (alist-get mode apheleia-formatters))))
27 `(progn
28 (setf (alist-get ',name apheleia-formatters)
29 ,formatter)
30 (setf (alist-get ',mode apheleia-mode-alist)
31 ',(pcase -pend
32 (:append (append (ensure-list current-formatters)
33 (list name)))
34 (:prepend (cons name (ensure-list current-formatters)))
35 ('nil name)
36 (_ (error "Improper `:apheleia' -PEND argument")))))))
37 :documentation
38 "Register a formatter to `apheleia''s lists.
39NAME is the name given to the formatter in `apheleia-formatters'
40and `apheleia-mode-alist'. FORMATTER is the command paired with
41NAME in `apheleia-formatters'. MODE is the mode or modes to add
42NAME to in `apheleia-mode-alist'. If MODE is not given or nil,
43use the setup form's MODE. Optional argument -PEND can be one of
44`:append' or `:prepend', and if given will append or prepend the
45given NAME to the current formatters for the MODE in
46`apheleia-mode-alist', rather than replace them (the default).
47
48Example:
49(setup
50 (:apheleia isort (\"isort\" \"--stdout\" \"-\")
51 python-mode))
52; =>
53(progn
54 (setf (alist-get 'isort apheleia-formatters)
55 '(\"isort\" \"--stdout\" \"-\"))
56 (setf (alist-get 'python-mode apheleia-mode-alist)
57 'isort))
58
59This form cannot be repeated, and it cannot be used as HEAD.")
60
14(provide '+apheleia) 61(provide '+apheleia)
15;;; +apheleia.el ends here 62;;; +apheleia.el ends here
diff --git a/lisp/+avy.el b/lisp/+avy.el index 8056f00..b0837a3 100644 --- a/lisp/+avy.el +++ b/lisp/+avy.el
@@ -50,17 +50,35 @@
50(defvar-local +avy-buffer-face-mode-face nil 50(defvar-local +avy-buffer-face-mode-face nil
51 "The state of `buffer-face-mode' before calling `avy-with'.") 51 "The state of `buffer-face-mode' before calling `avy-with'.")
52 52
53(defun +avy@un-buffer-face (&rest _) 53;;; XXX: Doesn't switch back if avy errors out or quits
54(defun +avy@un-buffer-face (win)
54 "BEFORE advice on `avy-with' to disable `buffer-face-mode'." 55 "BEFORE advice on `avy-with' to disable `buffer-face-mode'."
55 (when buffer-face-mode 56 (with-current-buffer (window-buffer win)
56 (setq +avy-buffer-face-mode-face buffer-face-mode-face) 57 (when buffer-face-mode
57 (buffer-face-mode -1))) 58 (setq +avy-buffer-face-mode-face buffer-face-mode-face)
59 (buffer-face-mode -1))))
58 60
59(defun +avy@re-buffer-face (&rest _) 61(defun +avy@re-buffer-face (win)
60 "AFTER advice on `avy-with' to re-enable `buffer-face-mode'." 62 "AFTER advice on `avy-with' to re-enable `buffer-face-mode'."
61 (when +avy-buffer-face-mode-face 63 (with-current-buffer (window-buffer win)
62 (setq buffer-face-mode-face +avy-buffer-face-mode-face) 64 (when +avy-buffer-face-mode-face
63 (buffer-face-mode +1))) 65 (setq buffer-face-mode-face +avy-buffer-face-mode-face)
66 (buffer-face-mode +1)))
67 (let ((bounds (bounds-of-thing-at-point 'symbol)))
68 (when (and (car bounds)
69 (cdr bounds))
70 (pulse-momentary-highlight-region (car bounds) (cdr bounds)))))
71
72(defun +avy@buffer-face (fn &rest r)
73 "AROUND advice for avy to dis/enable `buffer-face-mode'."
74 (if avy-all-windows
75 (walk-windows #'+avy@un-buffer-face nil (eq avy-all-windows 'all-frames)))
76 (condition-case e
77 (apply fn r)
78 ((quit error) (message "Avy: %S" e) nil)
79 (:sucess e))
80 (if avy-all-windows
81 (walk-windows #'+avy@re-buffer-face nil (eq avy-all-windows 'all-frames))))
64 82
65(define-minor-mode +avy-buffer-face-mode 83(define-minor-mode +avy-buffer-face-mode
66 "Turn off `buffer-face-mode' before doing Avy selections. 84 "Turn off `buffer-face-mode' before doing Avy selections.
@@ -71,11 +89,9 @@ Restore the mode after the selection."
71 (cond 89 (cond
72 (+avy-buffer-face-mode 90 (+avy-buffer-face-mode
73 (dolist (fn +avy-buffer-face-functions) 91 (dolist (fn +avy-buffer-face-functions)
74 (advice-add fn :before #'+avy@un-buffer-face)) 92 (advice-add fn :around #'+avy@buffer-face)))
75 (advice-add 'avy--done :after #'+avy@re-buffer-face))
76 (t (dolist (fn +avy-buffer-face-functions) 93 (t (dolist (fn +avy-buffer-face-functions)
77 (advice-remove fn #'+avy@un-buffer-face)) 94 (advice-remove fn #'+avy@buffer-face)))))
78 (advice-remove 'avy--done #'+avy@re-buffer-face))))
79 95
80(provide '+avy) 96(provide '+avy)
81;;; avy.el ends here 97;;; avy.el ends here
diff --git a/lisp/+circe.el b/lisp/+circe.el index e8c5079..382f0ab 100644 --- a/lisp/+circe.el +++ b/lisp/+circe.el
@@ -45,21 +45,27 @@
45 45
46;;; Channel information 46;;; Channel information
47 47
48(defvar-local +circe-current-topic ""
49 "Cached topic of the buffer's channel.")
50
48(defun +circe-current-topic (&optional message) 51(defun +circe-current-topic (&optional message)
49 "Return the topic of the current channel. 52 "Return the topic of the current channel.
50When called with optional MESSAGE non-nil, or interactively, also 53When called with optional MESSAGE non-nil, or interactively, also
51message the current topic." 54message the current topic."
52 (interactive "p") 55 (interactive "p")
53 (let ((topic 56 (let ((topic
54 (save-excursion 57 (or (save-excursion
55 (goto-char (point-max)) 58 (goto-char (point-max))
56 (or (re-search-backward 59 (and (re-search-backward
57 (rx (group "*** " 60 (rx (group "*** "
58 (or "Topic" "topic" "TOPIC") 61 (or "Topic" "topic" "TOPIC")
59 (* (not ":")) ": ") 62 (* (not ":")) ": ")
60 (group (+ nonl))))) 63 (group (+ nonl)))
61 (buffer-substring-no-properties 64 nil t)
62 (match-beginning 2) (match-end 2))))) 65 (buffer-substring-no-properties
66 (match-beginning 2) (match-end 2))))
67 +circe-current-topic)))
68 (setq +circe-current-topic topic)
63 (when message 69 (when message
64 (message "%s" topic)) 70 (message "%s" topic))
65 topic)) 71 topic))
@@ -86,8 +92,8 @@ replace {nick} in the string with {NO-NICK}."
86 "Make a formatting regex for CHAR delimiters. 92 "Make a formatting regex for CHAR delimiters.
87For entry into `lui-formatting-list'." 93For entry into `lui-formatting-list'."
88 `(rx (or bol whitespace) 94 `(rx (or bol whitespace)
89 (group ,char (+? (not (any whitespace ,char))) ,char) 95 (group ,char (+? (not (any whitespace ,char))) ,char)
90 (or eol whitespace))) 96 (or eol whitespace)))
91 97
92;;; Hooks & Advice 98;;; Hooks & Advice
93 99
@@ -139,7 +145,7 @@ For entry into `lui-formatting-list'."
139 "What to do with `circe-server' buffers when created.") 145 "What to do with `circe-server' buffers when created.")
140 146
141(el-patch-defun circe (network-or-server &rest server-options) 147(el-patch-defun circe (network-or-server &rest server-options)
142 "Connect to IRC. 148 "Connect to IRC.
143 149
144Connect to the given network specified by NETWORK-OR-SERVER. 150Connect to the given network specified by NETWORK-OR-SERVER.
145 151
@@ -157,16 +163,16 @@ All SERVER-OPTIONS are treated as variables by getting the string
157locally in the server buffer. 163locally in the server buffer.
158 164
159See `circe-network-options' for a list of common options." 165See `circe-network-options' for a list of common options."
160 (interactive (circe--read-network-and-options)) 166 (interactive (circe--read-network-and-options))
161 (let* ((options (circe--server-get-network-options network-or-server 167 (let* ((options (circe--server-get-network-options network-or-server
162 server-options)) 168 server-options))
163 (buffer (circe--server-generate-buffer options))) 169 (buffer (circe--server-generate-buffer options)))
164 (with-current-buffer buffer 170 (with-current-buffer buffer
165 (circe-server-mode) 171 (circe-server-mode)
166 (circe--server-set-variables options) 172 (circe--server-set-variables options)
167 (circe-reconnect)) 173 (circe-reconnect))
168 (el-patch-swap (pop-to-buffer-same-window buffer) 174 (el-patch-swap (pop-to-buffer-same-window buffer)
169 (funcall +circe-server-buffer-action buffer)))) 175 (funcall +circe-server-buffer-action buffer))))
170 176
171;;; Chat commands 177;;; Chat commands
172 178
@@ -177,7 +183,7 @@ See `circe-network-options' for a list of common options."
177 nil t nil))) 183 nil t nil)))
178 (circe-command-ME (format "slaps %s about a bit with a large trout" nick))) 184 (circe-command-ME (format "slaps %s about a bit with a large trout" nick)))
179 185
180;;; Filtering functions 186;;; Filtering functions --- XXX: These don't work right.
181;; Set `lui-input-function' to `+lui-filter', then add the filters you want to 187;; Set `lui-input-function' to `+lui-filter', then add the filters you want to
182;; `circe-channel-mode-hook'. 188;; `circe-channel-mode-hook'.
183 189
diff --git a/lisp/+cus-edit.el b/lisp/+cus-edit.el index 7fa46d4..4631811 100644 --- a/lisp/+cus-edit.el +++ b/lisp/+cus-edit.el
@@ -50,7 +50,7 @@ pass t to it."
50 (cl-letf (((symbol-function 'custom-set-faces) 'ignore) 50 (cl-letf (((symbol-function 'custom-set-faces) 'ignore)
51 ((symbol-function 'custom-set-variables) 51 ((symbol-function 'custom-set-variables)
52 (lambda (&rest args) 52 (lambda (&rest args)
53 (apply 'custom-theme-set-variables 'user 53 (apply #'custom-theme-set-variables 'user
54 (seq-filter (lambda (el) 54 (seq-filter (lambda (el)
55 (memq (car el) 55 (memq (car el)
56 +custom-variable-allowlist)) 56 +custom-variable-allowlist))
diff --git a/lisp/+emacs.el b/lisp/+emacs.el index 7c8a1a6..533d438 100644 --- a/lisp/+emacs.el +++ b/lisp/+emacs.el
@@ -326,13 +326,24 @@ ARG is passed to `backward-kill-word'."
326 (setq-default history-length t 326 (setq-default history-length t
327 history-delete-duplicates t 327 history-delete-duplicates t
328 history-autosave-interval 60 328 history-autosave-interval 60
329 savehist-file (.etc "savehist.el")) 329 savehist-file (.etc "savehist.el")
330 ;; Other variables --- don't truncate any of these.
331 ;; `add-to-history' uses the values of these variables unless
332 ;; they're nil, in which case it falls back to `history-length'.
333 kill-ring-max 100
334 mark-ring-max 100
335 global-mark-ring-max 100
336 regexp-search-ring-max 100
337 search-ring-max 100
338 kmacro-ring-max 100
339 eww-history-limit 100)
330 (dolist (var '(extended-command-history 340 (dolist (var '(extended-command-history
331 global-mark-ring 341 global-mark-ring
342 mark-ring
332 kill-ring 343 kill-ring
344 kmacro-ring
333 regexp-search-ring 345 regexp-search-ring
334 search-ring 346 search-ring))
335 mark-ring))
336 (add-to-list 'savehist-additional-variables var)) 347 (add-to-list 'savehist-additional-variables var))
337 (savehist-mode +1)) 348 (savehist-mode +1))
338 349
diff --git a/lisp/+flyspell-correct.el b/lisp/+flyspell-correct.el index b995b7e..22f8c82 100644 --- a/lisp/+flyspell-correct.el +++ b/lisp/+flyspell-correct.el
@@ -2,10 +2,13 @@
2 2
3;;; Code: 3;;; Code:
4 4
5(require 'flyspell-correct)
6
5(defun +flyspell-correct-buffer (&optional prefix) 7(defun +flyspell-correct-buffer (&optional prefix)
6 "Run `flyspell-correct-wrapper' on all misspelled words in the buffer. 8 "Run `flyspell-correct-wrapper' on all misspelled words in the buffer.
7With PREFIX, prompt to change the current dictionary." 9With PREFIX, prompt to change the current dictionary."
8 (interactive "P") 10 (interactive "P")
11 (flyspell-buffer)
9 (when prefix 12 (when prefix
10 (let ((current-prefix-arg nil)) 13 (let ((current-prefix-arg nil))
11 (call-interactively #'ispell-change-dictionary))) 14 (call-interactively #'ispell-change-dictionary)))
diff --git a/lisp/+modeline.el b/lisp/+modeline.el index 026302b..11d6a4c 100644 --- a/lisp/+modeline.el +++ b/lisp/+modeline.el
@@ -347,7 +347,7 @@ The order of elements matters: whichever one matches first is applied."
347(defun +modeline-line (&optional spacer) 347(defun +modeline-line (&optional spacer)
348 (when line-number-mode 348 (when line-number-mode
349 (+modeline-spacer nil spacer 349 (+modeline-spacer nil spacer
350 "%l"))) 350 "%3l")))
351 351
352(defun +modeline-column (&optional spacer) 352(defun +modeline-column (&optional spacer)
353 (when column-number-mode 353 (when column-number-mode
@@ -367,8 +367,8 @@ See `line-number-mode', `column-number-mode', and
367`file-percentage-mode'. If `+modeline-position-function' is set 367`file-percentage-mode'. If `+modeline-position-function' is set
368to a function in the current buffer, call that function instead." 368to a function in the current buffer, call that function instead."
369 (cond ((functionp +modeline-position-function) 369 (cond ((functionp +modeline-position-function)
370 (+modeline-spacer nil spacer 370 (when-let* ((str (funcall +modeline-position-function)))
371 (funcall +modeline-position-function))) 371 (+modeline-spacer nil spacer str)))
372 (t (funcall (+modeline-concat '(+modeline-region 372 (t (funcall (+modeline-concat '(+modeline-region
373 +modeline-line 373 +modeline-line
374 +modeline-column 374 +modeline-column
@@ -378,10 +378,9 @@ to a function in the current buffer, call that function instead."
378(defun +modeline-vc (&optional spacer) 378(defun +modeline-vc (&optional spacer)
379 "Display the version control branch of the current buffer in the modeline." 379 "Display the version control branch of the current buffer in the modeline."
380 ;; from https://www.gonsie.com/blorg/modeline.html, from Doom 380 ;; from https://www.gonsie.com/blorg/modeline.html, from Doom
381 (if-let ((backend (vc-backend buffer-file-name))) 381 (when-let ((backend (vc-backend buffer-file-name)))
382 (+modeline-spacer nil spacer 382 (+modeline-spacer nil spacer
383 (substring vc-mode (+ (if (eq backend 'Hg) 2 3) 2))) 383 (substring vc-mode (+ (if (eq backend 'Hg) 2 3) 2)))))
384 ""))
385 384
386(defun +modeline-track (&optional spacer) 385(defun +modeline-track (&optional spacer)
387 "Display `tracking-mode' information." 386 "Display `tracking-mode' information."
@@ -473,13 +472,16 @@ to a function in the current buffer, call that function instead."
473 (kmacro-end-macro nil))))) 472 (kmacro-end-macro nil)))))
474 'mouse-face 'mode-line-highlight)))) 473 'mouse-face 'mode-line-highlight))))
475 474
475(defface +nyan-mode-line nil
476 "Face for nyan-cat in mode line.")
477
476(defun +modeline-nyan-on-focused (&optional spacer) 478(defun +modeline-nyan-on-focused (&optional spacer)
477 "Display the cat from `nyan-mode', but only on the focused window." 479 "Display the cat from `nyan-mode', but only on the focused window."
478 (require 'nyan-mode) 480 (require 'nyan-mode)
479 (when (actually-selected-window-p) 481 (when (and (or nyan-mode (bound-and-true-p +nyan-local-mode))
480 (concat (or spacer "") (nyan-create) 482 (actually-selected-window-p))
481 (propertize "." 483 (+modeline-spacer nil spacer
482 'face 'font-lock-comment-face)))) 484 (propertize (nyan-create) 'face '+nyan-mode-line))))
483 485
484(provide '+modeline) 486(provide '+modeline)
485;;; +modeline.el ends here 487;;; +modeline.el ends here
diff --git a/lisp/+nyan-mode.el b/lisp/+nyan-mode.el new file mode 100644 index 0000000..fc6775b --- /dev/null +++ b/lisp/+nyan-mode.el
@@ -0,0 +1,39 @@
1;;; +nyan-mode.el --- Extras for nyan-mode -*- lexical-binding: t; -*-
2
3;;; Commentary:
4
5;;; Code:
6
7;;; Update even without line number in the mode line.
8
9(defcustom +nyan-mode-update-functions
10 '( end-of-buffer beginning-of-buffer
11 next-line previous-line
12 org-next-visible-heading org-previous-visible-heading)
13 "Functions after which to force a mode-line update."
14 :type '(repeat function))
15
16(defun +nyan-mode--fmlu (&rest _)
17 "Update the mode-line, advice-style."
18 (force-mode-line-update))
19
20(defun +nyan-mode-advice (&rest _)
21 "Advise line-moving functions when in `nyan-mode'."
22 (dolist (fn +nyan-mode-update-functions)
23 (if nyan-mode
24 (advice-add fn :after #'+nyan-mode--fmlu)
25 (advice-remove fn #'+nyan-mode--fmlu))))
26
27(define-minor-mode +nyan-local-mode
28 "My very own `nyan-mode' that isn't global and doesn't update the mode-line."
29 :global nil
30 :group 'nyan
31 (dolist (fn +nyan-mode-update-functions)
32 (if +nyan-local-mode
33 (advice-add fn :after #'+nyan-mode--fmlu)
34 (advice-remove fn #'+nyan-mode--fmlu))))
35
36(define-globalized-minor-mode +nyan-mode +nyan-local-mode +nyan-local-mode)
37
38(provide '+nyan-mode)
39;;; +nyan-mode.el ends here
diff --git a/lisp/+org-wc.el b/lisp/+org-wc.el index edd88f0..89b2708 100644 --- a/lisp/+org-wc.el +++ b/lisp/+org-wc.el
@@ -87,7 +87,7 @@ code... probably).")
87(defun +org-wc-modeline () 87(defun +org-wc-modeline ()
88 (cond 88 (cond
89 ((eq +org-wc-word-count 'huge) "huge") 89 ((eq +org-wc-word-count 'huge) "huge")
90 (+org-wc-word-count (format " %sw" (max 0 (+ +org-wc-word-count +org-wc-correction)))))) 90 (+org-wc-word-count (format "%sw" (max 0 (+ +org-wc-word-count +org-wc-correction))))))
91 91
92(define-minor-mode +org-wc-mode 92(define-minor-mode +org-wc-mode
93 "Count words in `org-mode' buffers in the mode-line." 93 "Count words in `org-mode' buffers in the mode-line."
diff --git a/lisp/+org.el b/lisp/+org.el index 6b93a7a..0d6e300 100644 --- a/lisp/+org.el +++ b/lisp/+org.el
@@ -2,6 +2,7 @@
2 2
3;;; Code: 3;;; Code:
4 4
5(require 'el-patch)
5(require 'org) 6(require 'org)
6(require 'org-element) 7(require 'org-element)
7(require 'ox) 8(require 'ox)
@@ -96,7 +97,7 @@ appropriate. In tables, insert a new row or end the table."
96 ;; for now, it works well enough. 97 ;; for now, it works well enough.
97 (cond ((and itemp emptyp) 98 (cond ((and itemp emptyp)
98 (delete-region (line-beginning-position) (line-end-position)) 99 (delete-region (line-beginning-position) (line-end-position))
99 (insert "\n\n")) 100 (insert "\n"))
100 ((or first-item-p 101 ((or first-item-p
101 (and itemp (not emptyp)) 102 (and itemp (not emptyp))
102 item-child-p) 103 item-child-p)
@@ -252,11 +253,11 @@ instead of the true count."
252 ((use-region-p) 253 ((use-region-p)
253 (message "%d words in region" 254 (message "%d words in region"
254 (+org-count-words-stupidly (region-beginning) 255 (+org-count-words-stupidly (region-beginning)
255 (region-end)))) 256 (region-end))))
256 (t 257 (t
257 (message "%d words in buffer" 258 (message "%d words in buffer"
258 (+org-count-words-stupidly (point-min) 259 (+org-count-words-stupidly (point-min)
259 (point-max)))))) 260 (point-max))))))
260 261
261;;; org-insert-link-dwim - https://xenodium.com/emacs-dwim-do-what-i-mean/ 262;;; org-insert-link-dwim - https://xenodium.com/emacs-dwim-do-what-i-mean/
262 263
@@ -561,7 +562,7 @@ and POST-PROCESS are passed to `org-export-to-file'."
561 (let ((org-tmp-file "/tmp/org.html")) 562 (let ((org-tmp-file "/tmp/org.html"))
562 (org-export-to-file 'html org-tmp-file 563 (org-export-to-file 'html org-tmp-file
563 async subtreep visible-only body-only ext-plist post-process) 564 async subtreep visible-only body-only ext-plist post-process)
564 (start-process "xclicp" "*xclip*" 565 (start-process "xclip" "*xclip*"
565 "xclip" "-verbose" 566 "xclip" "-verbose"
566 "-i" org-tmp-file 567 "-i" org-tmp-file
567 "-t" "text/html" 568 "-t" "text/html"
@@ -684,5 +685,49 @@ This should only fire when switching to a buffer from `org-agenda'."
684 (advice-remove 'org-agenda #'+org-agenda-inhibit-hooks) 685 (advice-remove 'org-agenda #'+org-agenda-inhibit-hooks)
685 (advice-remove 'org-agenda-switch-to #'+org-agenda-switch-run-hooks)))) 686 (advice-remove 'org-agenda-switch-to #'+org-agenda-switch-run-hooks))))
686 687
688
689;;; "Fix" `org-align-tags'
690
691(el-patch-defun org-align-tags (&optional all)
692 "Align tags in current entry.
693When optional argument ALL is non-nil, align all tags in the
694visible part of the buffer."
695 (let ((get-indent-column
696 (lambda ()
697 (let ((offset (el-patch-swap
698 (if (bound-and-true-p org-indent-mode)
699 (* (1- org-indent-indentation-per-level)
700 (1- (org-current-level)))
701 0)
702 0)))
703 (+ org-tags-column
704 (if (> org-tags-column 0) (- offset) offset))))))
705 (if (and (not all) (org-at-heading-p))
706 (org--align-tags-here (funcall get-indent-column))
707 (save-excursion
708 (if all
709 (progn
710 (goto-char (point-min))
711 (while (re-search-forward org-tag-line-re nil t)
712 (org--align-tags-here (funcall get-indent-column))))
713 (org-back-to-heading t)
714 (org--align-tags-here (funcall get-indent-column)))))))
715
716;;; Meta-return
717
718(defun +org-meta-return (&optional arg)
719 "Insert a new line, or wrap a region in a table.
720See `org-meta-return', but `+org-return-dwim' does most of the
721stuff I would want out of that function already.
722
723When called with a prefix ARG, will still unconditionally call
724`org-insert-heading'."
725 (interactive "P")
726 (org-fold-check-before-invisible-edit 'insert)
727 (or (run-hook-with-args-until-success 'org-metareturn-hook) ; Allow customizations
728 (call-interactively (cond (arg #'org-insert-heading)
729 ((org-at-table-p) #'org-table-wrap-region)
730 (t #'org-return)))))
731
687(provide '+org) 732(provide '+org)
688;;; +org.el ends here 733;;; +org.el ends here
diff --git a/lisp/+tab-bar.el b/lisp/+tab-bar.el index 3e6968e..7ff991c 100644 --- a/lisp/+tab-bar.el +++ b/lisp/+tab-bar.el
@@ -12,8 +12,8 @@
12 12
13(defface +tab-bar-extra 13(defface +tab-bar-extra
14 '((t :inherit (tab-bar font-lock-comment-face))) 14 '((t :inherit (tab-bar font-lock-comment-face)))
15 "Tab bar face for extra information, like the menu-bar and time." 15 "Tab bar face for extra information, like the menu-bar and time."
16 :group 'basic-faces) 16 :group 'basic-faces)
17 17
18 18
19;; Common 19;; Common
@@ -35,97 +35,97 @@
35(defun +tab-bar-tracking-mode () 35(defun +tab-bar-tracking-mode ()
36 "Display `tracking-mode-line-buffers' in the tab-bar." 36 "Display `tracking-mode-line-buffers' in the tab-bar."
37 ;; TODO: write something to convert a mode-line construct to a tab-bar 37 ;; TODO: write something to convert a mode-line construct to a tab-bar
38 ;; construct. 38 ;; construct.
39 (when (and (bound-and-true-p tracking-mode) 39 (when (and (bound-and-true-p tracking-mode)
40 (not (and +tracking-hide-when-org-clocking 40 (not (and +tracking-hide-when-org-clocking
41 (bound-and-true-p org-clock-current-task)))) 41 (bound-and-true-p org-clock-current-task))))
42 (cons (when (> (length tracking-mode-line-buffers) 0) 42 (cons (when (> (length tracking-mode-line-buffers) 0)
43 '(track-mode-line-separator menu-item " " ignore)) 43 '(track-mode-line-separator menu-item " " ignore))
44 (cl-loop for i from 0 below (length tracking-mode-line-buffers) 44 (cl-loop for i from 0 below (length tracking-mode-line-buffers)
45 as item = (nth i tracking-mode-line-buffers) 45 as item = (nth i tracking-mode-line-buffers)
46 collect (append (list (intern (format "tracking-mode-line-%s" i)) 46 collect (append (list (intern (format "tracking-mode-line-%s" i))
47 'menu-item 47 'menu-item
48 (string-trim (format-mode-line item))) 48 (string-trim (format-mode-line item)))
49 (if-let ((keymap (plist-get item 'keymap))) 49 (if-let ((keymap (plist-get item 'keymap)))
50 (list (alist-get 'down-mouse-1 (cdadr keymap))) 50 (list (alist-get 'down-mouse-1 (cdadr keymap)))
51 (list #'ignore)) 51 (list #'ignore))
52 (when-let ((help (plist-get item 'help-echo))) 52 (when-let ((help (plist-get item 'help-echo)))
53 (list :help help))))))) 53 (list :help help)))))))
54 54
55(defun +tab-bar-timer () 55(defun +tab-bar-timer ()
56 "Display `+timer-string' in the tab-bar." 56 "Display `+timer-string' in the tab-bar."
57 (when +timer-string 57 (when (> (length (bound-and-true-p +timer-string)) 0)
58 `((timer-string menu-item 58 `((timer-string menu-item
59 ,(concat " " +timer-string) 59 ,(concat " " +timer-string)
60 (lambda (ev) 60 (lambda (ev)
61 (interactive "e") 61 (interactive "e")
62 (cond ((not +timer-timer) nil) 62 (cond ((not +timer-timer) nil)
63 ((equal +timer-string +timer-running-string) 63 ((equal +timer-string +timer-running-string)
64 (popup-menu 64 (popup-menu
65 '("Running timer" 65 '("Running timer"
66 ["Cancel timer" +timer-cancel t]) 66 ["Cancel timer" +timer-cancel t])
67 ev)) 67 ev))
68 (t (setq +timer-string "")))))))) 68 (t (setq +timer-string ""))))))))
69 69
70(defun +tab-bar-date () 70(defun +tab-bar-date ()
71 "Display `display-time-string' in the tab-bar." 71 "Display `display-time-string' in the tab-bar."
72 (when display-time-mode 72 (when display-time-mode
73 `((date-time-string menu-item 73 `((date-time-string menu-item
74 ,(substring-no-properties (concat " " (string-trim display-time-string))) 74 ,(substring-no-properties (concat " " (string-trim display-time-string)))
75 (lambda (ev) 75 (lambda (ev)
76 (interactive "e") 76 (interactive "e")
77 (popup-menu 77 (popup-menu
78 (append '("Timer") 78 (append '("Timer")
79 (let (r) 79 (let (r)
80 (dolist (time '(3 5 10)) 80 (dolist (time '(3 5 10))
81 (push (vector (format "Timer for %d minutes" time) 81 (push (vector (format "Timer for %d minutes" time)
82 `(lambda () (interactive) 82 `(lambda () (interactive)
83 (+timer ,time)) 83 (+timer ,time))
84 :active t) 84 :active t)
85 r)) 85 r))
86 (nreverse r)) 86 (nreverse r))
87 '(["Timer for ..." +timer t])) 87 '(["Timer for ..." +timer t]))
88 ev)) 88 ev))
89 :help (discord-date-string))))) 89 :help (discord-date-string)))))
90 90
91(defun +tab-bar-notmuch-count () 91(defun +tab-bar-notmuch-count ()
92 "Display a notmuch count in the tab-bar." 92 "Display a notmuch count in the tab-bar."
93 (when (and (executable-find "notmuch") 93 (when (and (executable-find "notmuch")
94 (featurep 'notmuch)) 94 (featurep 'notmuch))
95 (let* ((counts (ignore-errors (notmuch-hello-query-counts notmuch-saved-searches))) 95 (let* ((counts (ignore-errors (notmuch-hello-query-counts notmuch-saved-searches)))
96 (next (cl-find "inbox" counts :key (lambda (l) (plist-get l :name)) :test 'equal)) 96 (next (cl-find "inbox+unread" counts :key (lambda (l) (plist-get l :name)) :test 'equal))
97 (next-count (plist-get next :count))) 97 (next-count (plist-get next :count)))
98 (when (and next-count (> next-count 0)) 98 (when (and next-count (> next-count 0))
99 `((notmuch-count menu-item 99 `((notmuch-count menu-item
100 ,(format " |%s|" next-count) 100 ,(format " |%s|" next-count)
101 ignore 101 ignore
102 :help ,(format "%s mails requiring attention." next-count))))))) 102 :help ,(format "%s mails requiring attention." next-count)))))))
103 103
104(defun +tab-bar-org-clock () 104(defun +tab-bar-org-clock ()
105 "Display `org-mode-line-string' in the tab-bar." 105 "Display `org-mode-line-string' in the tab-bar."
106 (when (and (fboundp 'org-clocking-p) 106 (when (and (fboundp 'org-clocking-p)
107 (org-clocking-p)) 107 (org-clocking-p))
108 ;; org-mode-line-string 108 ;; org-mode-line-string
109 `((org-clocking menu-item 109 `((org-clocking menu-item
110 ,org-mode-line-string 110 ,org-mode-line-string
111 (lambda (ev) 111 (lambda (ev)
112 (interactive "e") 112 (interactive "e")
113 (let ((menu (make-sparse-keymap 113 (let ((menu (make-sparse-keymap
114 (or org-clock-current-task "Org-Clock")))) 114 (or org-clock-current-task "Org-Clock"))))
115 (map-keymap (lambda (key binding) 115 (map-keymap (lambda (key binding)
116 (when (consp binding) 116 (when (consp binding)
117 (define-key-after menu (vector key) 117 (define-key-after menu (vector key)
118 (copy-sequence binding)))) 118 (copy-sequence binding))))
119 (org-clock-menu)) 119 (org-clock-menu))
120 (message "%S" ev) 120 (message "%S" ev)
121 (popup-menu menu ev))) 121 (popup-menu menu ev)))
122 :help ,(or (replace-regexp-in-string 122 :help ,(or (replace-regexp-in-string
123 (rx "[[" (group (* (not "]"))) 123 (rx "[[" (group (* (not "]")))
124 "][" (group (* (not "]"))) 124 "][" (group (* (not "]")))
125 "]]") 125 "]]")
126 "\\2" 126 "\\2"
127 org-clock-current-task) 127 org-clock-current-task)
128 "Org-Clock"))))) 128 "Org-Clock")))))
129 129
130(defcustom +tab-bar-emms-max-length 24 130(defcustom +tab-bar-emms-max-length 24
131 "Maximum length of `+tab-bar-emms'." 131 "Maximum length of `+tab-bar-emms'."
@@ -139,8 +139,8 @@
139 (- +tab-bar-emms-max-length 2)))) 139 (- +tab-bar-emms-max-length 2))))
140 `(emms-now-playing menu-item 140 `(emms-now-playing menu-item
141 ,(concat "{" now-playing "}" " ") 141 ,(concat "{" now-playing "}" " ")
142 emms-pause 142 emms-pause
143 ( :help ,(emms-mode-line-playlist-current)))))) 143 ( :help ,(emms-mode-line-playlist-current))))))
144 144
145(defun +tab-bar-bongo () 145(defun +tab-bar-bongo ()
146 "Display Bongo now playing information." 146 "Display Bongo now playing information."
@@ -160,22 +160,22 @@
160 "\\1: \\3" 160 "\\1: \\3"
161 (bongo-formatted-infoset)) 161 (bongo-formatted-infoset))
162 ;; This isn't right 162 ;; This isn't right
163 (- (min 50 (/ (frame-width) 3 )) 2))) 163 (- (min 50 (/ (frame-width) 3 )) 2)))
164 "}") 164 "}")
165 (lambda () (interactive) 165 (lambda () (interactive)
166 (let ((bongo-playlist-buffer 166 (let ((bongo-playlist-buffer
167 ;; XXX: I'm sure this is terribly inefficient 167 ;; XXX: I'm sure this is terribly inefficient
168 (cl-some (lambda (b) 168 (cl-some (lambda (b)
169 (with-current-buffer b 169 (with-current-buffer b
170 (when-let* ((modep (derived-mode-p 170 (when-let* ((modep (derived-mode-p
171 'bongo-playlist-mode)) 171 'bongo-playlist-mode))
172 (bongo-playlist-buffer b) 172 (bongo-playlist-buffer b)
173 (playingp (bongo-playing-p))) 173 (playingp (bongo-playing-p)))
174 b))) 174 b)))
175 (buffer-list)))) 175 (buffer-list))))
176 (with-bongo-playlist-buffer 176 (with-bongo-playlist-buffer
177 (bongo-pause/resume)))) 177 (bongo-pause/resume))))
178 :help ,(funcall bongo-header-line-function))))) 178 :help ,(funcall bongo-header-line-function)))))
179 179
180(defvar +tab-bar-show-original nil 180(defvar +tab-bar-show-original nil
181 "Original value of `tab-bar-show'.") 181 "Original value of `tab-bar-show'.")
@@ -192,49 +192,49 @@
192 192
193;;; FIXME this doesn't work... 193;;; FIXME this doesn't work...
194;; (defvar +tab-bar-tab-min-width 8 194;; (defvar +tab-bar-tab-min-width 8
195;; "Minimum width of a tab on the tab bar.") 195 ;; "Minimum width of a tab on the tab bar.")
196 196
197;; (defvar +tab-bar-tab-max-width 24 197;; (defvar +tab-bar-tab-max-width 24
198;; "Maximum width of a tab on the tab bar.") 198 ;; "Maximum width of a tab on the tab bar.")
199 199
200;; (defun +tab-bar-fluid-calculate-width () 200;; (defun +tab-bar-fluid-calculate-width ()
201;; "Calculate the width of each tab in the tab-bar." 201 ;; "Calculate the width of each tab in the tab-bar."
202;; (let* ((tab-bar-list (cdr (tab-bar-make-keymap-1))) 202 ;; (let* ((tab-bar-list (cdr (tab-bar-make-keymap-1)))
203;; (tab-bar-avail-width (frame-width)) 203 ;; (tab-bar-avail-width (frame-width))
204;; (tab-bar-tab-count (length (tab-bar-tabs))) 204 ;; (tab-bar-tab-count (length (tab-bar-tabs)))
205;; (tab-bar-close-button-char-width 1) 205 ;; (tab-bar-close-button-char-width 1)
206;; (tab-bar-add-tab-button-char-width 1) 206 ;; (tab-bar-add-tab-button-char-width 1)
207;; (tab-bar-total-width 207 ;; (tab-bar-total-width
208;; (length (mapconcat 208 ;; (length (mapconcat
209;; (lambda (el) 209 ;; (lambda (el)
210;; (when-let ((str (car-safe (cdr-safe (cdr-safe el))))) 210 ;; (when-let ((str (car-safe (cdr-safe (cdr-safe el)))))
211;; (substring-no-properties (eval str)))) 211 ;; (substring-no-properties (eval str))))
212;; tab-bar-list))) 212 ;; tab-bar-list)))
213;; (tab-bar-total-tab-width 213 ;; (tab-bar-total-tab-width
214;; (+ (* tab-bar-tab-count tab-bar-close-button-char-width) 214 ;; (+ (* tab-bar-tab-count tab-bar-close-button-char-width)
215;; tab-bar-add-tab-button-char-width 215 ;; tab-bar-add-tab-button-char-width
216;; (length (mapconcat 216 ;; (length (mapconcat
217;; (lambda (el) 217 ;; (lambda (el)
218;; (substring-no-properties (alist-get 'name el))) 218 ;; (substring-no-properties (alist-get 'name el)))
219;; (tab-bar-tabs))))) 219 ;; (tab-bar-tabs)))))
220;; (tab-bar-total-nontab-width (- tab-bar-total-width 220 ;; (tab-bar-total-nontab-width (- tab-bar-total-width
221;; tab-bar-total-tab-width))) 221 ;; tab-bar-total-tab-width)))
222;; (min +tab-bar-tab-max-width 222 ;; (min +tab-bar-tab-max-width
223;; (max +tab-bar-tab-min-width 223 ;; (max +tab-bar-tab-min-width
224;; (/ (- tab-bar-avail-width 224 ;; (/ (- tab-bar-avail-width
225;; tab-bar-total-tab-width 225 ;; tab-bar-total-tab-width
226;; tab-bar-total-nontab-width) 226 ;; tab-bar-total-nontab-width)
227;; tab-bar-tab-count))))) 227 ;; tab-bar-tab-count)))))
228 228
229;; (defun +tab-bar-fluid-width () 229;; (defun +tab-bar-fluid-width ()
230;; "Generate the tab name to fluidly fit in the given space." 230 ;; "Generate the tab name to fluidly fit in the given space."
231;; (let* ((tab-file-name (buffer-file-name (window-buffer 231 ;; (let* ((tab-file-name (buffer-file-name (window-buffer
232;; (minibuffer-selected-window))))) 232 ;; (minibuffer-selected-window)))))
233;; (format (format " %%s%%%ds" (+tab-bar-fluid-calculate-width)) 233 ;; (format (format " %%s%%%ds" (+tab-bar-fluid-calculate-width))
234;; (if tab-file-name 234 ;; (if tab-file-name
235;; (file-name-nondirectory tab-file-name) 235 ;; (file-name-nondirectory tab-file-name)
236;; (+tab-bar-tab-name-truncated-left)) 236 ;; (+tab-bar-tab-name-truncated-left))
237;; " "))) 237 ;; " ")))
238 238
239(defun +tab-bar-tab-name-truncated-left () 239(defun +tab-bar-tab-name-truncated-left ()
240 "Generate the tab name from the buffer of the selected window. 240 "Generate the tab name from the buffer of the selected window.
@@ -259,13 +259,13 @@ name to the left."
259(defun +tab-bar-format-align-right () 259(defun +tab-bar-format-align-right ()
260 "Align the rest of tab bar items to the right, pixel-wise." 260 "Align the rest of tab bar items to the right, pixel-wise."
261 ;; XXX: ideally, wouldn't require `shr' here 261 ;; XXX: ideally, wouldn't require `shr' here
262 (require 'shr) ; `shr-string-pixel-width' 262 (require 'shr) ; `shr-string-pixel-width'
263 (let* ((rest (cdr (memq '+tab-bar-format-align-right tab-bar-format))) 263 (let* ((rest (cdr (memq '+tab-bar-format-align-right tab-bar-format)))
264 (rest (tab-bar-format-list rest)) 264 (rest (tab-bar-format-list rest))
265 (rest (mapconcat (lambda (item) (nth 2 item)) rest "")) 265 (rest (mapconcat (lambda (item) (nth 2 item)) rest ""))
266 (hpos (shr-string-pixel-width rest)) 266 (hpos (shr-string-pixel-width rest))
267 (str (propertize " " 'display `(space :align-to (- right (,hpos)))))) 267 (str (propertize " " 'display `(space :align-to (- right (,hpos))))))
268 `((align-right menu-item ,str ignore)))) 268 `((align-right menu-item ,str ignore))))
269 269
270 270
271;;; Menu bar 271;;; Menu bar
@@ -309,18 +309,18 @@ Used by `tab-bar-format-menu-bar'."
309 `((current-tab 309 `((current-tab
310 menu-item 310 menu-item
311 ,(funcall tab-bar-tab-name-format-function tab i) 311 ,(funcall tab-bar-tab-name-format-function tab i)
312 ignore 312 ignore
313 :help "Current tab"))) 313 :help "Current tab")))
314 (t 314 (t
315 `((,(intern (format "tab-%i" i)) 315 `((,(intern (format "tab-%i" i))
316 menu-item 316 menu-item
317 ,(funcall tab-bar-tab-name-format-function tab i) 317 ,(funcall tab-bar-tab-name-format-function tab i)
318 ,(alist-get 'binding tab) 318 ,(alist-get 'binding tab)
319 :help "Click to visit tab")))) 319 :help "Click to visit tab"))))
320 (when (alist-get 'close-binding tab) 320 (when (alist-get 'close-binding tab)
321 `((,(if (eq (car tab) 'current-tab) 'C-current-tab (intern (format "C-tab-%i" i))) 321 `((,(if (eq (car tab) 'current-tab) 'C-current-tab (intern (format "C-tab-%i" i)))
322 menu-item "" 322 menu-item ""
323 ,(alist-get 'close-binding tab))))))) 323 ,(alist-get 'close-binding tab)))))))
324 324
325 325
326;; Emacs 27 326;; Emacs 27
@@ -334,7 +334,7 @@ This is :filter-return advice for `tab-bar-make-keymap-1'."
334 ,reserve))))) 334 ,reserve)))))
335 (prog1 (append output 335 (prog1 (append output
336 `((align-right menu-item ,str nil)) 336 `((align-right menu-item ,str nil))
337 (+tab-bar-misc-info))))) 337 (+tab-bar-misc-info)))))
338 338
339 339
340;; Emacs 28 340;; Emacs 28
@@ -353,27 +353,27 @@ This is :filter-return advice for `tab-bar-make-keymap-1'."
353(define-minor-mode +tab-bar-misc-info-mode 353(define-minor-mode +tab-bar-misc-info-mode
354 "Show the `mode-line-misc-info' in the `tab-bar'." 354 "Show the `mode-line-misc-info' in the `tab-bar'."
355 :lighter "" 355 :lighter ""
356 :global t 356 :global t
357 (if +tab-bar-misc-info-mode 357 (if +tab-bar-misc-info-mode
358 (progn ; Enable 358 (progn ; Enable
359 (setq +tab-bar-show-original tab-bar-show) 359 (setq +tab-bar-show-original tab-bar-show)
360 (cond 360 (cond
361 ((boundp 'tab-bar-format) ; Emacs 28 361 ((boundp 'tab-bar-format) ; Emacs 28
362 (setq +tab-bar-format-original tab-bar-format) 362 (setq +tab-bar-format-original tab-bar-format)
363 (unless (memq '+tab-bar-misc-info tab-bar-format) 363 (unless (memq '+tab-bar-misc-info tab-bar-format)
364 (setq tab-bar-format 364 (setq tab-bar-format
365 (append tab-bar-format (+tab-bar-misc-info-28))))) 365 (append tab-bar-format (+tab-bar-misc-info-28)))))
366 ((fboundp 'tab-bar-make-keymap-1) ; Emacs 27 366 ((fboundp 'tab-bar-make-keymap-1) ; Emacs 27
367 (advice-add 'tab-bar-make-keymap-1 :filter-return 367 (advice-add 'tab-bar-make-keymap-1 :filter-return
368 '+tab-bar-misc-info-27))) 368 '+tab-bar-misc-info-27)))
369 (setq tab-bar-show t)) 369 (setq tab-bar-show t))
370 (progn ; Disable 370 (progn ; Disable
371 (setq tab-bar-show +tab-bar-show-original) 371 (setq tab-bar-show +tab-bar-show-original)
372 (cond 372 (cond
373 ((boundp 'tab-bar-format) ; Emacs 28 373 ((boundp 'tab-bar-format) ; Emacs 28
374 (setq tab-bar-format +tab-bar-format-original)) 374 (setq tab-bar-format +tab-bar-format-original))
375 ((fboundp 'tab-bar-make-keymap-1) ; Emacs 27 375 ((fboundp 'tab-bar-make-keymap-1) ; Emacs 27
376 (advice-remove 'tab-bar-make-keymap-1 '+tab-bar-misc-info-27)))))) 376 (advice-remove 'tab-bar-make-keymap-1 '+tab-bar-misc-info-27))))))
377 377
378 378
379 379
diff --git a/lisp/+window.el b/lisp/+window.el new file mode 100644 index 0000000..52b3712 --- /dev/null +++ b/lisp/+window.el
@@ -0,0 +1,130 @@
1;;; +window.el --- Fixes for Emacs's window.el -*- lexical-binding: t; -*-
2
3;;; Commentary:
4
5;; Do I want to propose this change in the Emacs ML?
6
7;;; Code:
8
9(require 'window)
10
11;;; Split windows based on `window-total-width', not `window-width'
12;; I have to just redefine these functions because the check is really deep in
13;; there.
14
15(defun window-splittable-p (window &optional horizontal)
16 "Return non-nil if `split-window-sensibly' may split WINDOW.
17Optional argument HORIZONTAL nil or omitted means check whether
18`split-window-sensibly' may split WINDOW vertically. HORIZONTAL
19non-nil means check whether WINDOW may be split horizontally.
20
21WINDOW may be split vertically when the following conditions
22hold:
23- `window-size-fixed' is either nil or equals `width' for the
24 buffer of WINDOW.
25- `split-height-threshold' is an integer and WINDOW is at least as
26 high as `split-height-threshold'.
27- When WINDOW is split evenly, the emanating windows are at least
28 `window-min-height' lines tall and can accommodate at least one
29 line plus - if WINDOW has one - a mode line.
30
31WINDOW may be split horizontally when the following conditions
32hold:
33- `window-size-fixed' is either nil or equals `height' for the
34 buffer of WINDOW.
35- `split-width-threshold' is an integer and WINDOW is at least as
36 wide as `split-width-threshold'.
37- When WINDOW is split evenly, the emanating windows are at least
38 `window-min-width' or two (whichever is larger) columns wide."
39 (when (and (window-live-p window)
40 (not (window-parameter window 'window-side)))
41 (with-current-buffer (window-buffer window)
42 (if horizontal
43 ;; A window can be split horizontally when its width is not
44 ;; fixed, it is at least `split-width-threshold' columns wide
45 ;; and at least twice as wide as `window-min-width' and 2 (the
46 ;; latter value is hardcoded).
47 (and (memq window-size-fixed '(nil height))
48 ;; Testing `window-full-width-p' here hardly makes any
49 ;; sense nowadays. This can be done more intuitively by
50 ;; setting up `split-width-threshold' appropriately.
51 (numberp split-width-threshold)
52 (>= (window-total-width window)
53 (max split-width-threshold
54 (* 2 (max window-min-width 2)))))
55 ;; A window can be split vertically when its height is not
56 ;; fixed, it is at least `split-height-threshold' lines high,
57 ;; and it is at least twice as high as `window-min-height' and 2
58 ;; if it has a mode line or 1.
59 (and (memq window-size-fixed '(nil width))
60 (numberp split-height-threshold)
61 (>= (window-height window)
62 (max split-height-threshold
63 (* 2 (max window-min-height
64 (if mode-line-format 2 1))))))))))
65
66(defun split-window-sensibly (&optional window)
67 "Split WINDOW in a way suitable for `display-buffer'.
68WINDOW defaults to the currently selected window.
69If `split-height-threshold' specifies an integer, WINDOW is at
70least `split-height-threshold' lines tall and can be split
71vertically, split WINDOW into two windows one above the other and
72return the lower window. Otherwise, if `split-width-threshold'
73specifies an integer, WINDOW is at least `split-width-threshold'
74columns wide and can be split horizontally, split WINDOW into two
75windows side by side and return the window on the right. If this
76can't be done either and WINDOW is the only window on its frame,
77try to split WINDOW vertically disregarding any value specified
78by `split-height-threshold'. If that succeeds, return the lower
79window. Return nil otherwise.
80
81By default `display-buffer' routines call this function to split
82the largest or least recently used window. To change the default
83customize the option `split-window-preferred-function'.
84
85You can enforce this function to not split WINDOW horizontally,
86by setting (or binding) the variable `split-width-threshold' to
87nil. If, in addition, you set `split-height-threshold' to zero,
88chances increase that this function does split WINDOW vertically.
89
90In order to not split WINDOW vertically, set (or bind) the
91variable `split-height-threshold' to nil. Additionally, you can
92set `split-width-threshold' to zero to make a horizontal split
93more likely to occur.
94
95Have a look at the function `window-splittable-p' if you want to
96know how `split-window-sensibly' determines whether WINDOW can be
97split."
98 (let ((window (or window (selected-window))))
99 (or (and (window-splittable-p window)
100 ;; Split window vertically.
101 (with-selected-window window
102 (split-window-below)))
103 (and (window-splittable-p window t)
104 ;; Split window horizontally.
105 (with-selected-window window
106 (split-window-right)))
107 (and
108 ;; If WINDOW is the only usable window on its frame (it is
109 ;; the only one or, not being the only one, all the other
110 ;; ones are dedicated) and is not the minibuffer window, try
111 ;; to split it vertically disregarding the value of
112 ;; `split-height-threshold'.
113 (let ((frame (window-frame window)))
114 (or
115 (eq window (frame-root-window frame))
116 (catch 'done
117 (walk-window-tree (lambda (w)
118 (unless (or (eq w window)
119 (window-dedicated-p w))
120 (throw 'done nil)))
121 frame nil 'nomini)
122 t)))
123 (not (window-minibuffer-p window))
124 (let ((split-height-threshold 0))
125 (when (window-splittable-p window)
126 (with-selected-window window
127 (split-window-below))))))))
128
129(provide '+window)
130;;; +window.el ends here
diff --git a/lisp/private.el b/lisp/private.el index f9c4753..4f6115e 100644 --- a/lisp/private.el +++ b/lisp/private.el
@@ -15,5 +15,9 @@
15 "Private secretive secrets inside.") 15 "Private secretive secrets inside.")
16(add-to-list 'load-path private/) 16(add-to-list 'load-path private/)
17 17
18;; Load random private stuff
19
20(require '_acdw)
21
18(provide 'private) 22(provide 'private)
19;;; private.el ends here 23;;; private.el ends here