From 038e5de1adf2de6cdf28a428a44b0753813b928c Mon Sep 17 00:00:00 2001 From: Case Duckworth Date: Wed, 29 Dec 2021 22:55:55 -0600 Subject: Lots and lots of changes, oh jeez --- init.el | 223 +++++++++++++++++++++++++++++------------------------- lisp/+emacs.el | 95 +++++++++++++---------- lisp/+init.el | 6 ++ lisp/+lisp.el | 89 ++++++++++++++++++++++ lisp/+modeline.el | 110 +++++++++++++++++++-------- lisp/+setup.el | 2 +- lisp/+util.el | 5 +- 7 files changed, 353 insertions(+), 177 deletions(-) diff --git a/init.el b/init.el index d4a6a0f..1000714 100644 --- a/init.el +++ b/init.el @@ -24,13 +24,19 @@ (setq debug-on-error t) (setup (:require +emacs) + (:also-load +lisp) ;; +emacs.el contains super-basic defaults that are basically ;; necessary for good functioning. In this block, I add extra ;; things or more "experimental" ones that might not belong in a ;; separate file. - (:global "C-x C-k" 'kill-this-buffer - "C-x 4 n" 'clone-buffer - "C-c v" 'visible-mode) + (:global "C-x C-k" #'kill-this-buffer + "C-x 4 n" #'clone-buffer + "C-c v" #'visible-mode + "C-M-;" #'+lisp-comment-or-uncomment-sexp) + ;; Unbind stuff, too. + (dolist (key '("C-M-j" + "M-j")) + (global-set-key (kbd key) nil)) ;; C-h deletes backward - see https://idiomdrottning.org/bad-emacs-defaults (global-set-key (kbd "C-h") 'delete-backward-char) (keyboard-translate ?\C-h ?\C-?) @@ -44,10 +50,7 @@ (advice-add 'yank-pop :after '+yank@indent)) (setup (:require +init) - (:bind "C-c s" (lambda () - (interactive) - (+init-sort) - (save-buffer))) + (:bind "C-c s" #'+init-sort-then-save) (:hook #'+init-add-setup-to-imenu)) (setup (:require +key) @@ -68,8 +71,7 @@ (:also-load +pulse) (:option pulse-flag nil pulse-delay 0.5 - pulse-iterations 1 - (append +pulse-location-commands) 'lui-track-jump-to-indicator) + pulse-iterations 1) (+pulse-location-mode +1)) (setup (:require reading) @@ -93,8 +95,8 @@ (setup browse-url (:require +browse-url) (:option browse-url-secondary-browser-function (if (executable-find "firefox") - 'browse-url-firefox - 'browse-url-default-browser) + #'browse-url-firefox + #'browse-url-default-browser) browse-url-new-window-flag nil browse-url-firefox-arguments '("--new-tab") browse-url-firefox-new-window-is-tab t) @@ -105,15 +107,15 @@ "." (or "jpeg" "jpg" "png") eos) (lambda (&rest args) (apply - (cond ((executable-find "mpv") '+browse-image-with-mpv) - (t 'eww-browse-url)) + (cond ((executable-find "mpv") #'+browse-image-with-mpv) + (t #'eww-browse-url)) args))) (cons (rx ; videos (or "youtube.com" "youtu.be" "yewtu.be" (seq "." (or "mp4" "gif" "mov" "MOV") eos))) (lambda (&rest args) (apply (if (executable-find "mpv") - '+browse-url-with-mpv + #'+browse-url-with-mpv browse-url-secondary-browser-function) args))) (cons (rx ; non-eww-friendly websites @@ -130,7 +132,7 @@ )) browse-url-secondary-browser-function) (cons "." ; everything else - 'eww-browse-url))) + #'eww-browse-url))) ;; Transform URLs before passing to `browse-url' (:option +browse-url-transformations `((,(rx "//" (or "youtube.com" "youtu.be")) @@ -163,7 +165,8 @@ custom-raised-buttons nil custom-unlispify-tag-names nil custom-variable-default-form 'lisp - +custom-variable-allowlist '(safe-local-variable-values)) + +custom-variable-allowlist '(safe-local-variable-values + warning-suppress-types)) (when (file-exists-p custom-file) (+custom-load-ignoring-most-customizations t)) (advice-add #'custom-buffer-create-internal :after #'+cus-edit-expand-widgets) @@ -183,10 +186,10 @@ dired-listing-switches "-Al" ls-lisp-dirs-first t dired-ls-F-marks-symlinks t - dired-no-confirm '(byte-compile - chgrp chmod chown copy - hardlink load move - shell touch symlink) + dired-no-confirm '(byte-compile load + chgrp chmod chown + copy move hardlink symlink + shell touch) dired-dwim-target t) (:bind "" #'dired-up-directory "TAB" #'dired-subtree-cycle @@ -205,7 +208,7 @@ (:option dired-listing-switches (concat dired-listing-switches " -F"))))) (with-eval-after-load 'frowny - (add-to-list 'frowny-inhibit-modes 'dired-mode))) + (add-to-list 'frowny-inhibit-modes #'dired-mode))) (setup eldoc (:hook-into elisp-mode @@ -333,7 +336,7 @@ (setup scratch (:require +scratch) - (:option initial-major-mode 'lisp-interaction-mode + (:option initial-major-mode #'lisp-interaction-mode initial-scratch-message ";; ABANDON ALL HOPE YE WHO ENTER HERE\n\n") (add-hook 'kill-buffer-query-functions #'+scratch-immortal)) @@ -344,7 +347,7 @@ (setup (:straight 0x0) (:option 0x0-default-server 'ttm) (with-eval-after-load 'embark - (define-key embark-region-map (kbd "U") '0x0-dwim))) + (define-key embark-region-map (kbd "U") #'0x0-dwim))) (setup (:straight ace-window) (:require +ace-window) @@ -416,7 +419,7 @@ circe-prompt-string (format (format "%%%ds> " (- +circe-left-margin 2)) " ")) - + (:option +circe-server-buffer-action (lambda (buf) (message "Connected to %s" buf)) +circe-network-inhibit-autoconnect _circe-network-inhibit-autoconnect @@ -434,7 +437,7 @@ (advice-add #'circe-command-PART :after #'+circe-kill-buffer) (advice-add #'circe-command-QUIT :after #'+circe-quit@kill-buffer) (advice-add #'circe-command-GQUIT :after #'+circe-gquit@kill-buffer) - + (:with-mode circe-chat-mode (:hook #'enable-circe-color-nicks #'enable-circe-new-day-notifier @@ -454,7 +457,8 @@ (,(+lui-make-formatting-list-rx "_") 1 lui-emphasis-face) (,(+lui-make-formatting-list-rx "/") - 1 lui-emphasis-face))) + 1 lui-emphasis-face)) + (append +pulse-location-commands) 'lui-track-jump-to-indicator) (:hook #'visual-line-mode #'enable-lui-track #'visual-fill-column-mode) @@ -481,67 +485,67 @@ (:also-load +consult) ;; from Consult wiki (:option register-preview-delay 0 - register-preview-function 'consult-register-format - xref-show-xrefs-function 'consult-xref - xref-show-definitions-function 'consult-xref - tab-always-indent 'complete - completion-in-region-function 'consult-completion-in-region) + register-preview-function 'consult-register-format + xref-show-xrefs-function 'consult-xref + xref-show-definitions-function 'consult-xref + tab-always-indent 'complete + completion-in-region-function 'consult-completion-in-region) (advice-add #'register-preview :override #'consult-register-window) (advice-add #'completing-read-multiple :override - #'consult-completing-read-multiple) + #'consult-completing-read-multiple) (dolist (binding '(;; C-c bindings (mode-specific-map) - ("C-c h" . consult-history) - ("C-c m" . consult-mode-command) - ("C-c b" . consult-bookmark) - ("C-c k" . consult-kmacro) - ;; C-x bindings (ctl-x-map) - ("C-x M-:" . consult-complex-command) - ("C-x b" . consult-buffer) - ("C-x 4 b" . consult-buffer-other-window) - ("C-x 5 b" . consult-buffer-other-frame) - ;; Custom M-# bindings for fast register access - ("M-#" . consult-register-load) - ("M-'" . consult-register-store) - ("C-M-#" . consult-register) - ;; Other custom bindings - ("M-y" . consult-yank-pop) - (" a" . consult-apropos) - ;; M-g bindings (goto-map) - ("M-g e" . consult-compile-error) - ("M-g f" . consult-flymake) ; or consult-flycheck - ("M-g g" . consult-goto-line) - ("M-g M-g" . consult-goto-line) - ("M-g o" . consult-outline) ; or consult-org-heading - ("M-g m" . consult-mark) - ("M-g k" . consult-global-mark) - ("M-g i" . consult-imenu) - ("M-g I" . consult-imenu-multi) - ;; M-s bindings (search-map) - ("M-s f" . consult-find) - ("M-s F" . consult-locate) - ("M-s g" . consult-grep) - ("M-s G" . consult-git-grep) - ("M-s r" . consult-ripgrep) - ("M-s l" . consult-line) - ("M-s L" . consult-line-multi) - ("M-s m" . consult-multi-occur) - ("M-s k" . consult-keep-lines) - ("M-s u" . consult-focus-lines) - ;; Isearch integration - ("M-s e" . consult-isearch-history))) + ("C-c h" . consult-history) + ("C-c m" . consult-mode-command) + ("C-c b" . consult-bookmark) + ("C-c k" . consult-kmacro) + ;; C-x bindings (ctl-x-map) + ("C-x M-:" . consult-complex-command) + ("C-x b" . consult-buffer) + ("C-x 4 b" . consult-buffer-other-window) + ("C-x 5 b" . consult-buffer-other-frame) + ;; Custom M-# bindings for fast register access + ("M-#" . consult-register-load) + ("M-'" . consult-register-store) + ("C-M-#" . consult-register) + ;; Other custom bindings + ("M-y" . consult-yank-pop) + (" a" . consult-apropos) + ;; M-g bindings (goto-map) + ("M-g e" . consult-compile-error) + ("M-g f" . consult-flymake) ; or consult-flycheck + ("M-g g" . consult-goto-line) + ("M-g M-g" . consult-goto-line) + ("M-g o" . consult-outline) ; or consult-org-heading + ("M-g m" . consult-mark) + ("M-g k" . consult-global-mark) + ("M-g i" . consult-imenu) + ("M-g I" . consult-imenu-multi) + ;; M-s bindings (search-map) + ("M-s f" . consult-find) + ("M-s F" . consult-locate) + ("M-s g" . consult-grep) + ("M-s G" . consult-git-grep) + ("M-s r" . consult-ripgrep) + ("M-s l" . consult-line) + ("M-s L" . consult-line-multi) + ("M-s m" . consult-multi-occur) + ("M-s k" . consult-keep-lines) + ("M-s u" . consult-focus-lines) + ;; Isearch integration + ("M-s e" . consult-isearch-history))) (define-key +key-mode-map (kbd (car binding)) (cdr binding))) (with-eval-after-load 'isearch-mode (dolist (binding '(("M-e" . consult-isearch-history) - ("M-s e" . consult-isearch-history) - ("M-s l" . consult-line) - ("M-s L" . consult-line-multi))) + ("M-s e" . consult-isearch-history) + ("M-s l" . consult-line) + ("M-s L" . consult-line-multi))) (define-key isearch-mode-map (car binding) (cdr binding)))) (with-eval-after-load 'org-mode (define-key org-mode-map "M-g o" 'consult-org-heading)) (advice-add 'consult-yank-pop :after '+yank@indent) (with-eval-after-load 'consult (:option consult-narrow-key "<" - consult-project-root-function '+consult-project-root) + consult-project-root-function '+consult-project-root) (consult-customize consult-theme :preview-key '(:debounce 0.2 any) @@ -629,8 +633,8 @@ See also `crux-reopen-as-root-mode'." (setup (:straight embark) (:option prefix-help-command 'embark-prefix-help-command) (:+key "C-." #'embark-act - "M-." #'embark-dwim - " B" #'embark-bindings)) + "M-." #'embark-dwim + " B" #'embark-bindings)) (setup (:straight embark-consult) (:load-after consult embark) @@ -708,7 +712,7 @@ See also `crux-reopen-as-root-mode'." (setup (:straight hungry-delete) (:option hungry-delete-chars-to-skip " \t" - hungry-delete-join-reluctantly nil) + hungry-delete-join-reluctantly nil) (:bind-into paredit ;; I define these functions here because they really require both packages ;; to make any sense. So, would I put them in `+hungry-delete' or @@ -717,14 +721,14 @@ See also `crux-reopen-as-root-mode'." (defun acdw/paredit-hungry-delete-backward (arg) (interactive "P") (if (looking-back "[ \t]" 1) - (hungry-delete-backward (or arg 1)) - (paredit-backward-delete arg))) + (hungry-delete-backward (or arg 1)) + (paredit-backward-delete arg))) [remap paredit-forward-delete] (defun acdw/paredit-hungry-delete-forward (arg) (interactive "P") (if (looking-at "[ \t]") - (hungry-delete-forward (or arg 1)) - (paredit-forward-delete arg)))) + (hungry-delete-forward (or arg 1)) + (paredit-forward-delete arg)))) (global-hungry-delete-mode +1)) (setup (:straight isearch-mb) @@ -733,19 +737,19 @@ See also `crux-reopen-as-root-mode'." ;; project's README. (with-eval-after-load 'isearch-mb (dolist (spec '((isearch-mb--with-buffer - ("M-e" . consult-isearch) - ("C-o" . loccur-isearch)) - (isearch-mb--after-exit - ("M-%" . anzu-isearch-query-replace) - ("M-s l" . consult-line)))) + ("M-e" . consult-isearch) + ("C-o" . loccur-isearch)) + (isearch-mb--after-exit + ("M-%" . anzu-isearch-query-replace) + ("M-s l" . consult-line)))) (let ((isearch-mb-list (car spec)) - (isearch-mb-binds (cdr spec))) - (dolist (cell isearch-mb-binds) - (let ((key (car cell)) - (command (cdr cell))) - (when (fboundp command) - (add-to-list isearch-mb-list command) - (define-key isearch-mb-minibuffer-map (kbd key) command))))))) + (isearch-mb-binds (cdr spec))) + (dolist (cell isearch-mb-binds) + (let ((key (car cell)) + (command (cdr cell))) + (when (fboundp command) + (add-to-list isearch-mb-list command) + (define-key isearch-mb-minibuffer-map (kbd key) command))))))) (isearch-mb-mode +1)) (setup (:straight lacarte) @@ -881,11 +885,18 @@ See also `crux-reopen-as-root-mode'." (setup (:straight org-sticky-header) (:hook-into org-mode)) +(setup (:straight package-lint)) + (setup (:straight paredit) (:bind "DEL" #'paredit-backward-delete "C-" #'paredit-backward-kill-word) - (:hook-into emacs-lisp-mode lisp-interaction-mode - lisp-mode scheme-mode) + (dolist (hook '(emacs-lisp-mode-hook + eval-expression-minibuffer-setup-hook + ielm-mode-hook + lisp-interaction-mode-hook + lisp-mode-hook + scheme-mode-hook)) + (add-hook hook #'enable-paredit-mode)) (:also-load eldoc) (eldoc-add-command #'paredit-backward-delete #'paredit-close-round)) @@ -911,13 +922,15 @@ See also `crux-reopen-as-root-mode'." (setup (:straight sicp)) (setup (:straight (simple-modeline - :fork (:repo "duckwork/simple-modeline"))) + :fork (:host github :repo "duckwork/simple-modeline"))) (:also-load +modeline) - (:option simple-modeline-segments '((;; left + (:option simple-modeline-segments `((;; left +modeline-ace-window-display +modeline-modified - +modeline-reading-mode - +modeline-narrowed + ,(+modeline-concat + '(+modeline-reading-mode + +modeline-narrowed) + ",") +modeline-buffer-name +modeline-position +modeline-anzu @@ -968,8 +981,8 @@ See also `crux-reopen-as-root-mode'." (list (propertize " " 'display - `((space - :align-to + `((space + :align-to ,(unless (bound-and-true-p visual-fill-column-mode) 0)))) (funcall topsy-fn)))))) @@ -1023,7 +1036,6 @@ See also `crux-reopen-as-root-mode'." (setup (:straight whitespace-cleanup-mode) (:option whitespace-cleanup-mode-preserve-point t) - ;;(remove-hook 'before-save-hook 'whitespace-cleanup) (global-whitespace-cleanup-mode +1)) (setup (:straight zoom-frm)) @@ -1034,3 +1046,8 @@ See also `crux-reopen-as-root-mode'." (interactive "P") (call-interactively (if prefix #'zzz-up-to-char #'zzz-to-char))))) + +(setup (:straight (actually-selected-window + :host github + :repo "duckwork/actually-selected-window.el")) + (actually-selected-window-mode +1)) diff --git a/lisp/+emacs.el b/lisp/+emacs.el index 7ad6768..2d63e82 100644 --- a/lisp/+emacs.el +++ b/lisp/+emacs.el @@ -11,7 +11,8 @@ ;; Emacs. But like, why would I want to? ;; Other notable packages include -;; https://git.sr.ht/~technomancy/better-defaults/ +;; - https://git.sr.ht/~technomancy/better-defaults/ +;; - https://github.com/susam/emfy ;;; Code: @@ -45,6 +46,7 @@ Do this only if the buffer is not visiting a file." completion-category-overrides '((file (styles . (partial-completion)))) completion-ignore-case t completion-styles '(substring partial-completion) + create-lockfiles nil cursor-in-non-selected-windows 'hollow cursor-type 'bar custom-file (.etc "custom.el") @@ -64,6 +66,8 @@ Do this only if the buffer is not visiting a file." hscroll-step 1 imenu-auto-rescan t indent-tabs-mode nil + indicate-empty-lines t + indicate-buffer-boundaries 'left inhibit-startup-screen t initial-buffer-choice t kill-do-not-save-duplicates t @@ -75,8 +79,8 @@ Do this only if the buffer is not visiting a file." mark-ring-max 50 minibuffer-eldef-shorten-default t minibuffer-prompt-properties (list 'read-only t - 'cursor-intangible t - 'face 'minibuffer-prompt) + 'cursor-intangible t + 'face 'minibuffer-prompt) mode-require-final-newline 'visit-save mouse-drag-copy-region t mouse-yank-at-point t @@ -84,8 +88,8 @@ Do this only if the buffer is not visiting a file." read-answer-short t read-buffer-completion-ignore-case t read-extended-command-predicate (when (fboundp - 'command-completion-default-include-p) - 'command-completion-default-include-p) + 'command-completion-default-include-p) + 'command-completion-default-include-p) recenter-positions '(top middle bottom) regexp-search-ring-max 100 regexp-search-ring-max 200 @@ -101,7 +105,9 @@ Do this only if the buffer is not visiting a file." show-paren-style 'mixed show-paren-when-point-in-periphery t show-paren-when-point-inside-paren t + ;;show-trailing-whitespace t tab-bar-show 1 + tab-width 4 tramp-backup-directory-alist backup-directory-alist use-dialog-box nil use-file-dialog nil @@ -117,6 +123,13 @@ Do this only if the buffer is not visiting a file." yank-pop-change-selection t ) +;; Programming language offsets. +;; Set these after the initial block so I can use `tab-width' +(setq-default + c-basic-offset tab-width) + +;; Emacs 28 ships with an option, `use-short-answers', that makes this form +;; obsolete, but I still use 27 at work. (when (version< emacs-version "28") (fset 'yes-or-no-p 'y-or-n-p)) @@ -150,23 +163,23 @@ Do this only if the buffer is not visiting a file." ;;; Modes (dolist (enable-mode '(global-auto-revert-mode - blink-cursor-mode - electric-pair-mode - show-paren-mode - global-so-long-mode - minibuffer-depth-indicate-mode - file-name-shadow-mode - minibuffer-electric-default-mode - delete-selection-mode - column-number-mode)) + blink-cursor-mode + electric-pair-mode + show-paren-mode + global-so-long-mode + minibuffer-depth-indicate-mode + file-name-shadow-mode + minibuffer-electric-default-mode + delete-selection-mode + column-number-mode)) (when (fboundp enable-mode) (funcall enable-mode +1))) (dolist (disable-mode '(tooltip-mode tool-bar-mode - menu-bar-mode - scroll-bar-mode - horizontal-scroll-bar-mode)) + menu-bar-mode + scroll-bar-mode + horizontal-scroll-bar-mode)) (when (fboundp disable-mode) (funcall disable-mode -1))) @@ -187,19 +200,19 @@ PRESERVE-NL-BACK and MODE." (cycle-spacing (- n) preserve-nl-back mode)) (defun +save-buffers-quit (&optional arg) - "Silently save each buffer, then kill the current connection. + "Silently save each buffer, then kill the current connection. If the current frame has no client, kill Emacs itself using `save-buffers-kill-emacs' after confirming with the user. With prefix ARG, silently save all file-visiting buffers, then kill without asking." - (interactive "P") - (save-some-buffers t) - (if (and (not (frame-parameter nil 'client)) - (and (not arg))) - (when (yes-or-no-p "Sure you want to quit? ") - (save-buffers-kill-emacs)) - (server-save-buffers-kill-terminal nil))) + (interactive "P") + (save-some-buffers t) + (if (and (not (frame-parameter nil 'client)) + (and (not arg))) + (when (yes-or-no-p "Sure you want to quit? ") + (save-buffers-kill-emacs)) + (server-save-buffers-kill-terminal nil))) ;;; Bindings @@ -225,9 +238,9 @@ kill without asking." (when (require 'uniquify nil :noerror) (setq-default uniquify-buffer-name-style 'forward - uniquify-separator path-separator - uniquify-after-kill-buffer-p t - uniquify-ignore-buffers-re "^\\*")) + uniquify-separator path-separator + uniquify-after-kill-buffer-p t + uniquify-ignore-buffers-re "^\\*")) (when (require 'goto-addr) (if (fboundp 'global-goto-address-mode) @@ -236,34 +249,34 @@ kill without asking." (when (require 'recentf nil :noerror) (setq-default recentf-save-file (.etc "recentf.el") - recentf-max-menu-items 100 - recentf-max-saved-items nil - recentf-auto-cleanup 'mode) + recentf-max-menu-items 100 + recentf-max-saved-items nil + recentf-auto-cleanup 'mode) (add-to-list 'recentf-exclude .etc) (recentf-mode +1)) (when (require 'repeat nil :noerror) (setq-default repeat-exit-key "g" - repeat-exit-timeout 5) + repeat-exit-timeout 5) (repeat-mode +1)) (when (require 'savehist nil :noerror) (setq-default history-length t - history-delete-duplicates t - history-autosave-interval 60 - savehist-file (.etc "savehist.el")) + history-delete-duplicates t + history-autosave-interval 60 + savehist-file (.etc "savehist.el")) (dolist (var '(extended-command-history - global-mark-ring - kill-ring - regexp-search-ring - search-ring - mark-ring)) + global-mark-ring + kill-ring + regexp-search-ring + search-ring + mark-ring)) (add-to-list 'savehist-additional-variables var)) (savehist-mode +1)) (when (require 'saveplace nil :noerror) (setq-default save-place-file (.etc "places.el") - save-place-forget-unreadable-files (eq system-type 'gnu/linux)) + save-place-forget-unreadable-files (eq system-type 'gnu/linux)) (save-place-mode +1)) ;; (when (require 'tramp) diff --git a/lisp/+init.el b/lisp/+init.el index 3ab0486..360a1b9 100644 --- a/lisp/+init.el +++ b/lisp/+init.el @@ -67,6 +67,12 @@ are sorted lexigraphically." ;; otherwise, sort lexigraphically (t (string< s1 s2)))))))))))) +(defun +init-sort-then-save () + "Sort init.el, then save it." + (interactive) + (+init-sort) + (save-buffer)) + ;;; Add `setup' forms to `imenu-generic-expression' (defun +init-add-setup-to-imenu () diff --git a/lisp/+lisp.el b/lisp/+lisp.el index 3267fd9..07dfcbd 100644 --- a/lisp/+lisp.el +++ b/lisp/+lisp.el @@ -67,5 +67,94 @@ with `string<' starting with the key determined by KEY-FN." (insert-before-markers real) (delete-region (point) (marker-position end)))))))) +;;; Comment-or-uncomment-sexp +;; from https://endlessparentheses.com/a-comment-or-uncomment-sexp-command.html + +(defun +lisp-uncomment-sexp (&optional n) + "Uncomment N sexps around point." + (interactive "P") + (let* ((initial-point (point-marker)) + (inhibit-field-text-motion t) + (p) + (end (save-excursion + (when (elt (syntax-ppss) 4) + (re-search-backward comment-start-skip + (line-beginning-position) + t)) + (setq p (point-marker)) + (comment-forward (point-max)) + (point-marker))) + (beg (save-excursion + (forward-line 0) + (while (and (not (bobp)) + (= end (save-excursion + (comment-forward (point-max)) + (point)))) + (forward-line -1)) + (goto-char (line-end-position)) + (re-search-backward comment-start-skip + (line-beginning-position) + t) + (ignore-errors + (while (looking-at-p comment-start-skip) + (forward-char -1))) + (point-marker)))) + (unless (= beg end) + (uncomment-region beg end) + (goto-char p) + ;; Indentify the "top-level" sexp inside the comment. + (while (and (ignore-errors (backward-up-list) t) + (>= (point) beg)) + (skip-chars-backward (rx (syntax expression-prefix))) + (setq p (point-marker))) + ;; Re-comment everything before it. + (ignore-errors + (comment-region beg p)) + ;; And everything after it. + (goto-char p) + (forward-sexp (or n 1)) + (skip-chars-forward "\r\n[:blank:]") + (if (< (point) end) + (ignore-errors + (comment-region (point) end)) + ;; If this is a closing delimiter, pull it up. + (goto-char end) + (skip-chars-forward "\r\n[:blank:]") + (when (eq 5 (car (syntax-after (point)))) + (delete-indentation)))) + ;; Without a prefix, it's more useful to leave point where + ;; it was. + (unless n + (goto-char initial-point)))) + +(defun +lisp-comment-sexp--raw () + "Comment the sexp at point or ahead of point." + (pcase (or (bounds-of-thing-at-point 'sexp) + (save-excursion + (skip-chars-forward "\r\n[:blank:]") + (bounds-of-thing-at-point 'sexp))) + (`(,l . ,r) + (goto-char r) + (skip-chars-forward "\r\n[:blank:]") + (save-excursion + (comment-region l r)) + (skip-chars-forward "\r\n[:blank:]")))) + +(defun +lisp-comment-or-uncomment-sexp (&optional n) + "Comment the sexp at point and move past it. +If already inside (or before) a comment, uncomment instead. +With a prefix argument N, (un)comment that many sexps." + (interactive "P") + (if (or (elt (syntax-ppss) 4) + (< (save-excursion + (skip-chars-forward "\r\n[:blank:]") + (point)) + (save-excursion + (comment-forward 1) + (point)))) + (+lisp-uncomment-sexp n) + (dotimes (_ (or n 1)) + (+lisp-comment-sexp--raw)))) + (provide '+lisp) ;;; +lisp.el ends here diff --git a/lisp/+modeline.el b/lisp/+modeline.el index 5354e5b..5f46a75 100644 --- a/lisp/+modeline.el +++ b/lisp/+modeline.el @@ -17,22 +17,62 @@ :prefix "+modeline-" :group 'simple-modeline) -(defun +modeline-buffer-name () ; gonsie +(defcustom +modeline-default-spacer " " + "Default spacer to use for modeline elements. +All modeline elements take an optional argument, `spacer', which +will default to this string.") + +;;; Combinators + +(defun +modeline-concat (segments &optional separator) + "Concatenate multiple `simple-modeline'-style SEGMENTS. +SEGMENTS is a list of either modeline segment-functions (see +`simple-modeline' functions for an example of types of +functions), though it can also contain cons cells of the +form (SEGMENT . PREDICATE). + +Segments are separated from each other using SEPARATOR, which +defaults to a \" \". space. Only segments that evaluate to a +non-trivial string (that is, a string not equal to \"\") will be +separated, for a cleaner look. + +This function makes a lambda, so you can throw it straight into +`simple-modeline-segments'." + (setq separator (or separator +modeline-default-spacer)) + (lambda () + (apply #'concat + (let (this-sep result-list) + (dolist (segment segments) + (push (funcall (or (car-safe segment) segment) + this-sep) + result-list) + (if (or (cdr-safe segment) + (and (car result-list) + (not (equal (car result-list) "")))) + (setq this-sep separator) + (setq this-sep nil))) + (unless (seq-some #'null result-list) + (push +modeline-default-spacer result-list)) + (nreverse result-list))))) + +;;; Modeline segments + +(defun +modeline-buffer-name (&optional spacer) ; gonsie "Display the buffer name." - (concat " " (propertize - (+string-align (buffer-name) 20 :before "" :ellipsis "~ ") - 'face 'bold - 'help-echo (or (buffer-file-name) - (buffer-name)) - 'mouse-face 'mode-line-highlight))) + (concat (or spacer +modeline-default-spacer) + (propertize + (+string-align (buffer-name) 20 :ellipsis nil) + 'help-echo (or (buffer-file-name) + (buffer-name)) + 'mouse-face 'mode-line-highlight))) (defcustom +modeline-minions-icon "&" "The \"icon\" for `+modeline-minions' button." :type 'string) -(defun +modeline-minions () +(defun +modeline-minions (&optional spacer) "Display a button for `minions-minor-modes-menu'." - (concat " " + (concat (or spacer +modeline-default-spacer) (propertize +modeline-minions-icon 'help-echo "Minor modes menu\nmouse-1: show menu." @@ -45,9 +85,9 @@ (minions-minor-modes-menu))))) 'mouse-face 'mode-line-highlight))) -(defun +modeline-major-mode () +(defun +modeline-major-mode (&optional spacer) "Display the current `major-mode'." - (concat " " + (concat (or spacer +modeline-default-spacer) (propertize (+string-truncate (format-mode-line mode-name) 12 "~") 'face 'bold @@ -80,7 +120,7 @@ The order of elements matters: whichever one matches first is applied." `+modeline-modified'." :type '(repeat function)) -(defun +modeline-modified () ; modified from `simple-modeline-status-modified' +(defun +modeline-modified (&optional spacer) ; modified from `simple-modeline-status-modified' "Display a color-coded \"icon\" indicator for the buffer's status." (let* ((icon (catch :icon (dolist (cell +modeline-modified-icon-alist) @@ -94,14 +134,20 @@ The order of elements matters: whichever one matches first is applied." ('t t) (_ nil)) (throw :icon (cdr cell))))))) - (concat " " + (concat (or spacer +modeline-default-spacer) (propertize (or icon "") 'mouse-face 'mode-line-highlight)))) -(defun +modeline-narrowed () +(defun +modeline-buffer-modes (&optional spacer) + "Display various buffer-specific stuff cleanly." + ;; This is clunky and should probably be improved. + (concat (+modeline-reading-mode) + (+modeline-narrowed (when reading-mode ",")))) + +(defun +modeline-narrowed (&optional spacer) "Display an indication that the buffer is narrowed." (when (buffer-narrowed-p) - (concat " " + (concat (or spacer +modeline-default-spacer) (propertize "N" 'help-echo (format "%s\n%s" "Buffer is narrowed." @@ -111,10 +157,10 @@ The order of elements matters: whichever one matches first is applied." 'face 'font-lock-doc-face 'mouse-face 'mode-line-highlight)))) -(defun +modeline-reading-mode () +(defun +modeline-reading-mode (&optional spacer) "Display an indication that the buffer is in `reading-mode'." (when reading-mode - (concat " " + (concat (or spacer +modeline-default-spacer) (propertize (concat "R" (when (bound-and-true-p +eww-readable-p) "w")) 'help-echo (format "%s\n%s" @@ -136,7 +182,7 @@ The order of elements matters: whichever one matches first is applied." "Toggle the percentage display in the mode line (File Percentage Mode)." :init-value t :global t :group 'mode-line) -(defun +modeline-position () ; adapted from `simple-modeline' +(defun +modeline-position (&optional _) ; adapted from `simple-modeline' "Display the current cursor position." (list '((line-number-mode ((column-number-mode @@ -160,34 +206,38 @@ The order of elements matters: whichever one matches first is applied." (region-bounds)))) 'font-lock-face 'font-lock-variable-name-face)))) -(defun +modeline-vc () +(defun +modeline-vc (&optional spacer) "Display the version control branch of the current buffer in the modeline." ;; from https://www.gonsie.com/blorg/modeline.html, from Doom (if-let ((backend (vc-backend buffer-file-name))) - (concat " " (substring vc-mode (+ (if (eq backend 'Hg) 2 3) 2))))) + (concat (or spacer +modeline-default-spacer) + (substring vc-mode (+ (if (eq backend 'Hg) 2 3) 2))))) -(defun +modeline-track () +(defun +modeline-track (&optional spacer) "Display `tracking-mode' information." - '(tracking-mode + (when tracking-mode tracking-mode-line-buffers)) -(defun +modeline-anzu () +(defun +modeline-anzu (&optional spacer) "Display `anzu--update-mode-line'." - (concat " " (anzu--update-mode-line))) + (concat (or spacer +modeline-default-spacer) + (anzu--update-mode-line))) -(defun +modeline-text-scale () +(defun +modeline-text-scale (&optional spacer) "Display text scaling level." ;; adapted from https://github.com/seagle0128/doom-modeline (when (and (boundp 'text-scale-mode-amount) (/= text-scale-mode-amount 0)) - (format (if (> text-scale-mode-amount 0) " (%+d)" " (%-d)") + (format (if (> text-scale-mode-amount 0) "%s(%+d)" "%s(%-d)") + (or spacer +modeline-default-spacer) text-scale-mode-amount))) -(defun +modeline-ace-window-display () +(defun +modeline-ace-window-display (&optional spacer) "Display `ace-window-display-mode' information in the modeline." - '(+ace-window-display-mode - (ace-window-mode - (" " (:eval (window-parameter (selected-window) 'ace-window-path)))))) + (when (and +ace-window-display-mode + ace-window-mode) + (concat (or spacer +modeline-default-spacer) + (window-parameter (selected-window) 'ace-window-path)))) (provide '+modeline) ;;; +modeline.el ends here diff --git a/lisp/+setup.el b/lisp/+setup.el index dce5d7b..ac99c1f 100644 --- a/lisp/+setup.el +++ b/lisp/+setup.el @@ -72,7 +72,7 @@ (setup-define :straight (lambda (recipe) - `(unless (straight-use-package ',recipe) + `(unless (ignore-errors (straight-use-package ',recipe)) ,(setup-quit))) :documentation "Install RECIPE with `straight-use-package'. diff --git a/lisp/+util.el b/lisp/+util.el index fb77278..45d1e6d 100644 --- a/lisp/+util.el +++ b/lisp/+util.el @@ -58,7 +58,8 @@ either side of S. FILL is the string to fill extra space with (default \" \"). -ELLIPSIS is the string to show when S is too long to fit (default \"...\"). +ELLIPSIS is the string to show when S is too long to fit (default +\"...\"). If nil, don't truncate the string. ALIGNMENT can be one of these: - nil: align to `+string-default-alignment' @@ -73,7 +74,7 @@ ALIGNMENT can be one of these: (format "%s%s%s%s%s" before (if (eq alignment 'left) "" filler) - (+string-truncate s max-length ellipsis alignment) + (if ellipsis (+string-truncate s max-length ellipsis alignment) s) (if (eq alignment 'right) "" filler) after))) -- cgit 1.4.1-21-gabe81