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 --- lisp/+emacs.el | 95 ++++++++++++++++++++++++++-------------------- lisp/+init.el | 6 +++ lisp/+lisp.el | 89 +++++++++++++++++++++++++++++++++++++++++++ lisp/+modeline.el | 110 +++++++++++++++++++++++++++++++++++++++--------------- lisp/+setup.el | 2 +- lisp/+util.el | 5 ++- 6 files changed, 233 insertions(+), 74 deletions(-) (limited to 'lisp') 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