;;; .gnus --- Edward O'Connor's Gnus configuration -*- emacs-lisp -*- ;; Copyright (C) 1997 -- 2011 Edward O'Connor ;; Author: Edward O'Connor ;; Keywords: local ;; This file is NOT part of GNU Emacs. ;; This is free software; you can redistribute it and/or modify it under ;; the terms of the GNU General Public License as published by the Free ;; Software Foundation; either version 2, or (at your option) any later ;; version. ;; This file is distributed in the hope that it will be useful, but ;; WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with Emacs; see the file COPYING, or type `C-h C-c'. If not, ;; write to the Free Software Foundation at this address: ;; Free Software Foundation ;; 51 Franklin Street, Fifth Floor ;; Boston, MA 02110-1301 ;; USA ;;; Code: (setq gnus-novice-user nil) (when (executable-find "uncompface") (set (if (ted-variable-obsolete-p 'gnus-treat-display-xface) 'gnus-treat-display-x-face 'gnus-treate-display-xface) 'head)) (defconst ted-x-face (concat "#()Nun50FWhQvC^2/~=QQ`5c#28BjpE|dM0G']o]qVVKi2jHFqRFo[kGYloI\n" " wU\"N>Hhz0pS10c.yki^~3l{=.h@l\\-*G\\P\"@C!JZ,XZLJqv`,{)XUpo8qYu::fXJ[`\n" " QdcFF}p%kQ#wD@mA.\\CxU_#gVKOC.n/5LM/9paO\\>A9<^fdNH(||@C0I'bB(f]WHYB\n" " *ZEgQzA/6/-4~vf?NUd6JN\"ocE@Q(^)Ryity|#4n>p\\c4Y2`n=hfn\\w-oRF|@-") "My X-Face header. It's the Gödel SOMAD pic from Forum 2000.") (defconst ted-face "iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAHlBMVEX47PoBAAegiLwiH1N IQYI0M4iMeKYBAAYGBBGqm9JF4g0mAAACYElEQVR4nGWTsY/aMBTGLXoLo8WQjNVrFJXxzviUbig JEcy5SNft5LhRGT3RNecUuRuiCMn/bZ+dhHDqJ2SZ7+f3nt/DEMOcqv9E9AdQTsD7fPw6hRIz+iw xxuhbMBn3SUtRofk95CTa9D49UIWiRvt4TnTiNmUbHIIDykUxdwm8lTvQUmergwoCpXR/qwojXqk 7jTEK1xANXhKOgD8eRmHggrt2CNKKtfcAU3EHkCbB5OJn4Ws40Prco6jhAyiDoSyeTrAb1gNe+dI eKNVlpvXNE5+pT6HUIjEi24a8B6XvjSrd0rCon5vCDwX7eA2wvV9bqrPWdCAFZBtfA0tQRWmRsE6 uZCMA6qYHbRDg6I5RlxVSFNCISG56QB3oIBNSRKL+JuLMg9LZlGqIUhCFlH9m8FN74GxFQwEFxKm crWYQJQ680v43TSEGEDArAWLJPVAObN8BHDghhrwcI1RYH2GSLMfiKnzWd6DGx4DvwNc41mIC0QQ WqzgXH0HV+kvVoohvIB5AaHRSyCZHyzawtOd4SBUyXR9lxOb2RB7Sz4T0AB8zY/smvWzRIrN0OQL GcsbW8zf7dY1gfsIlZm66JUsdOK3ljjjNCbnoHuxq9jQnb+TkAa6XY0XyJmf7C1uRwfbk4b0m1tr 8+zljb+ROD0+xA9f4umHP9+CTAAesjfGPWNyBvzCAc5ax/I40CFJPvkQrC/vRP+NsiC58LpGKfWH 7Ppy/JMY8ObK0AJfTRUDTz5eQxHS2VxPlG1697N0ee4qSbjeQ64bjc94Nhex1b+2N5Hn1MoJJwlp pf1Rr7/8DXitGHanPc2gAAAAASUVORK5CYII=" "My Face header. It's an image of Ikari Shinji listening to music.") (setq mail-default-headers (concat "Face: " ted-face "\n") message-hidden-headers "\\(X-\\)?Face") (eval-after-load "gnus-art" '(setq gnus-visible-headers (concat (format "^\\(%s\\):" (regexp-opt '("User-Agent" "X-Mailer" "X-Newsreader" "X-Spam-Level" "List-Id" "X-Report-Spam" "Archived-At" "Comments"))) "\\|" gnus-visible-headers))) (setq message-user-organization "Church of Emacs") (setq gnus-treat-hide-headers 'head gnus-treat-hide-boring-headers 'head message-default-headers mail-default-headers) (defun ted-insert-citation-line () "Insert a simple citation line." (when message-reply-headers (let* ((components (mail-extract-address-components (mail-header-from message-reply-headers))) (name (or (car components) "You")) (email (cadr components))) (insert (cond ((string-match gnus-ignored-from-addresses email) "I") (t name)) " wrote:") (newline) (newline)))) (setq message-citation-line-function 'ted-insert-citation-line) (when (locate-library "tc") (autoload 'trivial-cite "tc" nil t) (setq message-cite-function 'trivial-cite tc-make-attribution 'tc-tiny-attribution)) (setq gnus-face-0 'font-lock-type-face) (setq gnus-face-1 'font-lock-string-face) (setq gnus-face-2 'font-lock-variable-name-face) (setq gnus-face-3 'font-lock-keyword-face) (setq gnus-group-line-format "%2{%M%S%p%} %0{%5y%} %P%1{%G%}\n") (setq gnus-topic-line-format "%i%3{[ %n -- %A ]%}%v\n") (setq gnus-summary-line-format (concat "%U%R%z%{" (if ted-oort+-flag "%B" "%I") "%} %0{%-25,25f %}%1{%s%}\n")) (defun gnus-goto-colon () (goto-char (point-at-bol))) (setq gnus-ignored-from-addresses (regexp-opt '(;; Gmail "hober0@gmail.com" ;; Standard. "ted@oconnor.cx" ;; Work "eoconnor@apple.com" ;; Old Teradata addresses "eo250006@teradata.com" "Edward.O'Connor@teradata.com" ;; Old EVDB / Eventful addresses "ted@evdb.com" "oconnor@evdb.com" "ted@eventful.com" ;; Old Tomo address "edward.oconnor@tomosoftware.com" ;; Old UCSD addresses "oconnor@ucsd.edu" "oconnor@soe.ucsd.edu" ;; RHIT "oconnoem@cs.rose-hulman.edu" "oconnoem@alumni.rose-hulman.edu" ;; old ISP "oconnoem@theworld.com"))) (setq message-dont-reply-to-names gnus-ignored-from-addresses) (defun ted-follow-link-at-point (point) "Try to follow an HTML link at point. This works for links created by w3, w3m, and on URLs embedded in text." (interactive "d") (let ((props (text-properties-at point))) (browse-url (or (plist-get (plist-get props 'w3-hyperlink-info) :href) (plist-get props 'w3m-href-anchor) (thing-at-point 'url) (error "Couldn't determine link at point."))))) (add-hook 'gnus-article-mode-hook (lambda () (local-set-key (kbd "C-c a") 'ted-follow-link-at-point))) (when (fboundp 'message-forward-subject-fwd) (setq message-make-forward-subject-function 'message-forward-subject-fwd)) (setq gnus-verbose 1 gnus-verbose-backends 1) (defun ted-mimedown () (interactive) (save-excursion (message-goto-body) (shell-command-on-region (point) (point-max) "~/bin/mimedown" nil t))) (setq mail-source-delete-incoming t gnus-activate-foreign-newsgroups nil gnus-treat-display-smileys nil gnus-treat-strip-trailing-blank-lines t gnus-treat-hide-citation nil gnus-treat-strip-multiple-blank-lines nil gnus-inhibit-startup-message t ;; My scores should be global. gnus-home-score-file "all.SCORE" gnus-visual t) (when (file-executable-p "/usr/bin/open") (eval-after-load "mailcap" '(mailcap-add "application/pdf" "open %s"))) (add-hook 'gnus-summary-mode-hook (lambda () (setq gnus-summary-expunge-below -5))) (add-hook 'message-sent-hook 'gnus-score-followup-thread) (add-hook 'gnus-group-mode-hook 'gnus-topic-mode) (add-hook 'nnfolder-save-buffer-hook (lambda () (set (make-local-variable 'backup-inhibited) t))) (setq nnmail-split-methods 'nnmail-split-fancy) (setq nnmail-treat-duplicates 'warn ; or 'delete nnmail-cache-accepted-message-ids t nnmail-message-id-cache-length 10000) ; Change a \205 figure to "..." (add-hook 'gnus-part-display-hook 'article-treat-dumbquotes) (setq gnus-topic-display-empty-topics t) ; Don't display topics that have nothing in them (setq gnus-topic-display-empty-topics nil) (when (and (fboundp 'gnus-subscribe-randomly) ted-oort+-flag) (if (listp gnus-subscribe-newsgroup-method) (add-to-list 'gnus-subscribe-newsgroup-method 'gnus-subscribe-randomly) (if (null gnus-subscribe-newsgroup-method) (setq gnus-subscribe-newsgroup-method 'gnus-subscribe-randomly) (setq gnus-subscribe-newsgroup-method (list 'gnus-subscribe-randomly gnus-subscribe-newsgroup-method))))) ;; I always hit 'j' instead of 'n' (gnus-define-keys gnus-summary-mode-map "j" gnus-summary-next-unread-article) (global-set-key (kbd "C-x m") 'gnus-group-mail) (defun ted-insert-centered-line (line) "Insert LINE into the current buffer. Will also insert the necessary number of spaces and newlines to center LINE in the window." (let ((lines (make-string (/ (frame-height) 2) ?\n)) (spaces (make-string (- (/ (frame-width) 2) (/ (length line) 2)) ?\ ))) (insert lines spaces line))) (defmacro with-compy-deleted-display (&rest body) "Execute forms in BODY while displaying a 'DELETED!!' buffer. Just like on Strong Bad's Compy 386. BA-LEETED!" `(save-window-excursion (let ((old-buf (current-buffer))) (with-temp-buffer (setq mode-line-format nil indicate-empty-lines nil indicate-buffer-boundaries nil) (let ((default-bg (face-background 'default)) (default-fg (face-foreground 'default)) (fringe-bg (face-background 'fringe)) (fringe-fg (face-foreground 'fringe))) (unwind-protect (progn (set-face-background 'default "Medium Blue") (set-face-foreground 'default "White") (set-face-background 'fringe "Medium Blue") (set-face-foreground 'fringe "White") (ted-insert-centered-line "DELETED!!!") (message "") (delete-other-windows) (switch-to-buffer (current-buffer)) (recenter) (with-current-buffer old-buf ,@body)) (set-face-background 'default default-bg) (set-face-foreground 'default default-fg) (set-face-background 'fringe fringe-bg) (set-face-foreground 'fringe fringe-fg))))))) (put 'with-compy-deleted-display 'lisp-indent-function 0) (defadvice gnus-summary-delete-article (around compyify-deletion activate) "Ensure that article deletion always looks like Strong Bad's Compy 386." (with-compy-deleted-display (sit-for 1) ad-do-it)) (defun ted-gnus-mark-thread-advance (p) "Mark this thread, and advance point to the next one. With prefix P, mark the next P threads, and advance point past all of them." (interactive "p") (let ((i 0)) (while (< i p) (gnus-uu-mark-thread) (gnus-summary-next-thread 1) (setq i (+ i 1))))) (add-hook 'gnus-summary-mode-hook (lambda () (local-set-key (kbd "") 'ted-gnus-mark-thread-advance))) ;% ;; yay oort (setq gnus-gcc-mark-as-read t) (defvar ted-default-gcc-group "INBOX") (defun ted-gnus-message-archive-group (group) (setq group (or group ted-default-gcc-group "INBOX")) (let ((method (gnus-find-method-for-group group))) (format "%s+%s:%s" (car method) (cadr method) group))) (setq gnus-message-archive-group 'ted-gnus-message-archive-group) (defvar ted-smtp-flag t "*Non-nil if I should use SMTP for sending mail. Set this before loading ~/.gnus!") (when ted-smtp-flag (setq message-send-mail-function 'smtpmail-send-it send-mail-function 'smtpmail-send-it smtpmail-local-domain nil smtpmail-debug-info t)) (setq smtpmail-starttls-credentials '(("smtp.gmail.com" 587 nil nil)) smtpmail-smtp-server "smtp.gmail.com" smtpmail-default-smtp-server "smtp.gmail.com" send-mail-function 'smtpmail-send-it message-send-mail-function 'smtpmail-send-it smtpmail-smtp-service 587 smtpmail-auth-credentials "~/.authinfo") ;; Should be overridden in local gnus config (setq gnus-select-method '(nnimap "imap.gmail.com" (nnimap-stream ssl) (nnimap-authenticator login)) gnus-secondary-select-methods '((nntp "news.gmane.org") (nntp "news.eternal-september.net"))) (defun ted-mangle-gmane-archival-gnus-data (link) "Mangle the `gnus-data' property value LINK. Specifically, change the archival URL from permalink.gmane.org (Gmane's blog-like interface) to article.gmane.org (Gmane's newslike interface)." (let ((original-date (get-text-property 5 'original-date link)) (face (get-text-property 5 'face link))) (propertize (replace-regexp-in-string "permalink" "article" (substring-no-properties link)) 'face face 'original-date original-date))) (defun ted-mangle-gmane-archival-header () "Mangle Gmane's Archived-At header to be more useful. Specifically, change the archival URL from permalink.gmane.org (Gmane's blog-like interface) to article.gmane.org (Gmane's newslike interface)." (gnus-with-article-headers (when (gnus-article-goto-header "Archived-At") (save-excursion (alter-text-property (+ 2 (point)) (1- (line-end-position)) 'gnus-data 'ted-mangle-gmane-archival-gnus-data)) (when (re-search-forward "permalink" (line-end-position) t) (replace-match (propertize "article" 'face 'gnus-header-content)))))) (add-hook 'gnus-article-prepare-hook 'ted-mangle-gmane-archival-header) (defun ted-report-spam () "Blah blah blah." (interactive) (let* ((server-name (gnus-method-to-server-name (gnus-find-method-for-group gnus-newsgroup-name))) (reporting-function (cdr (assoc* server-name ted-report-spam-map :test 'string-equal)))) (if reporting-function (funcall reporting-function) (message "No suitable spam reporting mechanism found.")))) ;; Key bindings from (gnus) Spam Package Introduction (gnus-define-keys gnus-summary-mode-map "Sx" ted-report-spam "Msx" ted-report-spam "\M-d" ted-report-spam) (defvar ted-report-spam-map '(("nnimap+imap.gmail.com" . ted-report-spam-to-gmail) ("nntp+news.gmane.org" . ted-report-spam-to-gmane)) "Blah blah blah.") (defun ted-report-spam-to-gmail () (gnus-summary-move-article nil "nnimap+imap.gmail.com:[Gmail]/Spam")) (autoload 'url-retrieve "url") (defun ted-report-spam-to-gmane () (gnus-with-article-headers (gnus-article-goto-header "Archived-At") (let ((url (buffer-substring-no-properties (+ 2 (point)) (1- (line-end-position)))) (url-request-method "POST")) ;; Every so often, gmane articles don't have Archived-At headers. (when (string-match gnus-button-url-regexp url) ;; N.B., we replace either 'article' or 'permalink' so that this ;; doesn't depend on my s/permalink/article/ hack. (setq url (replace-regexp-in-string "\\(article\\|permalink\\)" "spam" url nil t)) (setq url (replace-regexp-in-string "/\\([[:digit:]]+\\)$" ; $ ":\\1:unconfirmed" url)) ;; Fire and forget the spam report. (url-retrieve url (lambda (&rest ignore) (message "Spam reported to Gmane."))))))) (setq gnus-posting-styles '((".*" (name "Edward O'Connor") ("Jabber-ID" "hober0@gmail.com") ("X-Attribution" "Ted") (address "hober0@gmail.com") (signature "\ Edward O'Connor hober0@gmail.com Ense petit placidam sub libertate quietem.") (organization nil))));% (load (expand-file-name "local-gnus" ted-elisp-dir) t) ;;; .gnus ends here