diff options
| author | Kévin Le Gouguec <kevin.legouguec@gmail.com> | 2025-01-25 18:50:15 +0100 |
|---|---|---|
| committer | Kévin Le Gouguec <kevin.legouguec@gmail.com> | 2025-01-25 18:50:15 +0100 |
| commit | bb40f54627d7f777810957a1c5306aedfbbdd38b (patch) | |
| tree | a03d8fda8c79534c067c63225f9d6ef5cd7424d5 /.gnus | |
| parent | a8924d1fa1e2ce5f921d3aa54bd3205a6ff3f5b7 (diff) | |
| download | dotfiles-bb40f54627d7f777810957a1c5306aedfbbdd38b.tar.xz | |
Achieve XDG compliance
… sort of. Emacs apps will stuff all manner of transient state under
user-emacs-directory by default, so full XDG compliance would probably
involve customizing them all to instead use ~/.cache but 🤷
Diffstat (limited to '.gnus')
| -rw-r--r-- | .gnus | 368 |
1 files changed, 0 insertions, 368 deletions
@@ -1,368 +0,0 @@ -;;; -*- lexical-binding: t -*- - -;;; Externalities. - -;; user-full-name from /etc/passwd; set with chfn(1). -;; user-mail-address from EMAIL variable; set with ~/.profile, -;; ~/.xsessionrc, DE's convention-du-jour. - -;; ~/.authinfo.gpg: -;; machine imap.gmail.com login LOGIN password PASSWORD port 993 -;; machine smtp.gmail.com login LOGIN password PASSWORD port 587 - -;;; Þe Olde Setq. -(setq gnus-select-method - '(nnimap "gmail" - (nnimap-address "imap.gmail.com") - (nnimap-server-port 993) - (nnmail-expiry-target "nnimap+gmail:[Gmail]/Trash") - (nnmail-expiry-wait immediate)) - gnus-secondary-select-methods - '((nntp "archive.lwn.net") - (nntp "news.gmane.io")) - - smtpmail-smtp-server "smtp.gmail.com" - smtpmail-smtp-service 587 - - ;; Archival of sent messages. - gnus-gcc-mark-as-read t - ;; The next setting makes the previous one useless; keeping both - ;; for now because I'm not sure which I'll settle for. - gnus-message-archive-group nil - - ;; Groups. - gnus-group-uncollapsed-levels 2 - - ;; Summary. - gnus-summary-line-format "%*%U%R %-16,16&user-date; %B%-23,23f %s\n" - gnus-summary-dummy-line-format " ╭ %S\n" - gnus-summary-make-false-root 'dummy - gnus-sum-thread-tree-root "╭ " - gnus-sum-thread-tree-false-root "┬ " - gnus-sum-thread-tree-single-indent " " - gnus-sum-thread-tree-indent " " - gnus-sum-thread-tree-single-leaf "╰► " - gnus-sum-thread-tree-leaf-with-other "├► " - gnus-sum-thread-tree-vertical "│" - gnus-thread-sort-functions - '(gnus-thread-sort-by-number - (not gnus-thread-sort-by-most-recent-date)) - gnus-user-date-format-alist '(((gnus-seconds-today) - . "%H:%M") - ((+ 86400 (gnus-seconds-today)) - . "Yesterday %H:%M") - ((* 6 86400) - . "%a %H:%M") - ((gnus-seconds-month) - . "%a %d") - ((gnus-seconds-year) - . "%b %d") - (t - . "%F")) - ;; Articles. - gnus-cite-parse-max-size nil - gnus-header-face-alist - '(("From" nil gnus-header-from) - ("Subject" nil gnus-header-subject) - ("Date" nil eighters-date) - ("Newsgroups:.*," nil gnus-header-newsgroups) - ("" gnus-header-name gnus-header-content)) - gnus-sorted-header-list - (list - ;; What, when. - "^Subject:" "^Summary:" "^Keywords:" "^Date:" - ;; Who. - "^From:" "^Organization:" "^Followup-To:" "^To:" "^Cc:" "^Newsgroups:") - gnus-treat-display-smileys nil - ;; Do not fill anything; let visual-line-mode wrap text. - ;;; NB: for format=flowed, there is no setting to say "un-fill - ;;; flowed lines", so we *enable* filling, setting an absurd - ;;; line length limit, in order to un-fill flowed lines. - fill-flowed-display-column most-positive-fixnum - mm-fill-flowed t - ;;; More long-line-folding settings. - gnus-article-unfold-long-headers t - gnus-treat-fill-article nil - gnus-treat-fill-long-lines nil - gnus-treat-fold-headers nil) - -;;; Window configurations. - -(defvar my/gnus-side-by-side-threshold 160) - -(gnus-add-configuration - '(article - (if (>= (frame-width) my/gnus-side-by-side-threshold) - '(horizontal 1.0 - (summary 1.0 point) - (article 80)) - '(vertical 1.0 - (summary 0.25 point) - (article 1.0))))) - -(dolist (buf-name '(forward reply reply-yank)) - (gnus-add-configuration - `(,buf-name - (if (>= (frame-width) my/gnus-side-by-side-threshold) - '(vertical 1.0 - (summary 0.25) - (horizontal 1.0 - (article 0.5) - (message 1.0 point))) - '(vertical 1.0 - (summary 0.2) - (article 0.2) - (message 1.0 point)))))) - -;;; Summary tweaks. - -(defun my/gnus-toggle-article-wrap () - (interactive) - (with-current-buffer gnus-article-buffer - (visual-line-mode 'toggle))) - -(defun my/gnus-summary-tweak-keys () - (keymap-local-set "C-c d v" 'my/gnus-toggle-article-wrap)) - -(add-hook 'gnus-summary-mode-hook 'my/gnus-summary-tweak-keys) - -;; message-subject-re-regexp is used both in Gnus summary buffers to -;; detect and elide similar subjects in a thread, and by message mode -;; when replying, to determine what to strip from the subject. -;; -;; Some MUAs add cruft to the subject, turning "Re: bug#123: foobar" -;; into "RE: [External] : Re: bug#1234: foobar", which Debbugs will -;; then turn into "bug#1234: [External] : Re: bug#1234: foobar". -;; -;; The only way I can find to tell the Gnus summary code to -;; canonicalize all that cruft away is by tweaking this regexp, but -;; setting its global value causes message-mode to elide stuff it -;; shouldn't when crafting subjects. Therefore, chase down the best -;; Gnus hook for the job, and set the regexp locally. -(defun my/gnus-reply-prefixes () - (mapcan (lambda (prefix) (list prefix (upcase prefix) (capitalize prefix))) - '("re" "aw" "sv" "fw" "fwd"))) - -(setq my/gnus-summary-normalize-subject - (rx-to-string - `(seq bol - (+ (or (seq word-start (or ,@(my/gnus-reply-prefixes)) word-end) - (seq "bug#" (+ digit)) - (seq "[" (or "External" "SPAM UNSURE") "]")) - (? (* space) ":") (* space))))) - -(add-hook 'gnus-summary-generate-hook - (lambda () - (setq-local message-subject-re-regexp - my/gnus-summary-normalize-subject))) - -(let* ((initials (mapconcat (lambda (s) (substring s 0 1)) - (split-string user-full-name) - nil)) - (sent-prefix (format "%s → " initials))) - (setq gnus-summary-to-prefix sent-prefix - gnus-summary-newsgroup-prefix sent-prefix)) - -;;; Article tweaks. - -(defun my/gnus-article-eschew-tables () - ;; I set shr-fill-text to nil because I prefer letting - ;; visual-line-mode manage wrapping. Unfortunately, many HTML - ;; emails rely on <table>s for layouts, and rendering can get ugly. - ;; Work around this by treating <table> & children as any other - ;; <div>. - (make-local-variable 'shr-external-rendering-functions) - (pcase-dolist (`(,tag . ,shr-function) - '((table . shr-tag-div) - (thead . shr-tag-div) - (tbody . shr-tag-div) - (tr . shr-tag-ul) - (th . shr-tag-li) - (td . shr-tag-li))) - (setf (alist-get tag shr-external-rendering-functions) shr-function))) - -(defun my/gnus-article-has-html () - ;; Hard to tell the difference between - ;; * the variable `gnus-article-mime-handles', - ;; * the function `gnus-article-mime-handles', - ;; * the variable `gnus-article-mime-handle-alist'. - ;; - ;; Stealing debbugs.el's patch-finding logic. - (seq-some - (lambda (handle) - (string= (mm-handle-media-type (cdr handle)) "text/html")) - (gnus-article-mime-handles))) - -(defun my/gnus-article-should-wrap () - (save-excursion - (message-goto-body) - (let ((should-wrap nil) - (has-html (my/gnus-article-has-html))) - (while-let (((not should-wrap)) - ((not (eobp))) - (current-line (thing-at-point 'line))) - (setq should-wrap - (and - ;; The line is bigger than the target width. - (> (length current-line) - (window-width (get-buffer-window gnus-article-buffer))) - ;; The line is not boring (citation, diff addition/removal). - (not (string-match-p "\\`[>+-]" current-line)) - ;; Lines that start with spaces are boring, except in - ;; HTML parts: those are choked with <table> tags that - ;; shr left-pads with spaces. - ;; NB: HAS-HTML is a naive heuristic: we are assuming - ;; that "any text/html part is present" means "we are - ;; looking at this text/html part". - (or (not (string-match-p "\\` " current-line)) has-html))) - (forward-line)) - should-wrap))) - -(defun my/gnus-article-wrap-maybe () - ;; Enable visual-line-mode when it helps, i.e. when the message has - ;; long lines that are not part of citations nor patches. - (with-current-buffer gnus-article-buffer - (visual-line-mode - (unless (my/gnus-article-should-wrap) -1)))) - -;; Article setup is tricky. In order, `gnus-article-prepare' -;; -;; (1) calls `gnus-article-setup-buffer', which -;; (a) calls `gnus-article-mode', which runs -;; gnus-article-mode-hook, -;; (b) sets truncate-lines from gnus-article-truncate-lines, -;; -;; (2) calls `gnus-display-mime', which may end up calling `mm-shr'; -;; this can call `shr-tag-table', which turns truncate-lines on -;; unconditionally. -;; -;; (3) runs gnus-article-prepare-hook. -;; -;; Gnus will only run (1a) once, and skip that step when it re-uses -;; the same *Article* buffer for subsequent articles. So for our -;; purposes, we need to -;; -;; (Ⅰ) hack the shr rendering functions in mode-hook, before `mm-shr' -;; gets to work. -;; (Ⅱ) call `visual-line-mode' (if needed) in prepare-hook, after -;; truncate-lines has been set. - -(add-hook 'gnus-article-mode-hook 'my/gnus-article-eschew-tables) -(add-hook 'gnus-article-prepare-hook 'my/gnus-article-wrap-maybe) - -;;; MIME display. -(defun my/mm-display-markdown-inline (handle) - (mm-display-inline-fontify handle 'markdown-mode)) - -(with-eval-after-load 'mm-decode - ;; bug-gnu-emacs:<jwvzfsnntlq.fsf-monnier+emacs@gnu.org> - (setf (alist-get "text/markdown" mm-inline-media-tests nil nil 'equal) - '(my/mm-display-markdown-inline))) - -;;; Key bindings. -;; -;; m compose -;; -;; Group buffer: -;; -;; L list all groups -;; RET view unread mail in group -;; C-u RET view all mail in group -;; g refresh -;; G G search group -;; -;; Summary buffer: -;; -;; B m move message to group -;; / N fetch new -;; M-g refresh (expire, move, fetch new, show unread) -;; C-u M-g refresh (expire, move, fetch new, show all) -;; C-u g show raw, undecoded message source; g to decode -;; T h collapse (hide) thread -;; T s expand (show) thread -;; T k, C-M-k mark thread as read -;; M-1 T k mark thread as unread -;; r reply -;; R reply (quoting) -;; S w reply-all -;; S W reply-all (quoting) -;; C-c C-f forward -;; d mark read -;; M-u clear marks (≡ mark unread) -;; E expire -;; # toggle mark for next action -;; M-#, M P u unmark for next action -;; -;; Draft summary buffer: -;; -;; D e edit draft -;; -;; Article buffer: -;; -;; o save attachment at point -;; K b add button for inlined MIME part -;; -;; Composing: -;; -;; C-c C-c send -;; C-c C-a attach -;; C-c C-f s change the subject (append "was:") -;; -;;; FAQ. -;; -;; - how to see *all mails*, not just unread? -;; - C-u RET -;; -;; - how to do something on a bunch of mail matching a pattern? -;; - M P R ; mark all mails with subjects matching regexp -;; - M-& <x> ; do <x> on all marked mails -;; -;; - how to delete mail? -;; - E to mark as expired -;; - C-u M-g to refresh -;; -;; - how to remove groups deleted on the IMAP server? -;; - b to iterate over "bogus" groups and remove them -;; -;; - how to list most-recent mails on top? -;; - cf. gnus-thread-sort-functions -;; -;; - how to close a mail without going back to the group list? -;; - = to make summary full-screen -;; -;; - how to get contact completion? -;; - install ebdb from GNU ELPA -;; - or just use message-mail-alias-type -;; -;; - how to refresh? -;; - summary buffer: -;; - / N (fetch new) -;; - M-g (expire, move, fetch & redisplay) -;; - group buffer: g -;; -;; - what do all those letters mean? -;; (info "(gnus) Marking Articles") -;; - O old ≡ read during previous session -;; - R just read -;; - r manually marked as read -;; - A answered -;; - E expirable -;; - G cancelled (e.g. moved somewhere else) -;; - . unseen -;; -;; - how to subscribe to mailing lists? -;; - to browse an NNTP server, either -;; - hit B in the group buffer, then nntp *some server* -;; - or add (nntp "*some server*") to gnus-secondary-methods -;; - over the list: u -;; -;;; TODO. -;; -;; - gnus-summary-line-format (📎 for attachments) -;; -;; - how to archive mails and news locally? -;; -;; - describe-key is mostly useless in article mode: -;; > X runs the command gnus-article-read-summary-keys -;; -;; - detect possibly missing attachments from keywords |
