Make non-full window usage work better on choosing the next group.
[gnus] / lisp / gnus-sum.el
index 840e7d5..5cda693 100644 (file)
@@ -1,7 +1,6 @@
 ;;; gnus-sum.el --- summary mode commands for Gnus
 
-;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-;;   2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2011 Free Software Foundation, Inc.
 
 ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
 ;; Keywords: news
@@ -60,6 +59,8 @@
 (autoload 'gnus-article-outlook-unwrap-lines "deuglify" nil t)
 (autoload 'gnus-article-outlook-repair-attribution "deuglify" nil t)
 (autoload 'gnus-article-outlook-rearrange-citation "deuglify" nil t)
+(autoload 'nnir-article-rsv "nnir" nil nil 'macro)
+(autoload 'nnir-article-group "nnir" nil nil 'macro)
 
 (defcustom gnus-kill-summary-on-exit t
   "*If non-nil, kill the summary buffer when you exit from it.
@@ -358,7 +359,7 @@ first subject), `unread' (place point on the subject line of the first
 unread article), `best' (place point on the subject line of the
 higest-scored article), `unseen' (place point on the subject line of
 the first unseen article), `unseen-or-unread' (place point on the subject
-line of the first unseen article or, if all article have been seen, on the
+line of the first unseen article or, if all articles have been seen, on the
 subject line of the first unread article), or a function to be called to
 place point on some subject line."
   :version "24.1"
@@ -1361,13 +1362,13 @@ the normal Gnus MIME machinery."
     (?c (or (mail-header-chars gnus-tmp-header) 0) ?d)
     (?k (gnus-summary-line-message-size gnus-tmp-header) ?s)
     (?L gnus-tmp-lines ?s)
-    (?Z (or ,(macroexpand-all
+    (?Z (or ,(gnus-macroexpand-all
              '(nnir-article-rsv (mail-header-number gnus-tmp-header)))
            0) ?d)
-    (?G (or ,(macroexpand-all
+    (?G (or ,(gnus-macroexpand-all
              '(nnir-article-group (mail-header-number gnus-tmp-header)))
            "") ?s)
-    (?g (or ,(macroexpand-all
+    (?g (or ,(gnus-macroexpand-all
              '(gnus-group-short-name
                (nnir-article-group (mail-header-number gnus-tmp-header))))
            "") ?s)
@@ -3851,6 +3852,56 @@ This function is intended to be used in
          ((< c (* 1000 10000)) (format "%1.1fM" (/ c (* 1024.0 1024))))
          (t (format "%dM" (/ c (* 1024.0 1024)))))))
 
+(defcustom gnus-summary-user-date-format-alist
+  '(((gnus-seconds-today) . "Today, %H:%M")
+    ((+ 86400 (gnus-seconds-today)) . "Yesterday, %H:%M")
+    (604800 . "%A %H:%M")               ; That's one week
+    ((gnus-seconds-month) . "%A %d")
+    ((gnus-seconds-year) . "%B %d")
+    (t . "%b %d %Y"))                   ; This one is used when no other
+                                        ; does match
+  "Specifies date format depending on age of article.
+This is an alist of items (AGE . FORMAT).  AGE can be a number (of
+seconds) or a Lisp expression evaluating to a number.  When the age of
+the article is less than this number, then use `format-time-string'
+with the corresponding FORMAT for displaying the date of the article.
+If AGE is not a number or a Lisp expression evaluating to a
+non-number, then the corresponding FORMAT is used as a default value.
+
+Note that the list is processed from the beginning, so it should be
+sorted by ascending AGE.  Also note that items following the first
+non-number AGE will be ignored.
+
+You can use the functions `gnus-seconds-today', `gnus-seconds-month'
+and `gnus-seconds-year' in the AGE spec.  They return the number of
+seconds passed since the start of today, of this month, of this year,
+respectively."
+  :version "24.1"
+  :group 'gnus-summary-format
+  :type '(alist :key-type sexp :value-type string))
+(make-obsolete-variable 'gnus-user-date-format-alist
+                        'gnus-summary-user-date-format-alist "24.1")
+
+(defun gnus-user-date (messy-date)
+  "Format the messy-date according to `gnus-summary-user-date-format-alist'.
+Returns \"  ?  \" if there's bad input or if another error occurs.
+Input should look like this: \"Sun, 14 Oct 2001 13:34:39 +0200\"."
+  (condition-case ()
+      (let* ((messy-date (gnus-float-time (gnus-date-get-time messy-date)))
+            (now (gnus-float-time))
+            ;;If we don't find something suitable we'll use this one
+            (my-format "%b %d '%y"))
+       (let* ((difference (- now messy-date))
+              (templist gnus-summary-user-date-format-alist)
+              (top (eval (caar templist))))
+         (while (if (numberp top) (< top difference) (not top))
+           (progn
+             (setq templist (cdr templist))
+             (setq top (eval (caar templist)))))
+         (if (stringp (cdr (car templist)))
+             (setq my-format (cdr (car templist)))))
+       (format-time-string (eval my-format) (seconds-to-time messy-date)))
+    (error "  ?   ")))
 
 (defun gnus-summary-set-local-parameters (group)
   "Go through the local params of GROUP and set all variable specs in that list."
@@ -3938,11 +3989,9 @@ If NO-DISPLAY, don't generate a summary buffer."
              (gnus-group-jump-to-group group)
              (gnus-group-next-unread-group 1))
          (gnus-handle-ephemeral-exit quit-config)))
-      (let ((grpinfo (gnus-get-info group)))
-       (if (null (gnus-info-read grpinfo))
-           (gnus-message 3 "Group %s contains no messages"
-                         (gnus-group-decoded-name group))
-         (gnus-message 3 "Can't select group")))
+      (if (null (gnus-list-of-unread-articles group))
+         (gnus-message 3 "Group %s contains no messages" group)
+       (gnus-message 3 "Can't select group"))
       nil)
      ;; The user did a `C-g' while prompting for number of articles,
      ;; so we exit this group.
@@ -4018,6 +4067,7 @@ If NO-DISPLAY, don't generate a summary buffer."
        ;; gnus-summary-prepare-hook since kill processing may not
        ;; work with hidden articles.
        (gnus-summary-maybe-hide-threads)
+       (gnus-configure-windows 'summary)
        (when kill-buffer
          (gnus-kill-or-deaden-summary kill-buffer))
        (gnus-summary-auto-select-subject)
@@ -4027,7 +4077,6 @@ If NO-DISPLAY, don't generate a summary buffer."
                 gnus-newsgroup-unreads
                 gnus-auto-select-first)
            (progn
-             (gnus-configure-windows 'summary)
              (let ((art (gnus-summary-article-number)))
                (unless (and (not gnus-plugged)
                             (or (memq art gnus-newsgroup-undownloaded)
@@ -5543,7 +5592,8 @@ If SELECT-ARTICLES, only select those articles from GROUP."
             (mm-decode-coding-string group charset)
             (mm-decode-coding-string (gnus-status-message group) charset)))
 
-    (when gnus-agent
+    (when (and gnus-agent
+              (gnus-active group))
       (gnus-agent-possibly-alter-active group (gnus-active group) info)
 
       (setq gnus-summary-use-undownloaded-faces
@@ -5601,7 +5651,7 @@ If SELECT-ARTICLES, only select those articles from GROUP."
 
     (setq gnus-newsgroup-processable nil)
 
-    (gnus-update-read-articles group gnus-newsgroup-unreads)
+    (gnus-update-read-articles group gnus-newsgroup-unreads t)
 
     ;; Adjust and set lists of article marks.
     (when info
@@ -7170,16 +7220,6 @@ If FORCE (the prefix), also save the .newsrc file(s)."
        (when (eq mode 'gnus-summary-mode)
          (gnus-kill-buffer buf)))
 
-      ;; If we have several article buffers, we kill them at exit.
-      (unless gnus-single-article-buffer
-       (when (gnus-buffer-live-p gnus-article-buffer)
-         (with-current-buffer gnus-article-buffer
-           ;; Don't kill sticky article buffers
-           (unless (eq major-mode 'gnus-sticky-article-mode)
-             (gnus-kill-buffer gnus-article-buffer)
-             (setq gnus-article-current nil))))
-       (gnus-kill-buffer gnus-original-article-buffer))
-
       (setq gnus-current-select-method gnus-select-method)
       (set-buffer gnus-group-buffer)
       (if quit-config
@@ -7191,6 +7231,17 @@ If FORCE (the prefix), also save the .newsrc file(s)."
          (if win (set-window-point win (point))))
        (unless leave-hidden
          (gnus-configure-windows 'group 'force)))
+
+      ;; If we have several article buffers, we kill them at exit.
+      (unless gnus-single-article-buffer
+       (when (gnus-buffer-live-p gnus-article-buffer)
+         (with-current-buffer gnus-article-buffer
+           ;; Don't kill sticky article buffers
+           (unless (eq major-mode 'gnus-sticky-article-mode)
+             (gnus-kill-buffer gnus-article-buffer)
+             (setq gnus-article-current nil))))
+       (gnus-kill-buffer gnus-original-article-buffer))
+
       ;; Clear the current group name.
       (unless quit-config
        (setq gnus-newsgroup-name nil)))))
@@ -7219,6 +7270,8 @@ If FORCE (the prefix), also save the .newsrc file(s)."
        (gnus-kill-buffer gnus-article-buffer)
        (gnus-kill-buffer gnus-original-article-buffer)
        (setq gnus-article-current nil))
+      ;; Return to the group buffer.
+      (gnus-configure-windows 'group 'force)
       (if (not gnus-kill-summary-on-exit)
          (gnus-deaden-summary)
        (gnus-close-group group)
@@ -7230,8 +7283,6 @@ If FORCE (the prefix), also save the .newsrc file(s)."
       (gnus-async-prefetch-remove-group group)
       (when (get-buffer gnus-article-buffer)
        (bury-buffer gnus-article-buffer))
-      ;; Return to the group buffer.
-      (gnus-configure-windows 'group 'force)
       ;; Clear the current group name.
       (setq gnus-newsgroup-name nil)
       (unless (gnus-ephemeral-group-p group)
@@ -7685,9 +7736,6 @@ If BACKWARD, the previous article is selected instead of the next."
           (if (eq gnus-keep-same-level 'best)
               (gnus-summary-best-group gnus-newsgroup-name)
             (gnus-summary-search-group backward gnus-keep-same-level))))
-      ;; For some reason, the group window gets selected.  We change
-      ;; it back.
-      (select-window (get-buffer-window (current-buffer)))
       ;; Select next unread newsgroup automagically.
       (cond
        ((or (not gnus-auto-select-next)
@@ -8866,30 +8914,27 @@ fetch what's specified by the `gnus-refer-thread-limit'
 variable."
   (interactive "P")
   (gnus-warp-to-article)
-  (let ((id (mail-header-id (gnus-summary-article-header)))
-       (gnus-inhibit-demon t)
-       (gnus-agent nil)
-       (gnus-summary-ignore-duplicates t)
-       (gnus-read-all-available-headers t)
-       (limit (if limit (prefix-numeric-value limit)
-                gnus-refer-thread-limit)))
+  (let* ((header (gnus-summary-article-header))
+        (id (mail-header-id header))
+        (gnus-inhibit-demon t)
+        (gnus-summary-ignore-duplicates t)
+        (gnus-read-all-available-headers t)
+        (limit (if limit (prefix-numeric-value limit)
+                 gnus-refer-thread-limit)))
     (setq gnus-newsgroup-headers
          (gnus-merge
           'list gnus-newsgroup-headers
           (if (gnus-check-backend-function
                'request-thread gnus-newsgroup-name)
-              (gnus-request-thread id)
+              (gnus-request-thread header)
             (let* ((last (if (numberp limit)
-                             (min (+ (mail-header-number
-                                      (gnus-summary-article-header))
+                             (min (+ (mail-header-number header)
                                      limit)
                                   gnus-newsgroup-highest)
                            gnus-newsgroup-highest))
                    (subject (gnus-simplify-subject
-                             (mail-header-subject
-                              (gnus-summary-article-header))))
-                   (refs (split-string (or (mail-header-references
-                                            (gnus-summary-article-header))
+                             (mail-header-subject header)))
+                   (refs (split-string (or (mail-header-references header)
                                            "")))
                    (gnus-parse-headers-hook
                     (lambda () (goto-char (point-min))
@@ -8980,8 +9025,11 @@ variable."
 
 (defun gnus-summary-enter-digest-group (&optional force)
   "Enter an nndoc group based on the current article.
-If FORCE, force a digest interpretation.  If not, try
-to guess what the document format is."
+If FORCE, force a digest interpretation.  If not, try to guess
+what the document format is.
+
+To control what happens when you exit the group, see the
+`gnus-auto-select-on-ephemeral-exit' variable."
   (interactive "P")
   (let ((conf gnus-current-window-configuration))
     (save-window-excursion
@@ -9473,6 +9521,9 @@ C-u g', show the raw article."
    ((or (equal arg '(16))
        (eq arg t))
     ;; C-u C-u g
+    (let ((gnus-inhibit-article-treatments t))
+      (gnus-summary-select-article nil 'force)))
+   (t
     ;; We have to require this here to make sure that the following
     ;; dynamic binding isn't shadowed by autoloading.
     (require 'gnus-async)
@@ -9490,9 +9541,6 @@ C-u g', show the raw article."
          ;; Set it to nil for safety reason.
          (setq gnus-article-mime-handle-alist nil)
          (setq gnus-article-mime-handles nil)))
-      (gnus-summary-select-article nil 'force)))
-   (t
-    (let ((gnus-inhibit-article-treatments t))
       (gnus-summary-select-article nil 'force))))
   (gnus-summary-goto-subject gnus-current-article)
   (gnus-summary-position-point))
@@ -9837,7 +9885,8 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
            (unless (member to-group to-groups)
              (push to-group to-groups))
 
-           (unless (memq article gnus-newsgroup-unreads)
+           (when (and (not (memq article gnus-newsgroup-unreads))
+                      (cdr art-group))
              (push 'read to-marks)
              (gnus-info-set-read
               info (gnus-add-to-range (gnus-info-read info)
@@ -9854,14 +9903,16 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
 
              ;; Enter the article into the cache in the new group,
              ;; if that is required.
-             (when gnus-use-cache
+             (when (and to-article
+                        gnus-use-cache)
                (gnus-cache-possibly-enter-article
                 to-group to-article
                 (memq article gnus-newsgroup-marked)
                 (memq article gnus-newsgroup-dormant)
                 (memq article gnus-newsgroup-unreads)))
 
-             (when gnus-preserve-marks
+             (when (and gnus-preserve-marks
+                        to-article)
                ;; Copy any marks over to the new group.
                (when (and (equal to-group gnus-newsgroup-name)
                           (not (memq article gnus-newsgroup-unreads)))
@@ -9932,7 +9983,7 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
 
         ;;;!!!Why is this necessary?
        (set-buffer gnus-summary-buffer)
-       
+
        (when (eq action 'move)
          (save-excursion
            (gnus-summary-goto-subject article)
@@ -9953,7 +10004,7 @@ ACTION can be either `move' (the default), `crosspost' or `copy'."
 (defun gnus-summary-push-marks-to-backend (article)
   (let ((set nil)
        (marks gnus-article-mark-lists))
-    (when (memq article gnus-newsgroup-unreads)
+    (unless (memq article gnus-newsgroup-unreads)
       (push 'read set))
     (while marks
       (when (and (eq (gnus-article-mark-to-type (cdar marks)) 'list)
@@ -10002,7 +10053,7 @@ current group into whatever groups they are destined to.  In the
 latter case, they will be copied into the relevant groups."
   (interactive
    (list current-prefix-arg
-        (let* ((methods (gnus-methods-using 'respool))
+        (let* ((methods (mapcar #'car (gnus-methods-using 'respool)))
                (methname
                 (symbol-name (or gnus-summary-respool-default-method
                                  (car (gnus-find-method-for-group
@@ -12037,9 +12088,9 @@ If REVERSE, save parts that do not match TYPE."
                          gnus-summary-save-parts-default-mime)
                      'gnus-summary-save-parts-type-history)
         (setq gnus-summary-save-parts-last-directory
-              (read-file-name "Save to directory: "
-                              gnus-summary-save-parts-last-directory
-                              nil t))
+              (read-directory-name "Save to directory: "
+                                    gnus-summary-save-parts-last-directory
+                                    nil t))
         current-prefix-arg))
   (gnus-summary-iterate n
     (let ((gnus-display-mime-function nil)