;; -*- lexical-binding: t -*- ;; user-full-name: from /etc/passwd, chfn(1). ;; user-mail-address: from EMAIL variable, ~/.profile & ~/.xsessionrc. ;; In ~/.authinfo.gpg: ;; machine imap.gmail.com login LOGIN password PASSWORD port 993 ;; machine smtp.gmail.com login LOGIN password PASSWORD port 587 ;; machine irc.freenode.net login LOGIN password PASSWORD (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. gnus-article-unfold-long-headers t gnus-treat-fill-article nil gnus-treat-fill-long-lines nil gnus-treat-fold-headers nil) ;;; Summary tweaks. (defun my/gnus-toggle-article-wrap () (interactive) (with-current-buffer gnus-article-buffer (visual-line-mode 'toggle))) (add-hook 'gnus-summary-mode-hook (lambda () (setq fill-column 120) (my/centered-mode) (keymap-local-set "C-c d v" 'my/gnus-toggle-article-wrap))) ;; 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. 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-has-html () (seq-some (lambda (handle) (and (listp handle) (string= (mm-handle-media-type 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) fill-column) ;; The line is not boring (citation, diff addition/removal). (not (string-match-p "\\`[>+-]" current-line)) ;; Lines that start with spaces are boring, unless this ;; is an HTML part: those are choked with