;; -*- emacs-lisp -*-
;;; dot.gnus --- gnus configuration file

;; Author: Mark Triggs <mst@dishevelled.net>
;; Keywords: news
;; $Id: dot.gnus,v 1.291 2007/03/04 11:06:41 mst Exp $

;; This file 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 GNU Emacs; see the file COPYING. If not, write to the Free
;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
;; 02111-1307, USA.

;;; Code:

(try-require
 "gnus-mst-common"
 "gnus-homebrew" ; Small homemade functions
 "message-identities" ; Identities based on recipient
 'bbdb-com 'bbdb-hooks 'bbdb-gnus
 'spam ; spam filtering
 "gnus-mst-manipulate-threads" ; Alter references headers in summary
 "gnus-mst-move-article" ; Move articles to a group based on bbdb
 "gnus-mst-show-country" ; Display the country of posters.
 "gnus-mst-bbdb-split" ; Split based on bbdb rules
 'gnus-inline-docs ; Show word documents inline
 "gnus-notify" ; modeline notification of groups with new messages
 "gnus-loose-threads-by-date"
 )

(when (try-require 'escreen)
  (escreen-create-screen)
  (defvar gnus-screen nil)
  (setq gnus-screen escreen-current-screen-number)

  (defun select-gnus ()
    (interactive)
    (let ((gnus-buffers (remove-if-not
                         (lambda (b)
                           (member (buffer-mode b)
                                   '(message-mode gnus-summary-mode
                                                  gnus-group-mode)))
                         (buffer-list))))
      (if (= escreen-current-screen-number gnus-screen)
          (when gnus-buffers
            (let ((pos (position (current-buffer) gnus-buffers)))
              (if pos
                  (switch-to-buffer (nth (mod (1+ pos) (length gnus-buffers))
                                         gnus-buffers))
                (switch-to-buffer (car gnus-buffers)))))
        (escreen-goto-screen gnus-screen))))

  (define-key global-map [?\e f2] 'select-gnus)
  (define-key global-map [M-f2] 'select-gnus))


(defvar dotgnus-loaded-hook nil
  "A hook run after ~/.gnus has been loaded")


;; Identity ;;
(defvar custom-name nil "Your name")
(defvar custom-email nil "default email address")
(defvar custom-signature-file nil "default signature file")
(defvar custom-gpg-key-id nil "GPG key id")

;; Directories ;;
(defvar custom-mail-dir nil "location for gnus to store mail")
(defvar custom-news-dir nil "location for gnus to store news")

;; Outgoing SMTP server (nil for none) ;;
(defvar custom-smtp-server (getenv "SMTPSERVER") "SMTP server to use")

;; Envelope address to use (if this variable is nil, it will be set
;; automatically using the "From:" header of outgoing messages.
(defvar custom-envelope-address nil "address to present to the SMTP server")

;; Topics whose groups should be backed up when gnus-mst-backup is run.
;; Note that groups in sub-topics of these topics will not be backed up
;; unless their specific group is in this list.
(defvar gnus-mst-backup-topics nil
  "A list of topics whose groups should be backed up")

(require 'gnus-user-settings)


;;;; Key Bindings ;;;;

;; Kill the current thread ;;
(when (fboundp 'gnus-mst-summary-nuke-thread)
  (define-key gnus-summary-mode-map (kbd "C-c C-k")
    'gnus-mst-summary-nuke-thread))

(define-key gnus-summary-mode-map (kbd "M-p") 'gnus-summary-prev-thread)
(define-key gnus-summary-mode-map (kbd "M-n") 'gnus-summary-next-thread)

;; Customised move article
(when (fboundp 'gnus-mst-summary-move-article)
  (add-hook 'gnus-summary-mode-hook
            (lambda ()
              (define-key gnus-summary-backend-map "m"
                'gnus-mst-summary-move-article))))

;; Thread manipulation
(when (fboundp 'gnus-mst-summary-make-child)
  (define-key gnus-summary-mode-map (kbd "C-c c")
    'gnus-mst-summary-make-child))

;; Score spam down globally
(define-key gnus-summary-mode-map (kbd "C-c e")
  (lambda ()
    (interactive)
    (gnus-summary-lower-score 500000 'a)))


;; Jump to the article buffer
(when (fboundp 'gnus-markswitch-to-article)
  (define-key gnus-summary-mode-map "+" 'gnus-markswitch-to-article))

;; Make badly formatted articles more sane
(when (fboundp 'gnus-mst-summary-aol-cleanup)
  (define-key gnus-article-mode-map (kbd "C-c w")
    'gnus-mst-summary-aol-cleanup)
  (define-key gnus-summary-mode-map (kbd "C-c w")
    'gnus-mst-summary-aol-cleanup))

;; Fetch groups ;;
(define-key gnus-group-mode-map "f"
  (lambda ()
    (interactive)
    (save-excursion
      (goto-char (point-max))
      (call-interactively 'gnus-fetch-group))))

(when (fboundp 'gnus-msg-mail)
  (add-hook 'gnus-group-mode-hook
            (lambda () (define-key gnus-group-mode-map "m" 'gnus-msg-mail))))
(define-key gnus-summary-mode-map (kbd "TAB")
  'gnus-summary-select-article-buffer)


(define-key gnus-group-mode-map "/"
  (lambda () (interactive)
    (let ((gnus-fetch-old-headers nil)) (gnus-topic-select-group))))

;;;; End of Key Bindings ;;;;



;;;; Hooks ;;;;

;; Don't leave connections open.
;;(add-hook 'gnus-after-getting-new-news-hook 'gnus-mst-close-all-servers)
;; (add-hook 'gnus-get-new-news-hook 'gnus-group-find-new-groups)

;; Show the sender's country in the headers
(add-hook 'gnus-article-prepare-hook 'gnus-article-mst-show-country)

;; Perform GPG operations on outgoing messages if necessary.
(when (fboundp 'gnus-mst-gpg-recipient)
  (add-hook 'message-send-hook 'gnus-mst-gpg-recipient))

(add-hook 'message-send-hook (lambda () (message-rename-buffer)))
;(add-hook 'message-send-hook 'flyspell-buffer)
(add-hook 'message-send-hook 'message-check-for-forgotten-attachments)

;; I'm in the habit of adding leading whitespace. Nuke it.
(when (fboundp 'message-mst-nuke-whitespace)
  (add-hook 'message-send-hook 'message-mst-nuke-whitespace))

(add-hook 'message-send-hook 'message-sort-headers)

(add-hook 'message-send-hook 'message-identity-apply)

(add-hook 'message-send-hook 'message-move-parts-to-bottom t nil)

(when (fboundp 'message-mst-confirm)
  (add-hook 'message-send-hook 'message-mst-confirm t nil))

(when (fboundp 'mc-setversion)
  (mc-setversion "gpg")
  (setq mc-gpg-user-id custom-gpg-key-id))

;; Enable topic mode by default
(add-hook 'gnus-group-mode-hook 'gnus-topic-mode)

;; Enable mailinglist support
(when (fboundp 'turn-on-gnus-mailing-list-mode)
  (add-hook 'gnus-summary-mode-hook 'turn-on-gnus-mailing-list-mode))

;; Use highline mode in the summary buffer
(add-hook 'gnus-summary-mode-hook
          (lambda ()
            (try-require 'highline)
            (when (featurep 'highline)
              (highline-local-mode))))

;; Collapse threads which are half crossposted.
;; (when (fboundp 'gnus-mst-summary-collapse-low-thread)
;;   (add-hook 'gnus-summary-prepared-hook
;;             (lambda ()
;;               (save-excursion
;;                 (goto-char (point-min))
;;                 (while (not (eobp))
;;                   (gnus-mst-summary-collapse-thread -10001 0.5)
;;                   (when (= 1 (gnus-summary-next-thread 1 t))
;;                     (goto-char (point-max))))))))

(if (fboundp 'article-remove-trailing-blank-lines)
    (add-hook 'message-send-hook 'article-remove-trailing-blank-lines))

;; If we have bbdb, use it
(add-hook 'message-mode-hook
          (lambda ()
            (when (fboundp 'footnote-mode)
              (footnote-mode))
            (try-require 'bbdb-gnus)))

(eval-after-load "bbdb-gnus"
  '(progn (add-hook 'message-setup-hook 'bbdb-define-all-aliases)
          (bbdb-initialize 'gnus 'message)
          (setq bbdb-send-mail-style 'compose-mail)))

;;;; End of Hooks ;;;;



;;;; General Options ;;;;

;; Settings for groups ;;

(setq gnus-subscribe-newsgroup-method 'gnus-subscribe-topics

      ;; groups
      gnus-invalid-group-regexp "[: `'\"]\\|^$"
      gnus-group-line-format "%M%S%p%P%5uN: %(%G%)%l\n" ; 'N' user format
                                                        ; function defined
                                                        ; below
      gnus-large-newsgroup 5000         ; Only prompt for really big groups
      gnus-large-ephemeral-newsgroup 5000         ; Only prompt for really big groups
      gnus-group-use-permanent-levels nil
      gnus-group-default-list-level 2
      gnus-activate-level gnus-group-default-list-level
      gnus-keep-same-level nil

      ;; housekeeping
      mail-source-delete-incoming t
      gnus-always-read-dribble-file t
      gnus-read-active-file nil
      gnus-cache-active-file (expand-file-name "~/.news/cache/active")
      gnus-use-dribble-file t
      gnus-save-killed-list nil         ; don't save a killed list
      gnus-save-newsrc-file nil         ; Don't save a .newsrc file
      gc-cons-threshold 50000000        ; Minimise garbage collection

      ;; topics
      gnus-topic-indent-level 4
      gnus-topic-line-format "%i[ %1{%(%{%n%}%)%} ]%v\n")


;;; Show the total number of articles for certain groups
(when (fboundp 'gnus-define-group-parameter)
  (gnus-define-group-parameter
   show-all-articles
   :type bool
   :parameter-type '(const :tag "Show the total article count for this group." t)
   :parameter-document "\

If this is set, the total number articles in this group will be shown in the
group buffer (instead of only unread articles)
"))

(defun gnus-user-format-function-N (dummy)
  ;; gnus-tmp-group captured from calling environment
  (let ((count (if (cdr (assoc 'show-all-articles
                               (gnus-group-find-parameter gnus-tmp-group)))
                   (if (gnus-active gnus-tmp-group)
                       (1+ (- (cdr (gnus-active gnus-tmp-group))
                              (car (gnus-active gnus-tmp-group))))
                     0)
                 (gnus-group-unread gnus-tmp-group))))
    (if (numberp count)
        (number-to-string count)
      "*")))


;; Prompt before subscribing or unsubscribing
(defadvice gnus-group-unsubscribe-current-group
  (around gnus-group-unsubscribe-current-group-mst () activate)
  (when (y-or-n-p "Really (un)subscribe this group? ")
    ad-do-it))

;; Check for new mail every 2 minutes
(gnus-demon-add-handler 'gnus-group-get-new-news 2 t)
(gnus-demon-init)

;; Set the window title
;(modify-frame-parameters nil '((title . "Gnus")))


;; Settings for reading articles ;;

(setq gnus-asynchronous t             ; read ahead for articles
      gnus-suppress-duplicates t
      gnus-use-article-prefetch 10
      nndoc-article-type 'guess

      message-cite-prefix-regexp "\\([ 	]*[-_.[:word:]]+>+\\|[ 	]*[]>)|}+]\\)+"

      ;; vanity stuff
      gnus-summary-line-format "%U%R%I%(%[%4L: %-19,19a%]%) %0{%s%}\n"
      gnus-single-article-buffer nil    ; Use multiple article buffers
      gnus-treat-display-smileys nil
      gnus-treat-emphasize nil          ; Don't mess with *blah*s
      gnus-unseen-mark 32               ; blank
      gnus-keep-backlog 10
      gnus-visible-headers (concat
                            "^Date:\\|^From:\\|^To:\\|^Newsgroups:"
                            "\\|^Subject:\\|^X-Sent:\\|^Cc:\\|Reply-To:"
                            "\\|Followup-To:"
                            "\\|X-Mailer:\\|User-Agent:")

      ;; don't use HTML when plaintext is available
      mm-discouraged-alternatives '("text/html" "text/richtext")
      mm-inline-large-images t
      gnus-mime-display-multipart-related-as-mixed t
      gnus-buttonized-mime-types '("multipart/signed" "multipart/encrypted")
      ;; headers customisation
      gnus-article-date-lapsed-new-header t
      gnus-extra-headers '(To Newsgroups X-Newsreader Content-Type
                              CC User-Agent Gnus-Warning)
      nnmail-extra-headers gnus-extra-headers
      gnus-sorted-header-list '("^Date:" "^From:" "^To:" "^Newsgroups:"
                                "^Cc:" "^Subject:" "^X-Country:" "^X-Sent:")
      gnus-treat-date-lapsed 'head  ; show the time since this article came in

      ;; threading
      gnus-fetch-old-headers t
      gnus-build-sparse-threads nil
      gnus-simplify-subject-functions '(gnus-simplify-whitespace
                                        gnus-simplify-subject-re)
      gnus-sort-gathered-threads-function 'gnus-thread-sort-by-date
      gnus-summary-thread-gathering-function 'gnus-gather-threads-by-subject
      gnus-summary-make-false-root 'adopt
      gnus-summary-gather-subject-limit 'fuzzy

      ;; Sort by number, then subject and finally by date.
      gnus-thread-sort-functions '(gnus-thread-sort-by-number
                                   gnus-thread-sort-by-subject
                                   gnus-thread-sort-by-date)

      ;; mime related
      gnus-uu-tmp-dir (concat custom-news-dir ".tmp/")
      gnus-uu-post-length 7500
      mm-verify-option 'known

      ;; posting
      gnus-confirm-mail-reply-to-news t ; Confirm before replying to news
      nnmail-extra-headers gnus-extra-headers

      ;; article saving
      ;; Only prompt for one file when saving multiple articles
      gnus-prompt-before-saving t
      gnus-default-article-saver 'gnus-summary-save-in-mail

      ;; scoring
      gnus-summary-default-high-score 500
      gnus-default-adaptive-score-alist
      '((gnus-kill-file-mark)
        (gnus-unread-mark)
        (gnus-read-mark
         (subject 1)
         (from 1))
        (gnus-catchup-mark
         (subject -10))
        (gnus-killed-mark
         (subject -20))
        (gnus-del-mark
         (subject -15)))
      gnus-score-interactive-default-score 1000
      bbdb/gnus-score-default gnus-score-interactive-default-score
      gnus-score-find-score-files-function '(gnus-score-find-bnews
                                             bbdb/gnus-score))

;; Don't thread by subject if the article has less than 5 characters
;; (this would probably be inaccurate otherwise)
(when (string-match "Oort" gnus-version)
  (when (not (boundp 'gnus-summary-gather-exclude-subject))
    (setq gnus-summary-gather-exclude-subject nil))
  (setq gnus-summary-gather-exclude-subject
        (concat gnus-summary-gather-exclude-subject "\\|^.\\{1,10\\}$")))

;; Saved marks irritate me.
(defun gnus-summary-set-saved-mark (&rest args) nil)

;; Gnus Agent ;;
(setq gnus-agent t
      gnus-agent-expire-days 5)

(when (boundp 'message-required-headers)
  (setq message-required-headers (remove 'From message-required-headers)))
(when (boundp 'message-required-mail-headers)
  (setq message-required-mail-headers
        (remove-if (lambda (e) (and (consp e) (eql 'User-Agent (cdr e))))
                   message-required-mail-headers)))
(when (boundp 'message-required-news-headers)
  (setq message-required-news-headers
        (remove-if (lambda (e) (and (consp e) (eql 'User-Agent (cdr e))))
                   message-required-news-headers)))

;; Settings for sending messages ;;
(setq gnus-gcc-mark-as-read t
      message-sendmail-f-is-evil t
      message-kill-buffer-on-exit t
      message-draft-headers nil

      message-cite-function 'message-cite-original-without-signature
      mail-user-agent 'gnus-user-agent
      message-header-format-alist (append '((From))
                                          message-header-format-alist)
      custom-from-header-default (concat custom-name " <" custom-email ">")

      message-forward-ignored-headers
      (concat "^Content-Transfer-Encoding:\\|^X\\|^Received:\\|"
              "^Return-Path:\\|^References:\\|"
              "^In-Reply-To:\\|^Lines:")

      ;; Headers to be added to outgoing messages
      message-default-headers (concat
                               ;; My gnus version
                               (concat "User-Agent: " (gnus-version) "\n")))


;; Build a regular expression that matches all of our addresses based on enties
;; for identities and custom-email.
(when message-identities
  (setq message-dont-reply-to-names
        (regexp-opt
         (cons custom-email
               (mapcan (lambda (i)
                         (let ((a (cdr (assoc 'from (identity-headers i)))))
                           (if (stringp a)
                               (list (car (ietf-drums-parse-address a)))
                             nil)))
                       message-identities)))))

;; Leave out the sender header
(add-to-list 'message-syntax-checks '(sender . disabled))

;; Settings for directories ;;

(setq gnus-article-save-directory custom-news-dir
      message-auto-save-directory (concat custom-mail-dir "message-autosave/")
      gnus-directory custom-news-dir
      gnus-cache-directory (concat custom-news-dir "cache")
      gnus-dribble-directory custom-news-dir ; Dribble here, please
      gnus-kill-files-directory custom-news-dir
      mail-source-directory custom-mail-dir
      nntp-marks-directory (format "%smarks/" custom-news-dir)
      message-directory custom-mail-dir
      nndraft-directory custom-mail-dir
      gnus-agent-synchronize-flags t
      nnmail-tmp-directory custom-mail-dir)
;; Overload functions that gnus uses to construct message-id, sender etc.
;; Set the user name and login name to the email address we are sending from.
(defadvice message-generate-headers
  (around message-generate-headers-mst () activate)

  (let* ((address (or (message-fetch-field "from")
                      custom-email
                      (user-mail-address))))

    (flet
        ((user-login-name ()
           (car (split-string
                 (cadr (mail-extract-address-components address))
                 "@")))

         (system-name ()
           (cadr (split-string
                  (cadr (mail-extract-address-components address))
                  "@"))))
      ad-do-it)))

(defun gnus-mst-pick-method ()
  "Grok the current mail buffer and global variables and set the mail
  transport method accordingly. If the message contains an X-SMTP header, its
  contents are assumed to be the SMTP server that should be used to deliver
  the message. If CUSTOM-SMTP-SERVER is set, it is used as the SMTP server.
  Otherwise, sendmail is used."

  (let ((the-smtp-server (or (message-fetch-field "x-smtp")
                             custom-smtp-server)))
    (unwind-protect
        (progn (message-narrow-to-headers)
               (message-remove-header "x-smtp"))
      (widen))
    (if (not the-smtp-server)
        (setq message-send-mail-function 'message-send-mail-with-sendmail
              gnus-agent-send-mail-function 'message-send-mail-with-sendmail)
      (require 'smtpmail)
      (setq message-send-mail-function 'smtpmail-send-it
            gnus-agent-send-mail-function 'smtpmail-send-it
            smtpmail-smtp-service (parse-integer
                                   (or (cadr (split-string
                                              the-smtp-server
                                              ":"))
                                       "25"))
            smtpmail-smtp-server (car (split-string the-smtp-server ":"))
            smtp-server (car (split-string the-smtp-server ":")))

      (do-once 'message-sent-hook
               (lambda ()
                 (ignore-errors
                   (ad-remove-advice 'smtpmail-via-smtp 'around
                                     'smtpmail-via-smtp-mst))))

      ;; Use tweaked details when talking to the SMTP server
      (defadvice smtpmail-via-smtp
        (around smtpmail-via-smtp-mst () activate)
        (let* ((address (or (message-fetch-field "from")
                            custom-email
                            (user-mail-address))))

          (flet ((user-login-name ()
                                  (car (split-string
                                        (cadr (mail-extract-address-components
                                               address))
                                        "@")))

                 (system-name ()
                              (cadr (split-string
                                     (cadr (mail-extract-address-components
                                            address))
                                     "@"))))

            (let* ((user-mail-address
                    (or (and (boundp 'custom-envelope-address)
                             custom-envelope-address)
                        (cadr (mail-extract-address-components
                               (message-fetch-field "from")))))
                   (smtpmail-mail-address user-mail-address))
              ad-do-it)))))))

(add-hook 'message-send-hook 'gnus-mst-pick-method t)



;;;; Pretty Gnus! ;;;;
(ignore-errors
  ;; Remove god-awful summary highlighting resulting from gnus-agent.
  (when (boundp 'gnus-summary-highlight)
    (mapc
     (lambda (remove-me)
       (setq gnus-summary-highlight
             (remove (rassoc remove-me gnus-summary-highlight)
                     gnus-summary-highlight)))
     '(gnus-summary-high-uncached-face
       gnus-summary-normal-uncached-face
       gnus-summary-low-uncached-face
       gnus-summary-normal-undownloaded-face)))


  (when (not (featurep 'color-theme))
    (try-require 'color-theme))
  (when (featurep 'color-theme)

    ;; Tweak colours if we are running in a window system
    (eval-after-load "gnus-cite"
      '(progn
         (set-face-foreground 'gnus-cite-face-1 "#cde")
         (set-face-foreground 'gnus-cite-face-2 "#89a")
         (set-face-foreground 'gnus-cite-face-3 "#567")
         (set-face-foreground 'gnus-cite-face-4 "#345")
         (set-face-foreground 'gnus-cite-face-5 "blue1")
         (set-face-foreground 'gnus-cite-face-6 "blue4")
         (set-face-foreground 'gnus-cite-face-7 "green1")
         (set-face-foreground 'gnus-cite-face-8 "green4")
         (set-face-foreground 'gnus-cite-face-9 "Black")))

    (setq gnus-face-0 'gnus-group-news-3-face)

    (eval-after-load "gnus-art"
      '(progn
         (set-face-foreground 'gnus-header-name-face "#def")
         (set-face-foreground 'gnus-header-subject-face "#abc")
         (set-face-attribute 'gnus-header-subject-face nil :weight 'normal)
         (set-face-foreground 'gnus-header-content-face "#abc")))

    (set-face-foreground 'gnus-summary-cancelled-face "gray50")
    (set-face-background 'gnus-summary-cancelled-face
                         (face-background 'default))

    (set-face-foreground 'gnus-summary-high-ticked-face "#fff")
    (set-face-foreground 'gnus-summary-high-unread-face "#fff")

    (set-face-foreground 'gnus-summary-low-ticked-face "medium blue")
    (set-face-foreground 'gnus-summary-normal-ticked-face "blue")

    ;; Regular Groups
    (set-face-foreground 'gnus-group-mail-1-face "#fff")
    (set-face-attribute 'gnus-group-mail-1-face nil :weight 'bold)
    (set-face-attribute 'gnus-summary-high-undownloaded-face nil :weight 'bold)
    (set-face-foreground 'gnus-group-mail-2-face "#def")
    (set-face-foreground 'gnus-group-mail-3-face "#cde")

    (set-face-foreground 'gnus-group-news-1-face "#fff")
    (set-face-foreground 'gnus-group-news-2-face "#def")
    (set-face-foreground 'gnus-group-news-3-face "#cde")
    (set-face-foreground 'gnus-group-news-4-face "#bcd")

    ;; Empty Groups
    (set-face-foreground 'gnus-group-mail-1-empty-face "#bcd")
    (set-face-foreground 'gnus-group-mail-2-empty-face "#abc")
    (set-face-foreground 'gnus-group-mail-3-empty-face "#9ab")

    (set-face-foreground 'gnus-group-news-1-empty-face "#bcd")
    (set-face-foreground 'gnus-group-news-2-empty-face "#abc")
    (set-face-foreground 'gnus-group-news-3-empty-face "#9ab")
    (set-face-foreground 'gnus-group-news-4-empty-face "#8ab")
    (set-face-foreground 'gnus-summary-selected-face "#def")
    (set-face-foreground 'gnus-summary-high-ancient-face "Gray70")
    (set-face-foreground 'gnus-summary-high-read-face "Gray70")
    (set-face-foreground 'gnus-summary-normal-ancient-face "Gray70")
    (set-face-foreground 'gnus-summary-normal-read-face "Gray70")
    (set-face-foreground 'gnus-summary-low-read-face "Gray70")

    (set-face-foreground 'gnus-summary-low-undownloaded-face "Gray50")

    (set-face-foreground 'gnus-summary-high-undownloaded-face "Black")
    (set-face-attribute 'gnus-summary-high-undownloaded-face nil :weight 'bold)

    (set-face-foreground 'gnus-summary-normal-unread-face "#abc")
    (set-face-attribute 'gnus-summary-normal-unread-face nil :weight 'normal)
    (set-face-foreground 'message-header-other-face "#abc")

    (mapc
     #'(lambda (face)
         (set-face-foreground face
                              (face-foreground 'message-header-other-face))
         (set-face-attribute face nil :weight 'normal))
     '(message-header-to-face message-header-cc-face
                              message-header-subject-face
                              gnus-header-newsgroups-face))
    (set-face-foreground 'message-separator-face (face-background 'default))
    (set-face-attribute 'message-separator-face nil :weight 'normal)
    (set-face-attribute 'message-separator-face nil :height 0.6)
    (when (fboundp 'set-face-attribute)
      (mapc
       (lambda (face)
         (set-face-attribute face nil :weight 'normal))
       '(gnus-group-mail-1-face
         gnus-group-mail-2-face gnus-group-mail-3-face gnus-group-news-1-face
         gnus-group-news-2-face gnus-group-news-3-face gnus-group-news-4-face))



      (setq gnus-cite-face-list
            '(gnus-cite-face-1 gnus-cite-face-2 gnus-cite-face-3
                               gnus-cite-face-4 gnus-cite-face-5
                               gnus-cite-face-6 gnus-cite-face-7
                               gnus-cite-face-8 gnus-cite-face-9
                               gnus-cite-face-10 gnus-cite-face-11)))))

;;;; Other Programs ;;;;

;; W3M ;;
(setq mm-inline-text-html-renderer 'mm-inline-text-html-render-with-w3m)

(setq gnus-summary-thread-gathering-function
      'gnus-gather-threads-by-subject-and-date)


;; This variable and the following bits are a bit of a trick.  Sometimes
;; I'll have a buffer open (a document, a mail message, whatever) and I'll want
;; to refer to what someone said in a previous message as I write.  Previously
;; this involved jumping to gnus, finding the article, splitting the window and
;; finding what I was originally editing.
;;
;; This advice makes things work a bit differently: I split the window and can
;; navigate to the article through gnus without my window configuration being
;; messed up.  The logic is that if I have a window containing a non-gnus
;; buffer, gnus won't stomp on the window configuration.
;;

(setq gnus-use-full-window nil)

(defadvice gnus-configure-windows (around single-window-maybe activate)
  (cond ((and (member setting '(article summary))
              (some (lambda (buffer)
                      (or (not (member buffer (gnus-buffers)))
                          (with-current-buffer buffer
                            (eq major-mode 'message-mode))))
                    (mapcar 'window-buffer (window-list))))
         (save-window-excursion
           ad-do-it)
         (ecase setting
           (article (switch-to-buffer gnus-article-buffer))
           (summary (switch-to-buffer gnus-summary-buffer))))
        (t ad-do-it)))

(add-hook 'gnus-summary-exit-hook
          (lambda ()
            (when (every (lambda (buffer) (member buffer (gnus-buffers)))
                         (mapcar 'window-buffer (window-list)))
              (delete-other-windows)))
          t nil)

(setq gnus-group-line-format "%M%S%p%P%5uN: %(%ug%)%l\n")
(puthash "nnimap+gimli:INBOX" "work-inbox" gnus-group-display-names)


;; Don't thread nnir!
(add-hook 'gnus-summary-generate-hook
          (lambda ()
            (when (eq (car gnus-current-select-method) 'nnir)
              (set (make-local-variable 'gnus-show-threads)
                   nil))))

(setq gnus-use-cache nil)


;; This should always be at the end
(when (boundp 'dotgnus-loaded-hook)
  (run-hooks 'dotgnus-loaded-hook))
