diff options
-rw-r--r-- | early-init.el | 7 | ||||
-rw-r--r-- | init.el | 212 | ||||
-rw-r--r-- | lisp/+apheleia.el | 51 | ||||
-rw-r--r-- | lisp/+avy.el | 40 | ||||
-rw-r--r-- | lisp/+circe.el | 52 | ||||
-rw-r--r-- | lisp/+cus-edit.el | 2 | ||||
-rw-r--r-- | lisp/+emacs.el | 17 | ||||
-rw-r--r-- | lisp/+flyspell-correct.el | 3 | ||||
-rw-r--r-- | lisp/+modeline.el | 22 | ||||
-rw-r--r-- | lisp/+nyan-mode.el | 39 | ||||
-rw-r--r-- | lisp/+org-wc.el | 2 | ||||
-rw-r--r-- | lisp/+org.el | 53 | ||||
-rw-r--r-- | lisp/+tab-bar.el | 314 | ||||
-rw-r--r-- | lisp/+window.el | 130 | ||||
-rw-r--r-- | lisp/private.el | 4 |
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. | ||
39 | NAME is the name given to the formatter in `apheleia-formatters' | ||
40 | and `apheleia-mode-alist'. FORMATTER is the command paired with | ||
41 | NAME in `apheleia-formatters'. MODE is the mode or modes to add | ||
42 | NAME to in `apheleia-mode-alist'. If MODE is not given or nil, | ||
43 | use the setup form's MODE. Optional argument -PEND can be one of | ||
44 | `:append' or `:prepend', and if given will append or prepend the | ||
45 | given NAME to the current formatters for the MODE in | ||
46 | `apheleia-mode-alist', rather than replace them (the default). | ||
47 | |||
48 | Example: | ||
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 | |||
59 | This 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. |
50 | When called with optional MESSAGE non-nil, or interactively, also | 53 | When called with optional MESSAGE non-nil, or interactively, also |
51 | message the current topic." | 54 | message 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. |
87 | For entry into `lui-formatting-list'." | 93 | For 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 | ||
144 | Connect to the given network specified by NETWORK-OR-SERVER. | 150 | Connect 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 | |||
157 | locally in the server buffer. | 163 | locally in the server buffer. |
158 | 164 | ||
159 | See `circe-network-options' for a list of common options." | 165 | See `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. |
7 | With PREFIX, prompt to change the current dictionary." | 9 | With 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 |
368 | to a function in the current buffer, call that function instead." | 368 | to 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. | ||
693 | When optional argument ALL is non-nil, align all tags in the | ||
694 | visible 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. | ||
720 | See `org-meta-return', but `+org-return-dwim' does most of the | ||
721 | stuff I would want out of that function already. | ||
722 | |||
723 | When 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. | ||
17 | Optional argument HORIZONTAL nil or omitted means check whether | ||
18 | `split-window-sensibly' may split WINDOW vertically. HORIZONTAL | ||
19 | non-nil means check whether WINDOW may be split horizontally. | ||
20 | |||
21 | WINDOW may be split vertically when the following conditions | ||
22 | hold: | ||
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 | |||
31 | WINDOW may be split horizontally when the following conditions | ||
32 | hold: | ||
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'. | ||
68 | WINDOW defaults to the currently selected window. | ||
69 | If `split-height-threshold' specifies an integer, WINDOW is at | ||
70 | least `split-height-threshold' lines tall and can be split | ||
71 | vertically, split WINDOW into two windows one above the other and | ||
72 | return the lower window. Otherwise, if `split-width-threshold' | ||
73 | specifies an integer, WINDOW is at least `split-width-threshold' | ||
74 | columns wide and can be split horizontally, split WINDOW into two | ||
75 | windows side by side and return the window on the right. If this | ||
76 | can't be done either and WINDOW is the only window on its frame, | ||
77 | try to split WINDOW vertically disregarding any value specified | ||
78 | by `split-height-threshold'. If that succeeds, return the lower | ||
79 | window. Return nil otherwise. | ||
80 | |||
81 | By default `display-buffer' routines call this function to split | ||
82 | the largest or least recently used window. To change the default | ||
83 | customize the option `split-window-preferred-function'. | ||
84 | |||
85 | You can enforce this function to not split WINDOW horizontally, | ||
86 | by setting (or binding) the variable `split-width-threshold' to | ||
87 | nil. If, in addition, you set `split-height-threshold' to zero, | ||
88 | chances increase that this function does split WINDOW vertically. | ||
89 | |||
90 | In order to not split WINDOW vertically, set (or bind) the | ||
91 | variable `split-height-threshold' to nil. Additionally, you can | ||
92 | set `split-width-threshold' to zero to make a horizontal split | ||
93 | more likely to occur. | ||
94 | |||
95 | Have a look at the function `window-splittable-p' if you want to | ||
96 | know how `split-window-sensibly' determines whether WINDOW can be | ||
97 | split." | ||
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 |