diff --git a/early-init.el b/early-init.el index 113f261..e50d99e 100644 --- a/early-init.el +++ b/early-init.el @@ -140,10 +140,9 @@ See `no-littering' for examples.") (add-to-list 'setup-modifier-list 'setup-wrap-to-demote-errors) (unless (memq debug-on-error '(nil init)) - (define-advice setup (:before (head &rest args) +setup-before) - (message "[Setup] %S" head)) - (define-advice setup (:after (head &rest args) +setup-after) - (message "[Setup] %S...done" head))) + (define-advice setup (:around (fn head &rest args) +setup-report) + (+with-progress ((format "[Setup] %S..." head)) + (apply fn head args)))) ;;; Appendix diff --git a/init.el b/init.el index 42cac67..5e52215 100644 --- a/init.el +++ b/init.el @@ -465,7 +465,7 @@ (setup notmuch (:load-from "~/usr/share/emacs/site-lisp/") - ;;(:load-after org-contacts) + (:load-after org-contacts) (:also-load +notmuch +message) (+define-dir notmuch/ (sync/ "emacs/notmuch") "Notmuch configuration and data.") @@ -568,11 +568,11 @@ org-startup-truncated nil org-startup-with-inline-images t org-tags-column (- (- fill-column (length org-ellipsis))) - org-todo-keywords '((sequence "TODO(t)" "WAIT(w@/!)" + org-todo-keywords '((sequence "TODO(t)" "WAIT(w@/!)" "ONGOING(o@)" "|" "DONE(d!)") - (sequence "ONGOING(o@)") (sequence "|" "CANCELED(k@)") - (sequence "MEETING(m)")) + (sequence "MEETING(m)") + (sequence "ASSIGNED(a@/!)" "REVIEW(r)" "|" "DONE(d!)")) org-emphasis-alist '(("*" org-bold) ("/" org-italic) ("_" org-underline) @@ -698,8 +698,8 @@ :unnarrowed t)) (+org-capture-sort)) -(setup org-contacts - (:load-after org) +(setup org-contacts (:quit) + (:require) (:also-straight org-vcard) ; for importing Vcard files (:option org-contacts-matcher "contact") ; Contacts are tagged "contact" ) @@ -854,6 +854,12 @@ They are completed by \"M-x TAB\" only in Tramp debug buffers." (:when-loaded (setf (alist-get ?. avy-dispatch-alist) #'avy-action-embark))) +(setup (:straight bbdb) + (:require bbdb-autoloads + bbdb) + (:also-straight bbdb-vcard) + (bbdb-initialize 'gnus 'message)) + (setup (:straight (bongo :type git :flavor melpa :files ("*.el" "*.texi" "images" "*.rb" "bongo-pkg.el" "*.info") @@ -1344,7 +1350,9 @@ See also `crux-reopen-as-root-mode'." (:+leader "f" #'elfeed "C-f" #'elfeed) (advice-add #'elfeed-search-fetch :after #'beginning-of-buffer) (:with-mode elfeed-search-mode - (:bind "&" #'+elfeed-search-browse-generic) + (:bind "&" #'+elfeed-search-browse-generic + "w" #'elfeed-search-yank + "y" nil) (:hook #'hl-line-mode) ;; https://old.reddit.com/r/emacs/comments/rlli0u/whats_your_favorite_defadvice/hphfh4e/ (advice-add #'elfeed-search-update--force :after #'elfeed-db-save) @@ -1353,7 +1361,9 @@ See also `crux-reopen-as-root-mode'." (:bind "SPC" #'+elfeed-scroll-up-command "S-SPC" #'+elfeed-scroll-down-command "&" #'+elfeed-show-browse-generic - "RET" #'shr-browse-url) + "RET" #'shr-browse-url + "w" #'elfeed-show-yank + "y" nil) (:hook #'reading-mode) (:option +elfeed--update-repeat (* 60 30) ; 1/2 hour +elfeed--update-first-time 60)) @@ -1744,9 +1754,10 @@ See also `crux-reopen-as-root-mode'." (:option +mwim-passthrough-modes '(comint-mode eshell-mode vterm-mode - crossword-mode)) - (:global "C-a" #'+mwim-beginning-maybe - "C-e" #'+mwim-end-maybe)) + crossword-mode + geiser-repl-mode)) + (:global "C-a" #'mwim-beginning + "C-e" #'mwim-end)) (setup (:straight notmuch-bookmarks) (:load-after notmuch) @@ -1780,12 +1791,16 @@ See also `crux-reopen-as-root-mode'." (:hook-into org-mode)) (setup (:straight org-download) + (:require) (:option org-download-method 'attach org-download-backend (cond ((executable-find "curl") 'curl) ((executable-find "wget") 'wget) (:else 'url-retrieve))) (add-hook 'dired-mode-hook 'org-download-enable)) +(setup (:straight org-mime) + (:option org-mime-export-ascii 'utf-8)) + (setup (:straight org-mime) (add-hook 'message-mode-hook (defun org-mime-setup@message-mode () @@ -1801,9 +1816,9 @@ See also `crux-reopen-as-root-mode'." (setup (:straight (org-taskwise :host github :repo "duckwork/org-taskwise.el")) - (:load-after org) - (:bind-into org-mode - "C-x n t" #'org-taskwise-narrow-to-task)) + (with-eval-after-load 'org + (require 'org-taskwise) + (define-key org-mode-map (kbd "C-x n t") #'org-taskwise-narrow-to-task))) (setup (:straight org-visibility) (:require org-visibility) @@ -1834,7 +1849,8 @@ See also `crux-reopen-as-root-mode'." lisp-interaction-mode-hook lisp-mode-hook scheme-mode-hook - geiser-mode-hook)) + geiser-mode-hook + geiser-repl-mode-hook)) (add-hook hook #'enable-paredit-mode)) (:also-load eldoc) (eldoc-add-command #'paredit-backward-delete #'paredit-close-round)) @@ -1916,6 +1932,7 @@ See also `crux-reopen-as-root-mode'." +modeline-text-scale ,(+modeline-concat '(+modeline-god-mode + +modeline-kmacro-indicator +modeline-reading-mode +modeline-narrowed) ",") diff --git a/lisp/+elfeed.el b/lisp/+elfeed.el index ac316c4..8f7f17a 100644 --- a/lisp/+elfeed.el +++ b/lisp/+elfeed.el @@ -60,49 +60,51 @@ (make-directory (file-name-directory script) :parents) (with-temp-buffer (insert - (prin1-to-string ;; Print the following s-expression to a string - `(progn - ;; Set up the environment - (setq lexical-binding t) - (load (locate-user-emacs-file "early-init")) - (dolist (pkg '(elfeed elfeed-org)) - (straight-use-package pkg) - (require pkg)) - ;; Copy variables from current environment - (progn - ,@(cl-loop for copy-var in '(rmh-elfeed-org-files - elfeed-db-directory - elfeed-curl-program-name - elfeed-use-curl - elfeed-curl-extra-arguments - elfeed-enclosure-default-dir) - collect `(progn (message "%S = %S" ',copy-var ',(symbol-value copy-var)) - (setq ,copy-var ',(symbol-value copy-var))))) - ;; Define new variables for this environment - (progn - ,@(cl-loop for (new-var . new-val) in '((elfeed-curl-max-connections . 4)) - collect `(progn (message "%S = %S" ',new-var ',new-val) - (setq ,new-var ',new-val)))) - ;; Redefine `elfeed-log' to log everything - (defun elfeed-log (level fmt &rest objects) - (princ (format "[%s] [%s]: %s\n" - (format-time-string "%F %T") - level - (apply #'format fmt objects)))) - ;; Run elfeed - (elfeed-org) - (elfeed) - (elfeed-db-load) - (elfeed-update) - ;; Wait for `elfeed-update' to finish - (while (> (elfeed-queue-count-total) 0) - (sleep-for 5) - (message "%s" (elfeed-queue-count-total)) - (accept-process-output)) - ;; Garbage collect and save the database - (elfeed-db-gc) - (elfeed-db-save) - (princ (format ,update-message-format "done."))))) + (let ((print-level nil) + (print-length nil)) + (prin1-to-string ;; Print the following s-expression to a string + `(progn + ;; Set up the environment + (setq lexical-binding t) + (load (locate-user-emacs-file "early-init")) + (dolist (pkg '(elfeed elfeed-org)) + (straight-use-package pkg) + (require pkg)) + ;; Copy variables from current environment + (progn + ,@(cl-loop for copy-var in '(rmh-elfeed-org-files + elfeed-db-directory + elfeed-curl-program-name + elfeed-use-curl + elfeed-curl-extra-arguments + elfeed-enclosure-default-dir) + collect `(progn (message "%S = %S" ',copy-var ',(symbol-value copy-var)) + (setq ,copy-var ',(symbol-value copy-var))))) + ;; Define new variables for this environment + (progn + ,@(cl-loop for (new-var . new-val) in '((elfeed-curl-max-connections . 4)) + collect `(progn (message "%S = %S" ',new-var ',new-val) + (setq ,new-var ',new-val)))) + ;; Redefine `elfeed-log' to log everything + (defun elfeed-log (level fmt &rest objects) + (princ (format "[%s] [%s]: %s\n" + (format-time-string "%F %T") + level + (apply #'format fmt objects)))) + ;; Run elfeed + (elfeed-org) + (elfeed) + (elfeed-db-load) + (elfeed-update) + ;; Wait for `elfeed-update' to finish + (while (> (elfeed-queue-count-total) 0) + (sleep-for 5) + (message "%s" (elfeed-queue-count-total)) + (accept-process-output)) + ;; Garbage collect and save the database + (elfeed-db-gc) + (elfeed-db-save) + (princ (format ,update-message-format "done.")))))) (write-file script)) (chmod script #o777) (message update-message-format "start") diff --git a/lisp/+emacs.el b/lisp/+emacs.el index f26dc98..b7e31e2 100644 --- a/lisp/+emacs.el +++ b/lisp/+emacs.el @@ -60,15 +60,18 @@ Do this only if the buffer is not visiting a file." enable-recursive-minibuffers t executable-prefix-env t fast-but-imprecise-scrolling t - find-file-visit-truename t file-name-shadow-properties '(invisible t intangible t) fill-column 80 + find-file-visit-truename t frame-resize-pixelwise t global-auto-revert-non-file-buffers t global-mark-ring-max 100 hscroll-margin 1 hscroll-step 1 imenu-auto-rescan t + image-use-external-converter (or (executable-find "convert") + (executable-find "gm") + (executable-find "ffmpeg")) indent-tabs-mode nil indicate-buffer-boundaries 'left indicate-empty-lines nil @@ -104,7 +107,7 @@ Do this only if the buffer is not visiting a file." save-interprogram-paste-before-kill t scroll-conservatively 101 scroll-down-aggressively 0.01 - scroll-margin 1 + scroll-margin 2 scroll-preserve-screen-position 1 scroll-step 1 scroll-up-aggressively 0.01 @@ -148,6 +151,9 @@ Do this only if the buffer is not visiting a file." ;;; Encodings +;; Allegedly, this is the only one you need... +(set-language-environment "UTF-8") +;; But I still set all of these, for fun. (setq-default locale-coding-system 'utf-8-unix coding-system-for-read 'utf-8-unix coding-system-for-write 'utf-8-unix @@ -159,7 +165,6 @@ Do this only if the buffer is not visiting a file." STRING)) (set-charset-priority 'unicode) -(set-language-environment "UTF-8") (prefer-coding-system 'utf-8-unix) (set-default-coding-systems 'utf-8-unix) (set-terminal-coding-system 'utf-8-unix) diff --git a/lisp/+ispell.el b/lisp/+ispell.el index c3ee417..697233f 100644 --- a/lisp/+ispell.el +++ b/lisp/+ispell.el @@ -58,30 +58,34 @@ prefix ARG is non-nil; then it just saves them." (unless (buffer-file-name) (user-error "Buffer not attached to file")) (hack-dir-local-variables) - (when-let ((new-words (+ispell-append-removing-duplicates - :test #'string= - ispell-buffer-session-localwords - (alist-get 'ispell-buffer-session-localwords - dir-local-variables-alist) - (alist-get 'ispell-buffer-session-localwords - file-local-variables-alist) - (+ispell-buffer-local-words-list)))) - (save-excursion - (add-dir-local-variable - major-mode - 'ispell-buffer-session-localwords - (setq ispell-buffer-session-localwords - new-words)) - (when (or arg - (y-or-n-p "Save .dir-locals.el?")) - (save-buffer)) - (bury-buffer)) - (or ispell-buffer-local-name - (setq ispell-buffer-local-name (buffer-name))) - (save-excursion - (goto-char (point-min)) - (while (search-forward ispell-words-keyword nil t) - (delete-region (point-at-bol) (1+ (point-at-eol))))))) + (let ((print-level nil) + (print-length nil)) + (when-let ((new-words (cl-remove-if (lambda (el) (eq el '\.\.\.)) ; XXX: NO IDEA + ; where this came from + (+ispell-append-removing-duplicates + :test #'string= + ispell-buffer-session-localwords + (alist-get 'ispell-buffer-session-localwords + dir-local-variables-alist) + (alist-get 'ispell-buffer-session-localwords + file-local-variables-alist) + (+ispell-buffer-local-words-list))))) + (save-excursion + (add-dir-local-variable + major-mode + 'ispell-buffer-session-localwords + (setq ispell-buffer-session-localwords + new-words)) + (when (or arg + (y-or-n-p "Save .dir-locals.el?")) + (save-buffer)) + (bury-buffer)) + (or ispell-buffer-local-name + (setq ispell-buffer-local-name (buffer-name))) + (save-excursion + (goto-char (point-min)) + (while (search-forward ispell-words-keyword nil t) + (delete-region (point-at-bol) (1+ (point-at-eol)))))))) ;;;###autoload (defun +ispell-move-buffer-words-to-dir-locals-hook () diff --git a/lisp/+kmacro.el b/lisp/+kmacro.el index 2b2916f..a3cde61 100644 --- a/lisp/+kmacro.el +++ b/lisp/+kmacro.el @@ -21,6 +21,7 @@ (defun +kmacro-change-mode-line (&rest _) "Remap the mode-line face when recording a kmacro." + (add-to-list 'face-remapping-alist '(mode-line . +kmacro-modeline))) (defun +kmacro-restore-mode-line (&rest _) diff --git a/lisp/+modeline.el b/lisp/+modeline.el index c8dab4e..7bef5c6 100644 --- a/lisp/+modeline.el +++ b/lisp/+modeline.el @@ -296,7 +296,7 @@ See `line-number-mode', `column-number-mode', `file-percentage-mode'" (interactive "e") (with-selected-window (posn-window - (event-start ev)) + (event-start e)) (god-local-mode -1) (force-mode-line-update))))) 'mouse-face 'mode-line-highlight)))) @@ -326,5 +326,26 @@ See `line-number-mode', `column-number-mode', `file-percentage-mode'" map)) 'mouse-face 'mode-line-highlight)))) +(defface +modeline-kmacro-indicator '((t :foreground "Firebrick")) + "Face for the kmacro indicator in the modeline.") + +(defun +modeline-kmacro-indicator (&optional spacer) + "Display an indicator when recording a kmacro." + (when defining-kbd-macro + (concat (or spacer +modeline-default-spacer) + (propertize "●" + 'face '+modeline-kmacro-indicator + 'help-echo (format (concat "Defining a macro\n" + "Current step: %d\n" + "mouse-1: Stop recording") + kmacro-counter) + 'local-map (purecopy (simple-modeline-make-mouse-map + 'mouse-1 (lambda (e) + (interactive "e") + (with-selected-window + (posn-window (event-start e)) + (kmacro-end-macro nil))))) + 'mouse-face 'mode-line-highlight)))) + (provide '+modeline) ;;; +modeline.el ends here diff --git a/lisp/+org.el b/lisp/+org.el index 2ff3e11..3d14c52 100644 --- a/lisp/+org.el +++ b/lisp/+org.el @@ -550,6 +550,7 @@ language name.") "Export region to HTML, and copy it to the clipboard. Arguments ASYNC, SUBTREEP, VISIBLE-ONLY, BODY-ONLY, EXT-PLIST, and POST-PROCESS are passed to `org-export-to-file'." + (interactive) ; XXX: hould this be interactive? (message "Exporting Org to HTML...") (let ((org-tmp-file "/tmp/org.html")) (org-export-to-file 'html org-tmp-file @@ -567,8 +568,5 @@ and POST-PROCESS are passed to `org-export-to-file'." (interactive) (+org-export-clip-to-html nil :subtree)) -;;; Taskwise functions -;; TODO: break out into another library - (provide '+org) ;;; +org.el ends here diff --git a/lisp/+tab-bar.el b/lisp/+tab-bar.el index c4b7420..e328146 100644 --- a/lisp/+tab-bar.el +++ b/lisp/+tab-bar.el @@ -27,7 +27,8 @@ "Display `tracking-mode-line-buffers' in the tab-bar." ;; TODO: write something to convert a mode-line construct to a tab-bar ;; construct. - (when tracking-mode + (when (and tracking-mode + (not (bound-and-true-p org-clock-current-task))) (cons (when (> (length tracking-mode-line-buffers) 0) '(track-mode-line-separator menu-item " " ignore)) (cl-loop for i from 0 below (length tracking-mode-line-buffers) @@ -63,7 +64,8 @@ (defun +tab-bar-org-clock () "Display `org-mode-line-string' in the tab-bar." - (when (org-clocking-p) + (when (and (fboundp 'org-clocking-p) + (org-clocking-p)) ;; org-mode-line-string `((org-clocking menu-item ,org-mode-line-string diff --git a/lisp/acdw.el b/lisp/acdw.el index 7012b16..de2b8e7 100644 --- a/lisp/acdw.el +++ b/lisp/acdw.el @@ -281,24 +281,30 @@ always nil; this function is mostly intended for use in init." (defun chat-disconnect () "Disconnect from all chats." (interactive) - (ignore-errors - (circe-command-GQUIT "☮ 🫀 🍞")) - (ignore-errors - (jabber-disconnect)) - (dolist (team +slack-teams) + (+with-progress "Quitting circe..." (ignore-errors - (slack-team-disconnect team))) - (ignore-errors (slack-ws-close)) - (+mapc-some-buffers (lambda () "Remove the buffer from tracking and kill it unconditionally." - (let ((kill-buffer-query-functions nil)) - (tracking-remove-buffer (current-buffer)) - (kill-buffer))) - (lambda () "Return t if derived from the following modes." - (derived-mode-p 'lui-mode - 'jabber-chat-mode - 'jabber-roster-mode - 'jabber-browse-mode - 'slack-mode)))) + (circe-command-GQUIT "☮ 🫀 🍞") + (cancel-timer (irc-connection-get conn :flood-timer)))) + (+with-progress "Quitting jabber..." + (ignore-errors + (jabber-disconnect))) + (+with-progress "Quitting-slack..." + (dolist (team +slack-teams) + (ignore-errors + (slack-team-disconnect team))) + (ignore-errors (slack-ws-close))) + (+with-progress "Killing buffers..." + (ignore-errors + (+mapc-some-buffers (lambda () "Remove the buffer from tracking and kill it unconditionally." + (let ((kill-buffer-query-functions nil)) + (tracking-remove-buffer (current-buffer)) + (kill-buffer))) + (lambda () "Return t if derived from the following modes." + (derived-mode-p 'lui-mode + 'jabber-chat-mode + 'jabber-roster-mode + 'jabber-browse-mode + 'slack-mode)))))) ;; I can never remember all the damn chat things I run, so this just does all of em. (defun chat (&optional arg) @@ -306,7 +312,9 @@ always nil; this function is mostly intended for use in init." With optional ARG, kill all chat-related buffers first." (interactive "P") (when arg (chat-disconnect)) - (mapc #'call-interactively chat-functions)) + (dolist-with-progress-reporter (fn chat-functions) + "Connecting to chat..." + (call-interactively fn))) (defun +forward-paragraph (arg) "Move forward ARG (simple) paragraphs. @@ -353,5 +361,18 @@ SEPARATOR defaults to the newline (\\n)." (with-current-buffer (find-file-noselect file) (buffer-string))) +(defmacro +with-progress (pr-args &rest body) + "Perform BODY wrapped in a progress reporter. +PR-ARGS is the list of arguments to pass to +`make-progress-reporter'; it can be a single string for the +message, as well. If you want to use a formatted string, wrap +the `format' call in a list." + (declare (indent 1)) + (let ((reporter (gensym)) + (pr-args (if (listp pr-args) pr-args (list pr-args)))) + `(let ((,reporter (make-progress-reporter ,@pr-args))) + (prog1 (progn ,@body) + (progress-reporter-done ,reporter))))) + (provide 'acdw) ;;; acdw.el ends here diff --git a/machines/bob.el b/machines/bob.el index 8a2aefc..3455c44 100644 --- a/machines/bob.el +++ b/machines/bob.el @@ -10,8 +10,8 @@ ;; Other ideas: [[https://twitter.com/NPRougier/status/1488570192561160195][from Nic Rougier]] (add-function :after machine-after-load-theme (defun +bob-set-faces (&rest _) - (let ((base-face "Monego") - (italic-face "Victor Mono") + (let ((base-face "Roboto Mono") + (italic-face nil) ;; (bold-face nil) (mono-face nil) (var-face "Lato") @@ -22,16 +22,17 @@ :height ,base-size) ;; (bold :family ,(or bold-face base-face) ;; :weight bold) - (italic :family ,(or italic-face base-face) - :weight medium - :slant italic - :height ,base-size) + ;; (italic :family ,(or italic-face base-face) + ;; :weight medium + ;; :slant italic + ;; :height ,base-size) (fixed-pitch :family ,(or mono-face base-face) :weight regular :height ,base-size) (variable-pitch :family ,(or var-face base-face) :height 1.2) (org-italic :family ,(or var-face base-face) - :slant italic)))))) + :slant italic)))) + )) ;;; bob.el ends here