;;; gnus-topic.el --- a folding minor mode for Gnus group buffers
-;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
-;; Free Software Foundation, Inc.
+
+;; Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+;; 2004, 2005 Free Software Foundation, Inc.
;; Author: Ilja Weis <kult@uni-paderborn.de>
;; Lars Magne Ingebrigtsen <larsi@gnus.org>
;; 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.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;; Commentary:
%A Number of unread articles in the groups in the topic and its subtopics.
General format specifiers can also be used.
-See (gnus)Formatting Variables."
+See Info node `(gnus)Formatting Variables'."
:link '(custom-manual "(gnus)Formatting Variables")
:type 'string
:group 'gnus-topic)
(defun gnus-group-topic-name ()
"The name of the topic on the current line."
- (let ((topic (get-text-property (gnus-point-at-bol) 'gnus-topic)))
+ (let ((topic (get-text-property (point-at-bol) 'gnus-topic)))
(and topic (symbol-name topic))))
(defun gnus-group-topic-level ()
"The level of the topic on the current line."
- (get-text-property (gnus-point-at-bol) 'gnus-topic-level))
+ (get-text-property (point-at-bol) 'gnus-topic-level))
(defun gnus-group-topic-unread ()
"The number of unread articles in topic on the current line."
- (get-text-property (gnus-point-at-bol) 'gnus-topic-unread))
+ (get-text-property (point-at-bol) 'gnus-topic-unread))
(defun gnus-topic-unread (topic)
"Return the number of unread articles in TOPIC."
(defun gnus-topic-visible-p ()
"Return non-nil if the current topic is visible."
- (get-text-property (gnus-point-at-bol) 'gnus-topic-visible))
+ (get-text-property (point-at-bol) 'gnus-topic-visible))
(defun gnus-topic-articles-in-topic (entries)
(let ((total 0)
(list (completing-read "Go to topic: "
(mapcar 'list (gnus-topic-list))
nil t)))
- (dolist (topic (gnus-current-topics topic))
- (gnus-topic-goto-topic topic)
- (gnus-topic-fold t))
+ (let ((buffer-read-only nil))
+ (dolist (topic (gnus-current-topics topic))
+ (unless (gnus-topic-goto-topic topic)
+ (gnus-topic-goto-missing-topic topic)
+ (gnus-topic-display-missing-topic topic))))
(gnus-topic-goto-topic topic))
(defun gnus-current-topic ()
(defun gnus-group-active-topic-p ()
"Say whether the current topic comes from the active topics."
- (save-excursion
- (beginning-of-line)
- (get-text-property (point) 'gnus-active)))
+ (get-text-property (point-at-bol) 'gnus-active))
(defun gnus-topic-find-groups (topic &optional level all lowest recursive)
"Return entries for all visible groups in TOPIC.
;; We go through the newsrc to look for matches.
(while groups
(when (setq group (pop groups))
- (setq entry (gnus-gethash group gnus-newsrc-hashtb)
+ (setq entry (gnus-group-entry group)
info (nth 2 entry)
params (gnus-info-params info)
active (gnus-active group)
"Compute the group parameters for GROUP taking into account inheritance from topics."
(let ((params-list (copy-sequence (gnus-group-get-parameter group))))
(save-excursion
- (gnus-group-goto-group group)
(nconc params-list
- (gnus-topic-hierarchical-parameters (gnus-current-topic))))))
+ (gnus-topic-hierarchical-parameters
+ ;; First we try to go to the group within the group
+ ;; buffer and find the topic for the group that way.
+ ;; This hopefully copes well with groups that are in
+ ;; more than one topic. Failing that (i.e. when the
+ ;; group isn't visible in the group buffer) we find a
+ ;; topic for the group via gnus-group-topic.
+ (or (and (gnus-group-goto-group group)
+ (gnus-current-topic))
+ (gnus-group-topic group)))))))
(defun gnus-topic-hierarchical-parameters (topic)
"Return a topic list computed for TOPIC."
- (let ((topics (gnus-current-topics topic))
- params-list param out params)
- (while topics
- (push (gnus-topic-parameters (pop topics)) params-list))
+ (let ((params-list (nreverse (mapcar 'gnus-topic-parameters
+ (gnus-current-topics topic))))
+ param out params)
;; We probably have lots of nil elements here, so
;; we remove them. Probably faster than doing this "properly".
(setq params-list (delq nil params-list))
(and gnus-group-listed-groups
(copy-sequence gnus-group-listed-groups))))
+ (gnus-update-format-specifications nil 'topic)
+
(when (or (not gnus-topic-alist)
(not gnus-topology-checked-p))
(gnus-topic-check-topology))
(unless gnus-killed-hashtb
(gnus-make-hashtable-from-killed))
(gnus-group-prepare-flat-list-dead
- (gnus-delete-if (lambda (group)
- (or (gnus-gethash group gnus-newsrc-hashtb)
+ (gnus-remove-if (lambda (group)
+ (or (gnus-group-entry group)
(gnus-gethash group gnus-killed-hashtb)))
not-in-list)
gnus-level-killed ?K regexp)))
(unfound t)
entry)
;; Try to jump to a visible group.
- (while (and g (not (gnus-group-goto-group (car g) t)))
+ (while (and g
+ (not (gnus-group-goto-group (car g) t)))
(pop g))
;; It wasn't visible, so we try to see where to insert it.
(when (not g)
(when (and unfound
topic
(not (gnus-topic-goto-missing-topic topic)))
- (let* ((top (gnus-topic-find-topology topic))
- (children (cddr top))
- (type (cadr top))
- (unread 0)
- (entries (gnus-topic-find-groups
- (car type) (car gnus-group-list-mode)
- (cdr gnus-group-list-mode))))
- (while children
- (incf unread (gnus-topic-unread (caar (pop children)))))
- (while (setq entry (pop entries))
- (when (numberp (car entry))
- (incf unread (car entry))))
- (gnus-topic-insert-topic-line
- topic t t (car (gnus-topic-find-topology topic)) nil unread))))))
+ (gnus-topic-display-missing-topic topic)))))
+
+(defun gnus-topic-display-missing-topic (topic)
+ "Insert topic lines recursively for missing topics."
+ (let ((parent (gnus-topic-find-topology
+ (gnus-topic-parent-topic topic))))
+ (when (and parent
+ (not (gnus-topic-goto-missing-topic (caadr parent))))
+ (gnus-topic-display-missing-topic (caadr parent))))
+ (gnus-topic-goto-missing-topic topic)
+ (let* ((top (gnus-topic-find-topology topic))
+ (children (cddr top))
+ (type (cadr top))
+ (unread 0)
+ (entries (gnus-topic-find-groups
+ (car type) (car gnus-group-list-mode)
+ (cdr gnus-group-list-mode)))
+ entry)
+ (while children
+ (incf unread (gnus-topic-unread (caar (pop children)))))
+ (while (setq entry (pop entries))
+ (when (numberp (car entry))
+ (incf unread (car entry))))
+ (gnus-topic-insert-topic-line
+ topic t t (car (gnus-topic-find-topology topic)) nil unread)))
(defun gnus-topic-goto-missing-topic (topic)
(if (gnus-topic-goto-topic topic)
(pop topics)))
;; Go through all living groups and make sure that
;; they belong to some topic.
- (let* ((tgroups (apply 'append (mapcar (lambda (entry) (cdr entry))
- gnus-topic-alist)))
+ (let* ((tgroups (apply 'append (mapcar 'cdr gnus-topic-alist)))
(entry (last (assoc (caar gnus-topic-topology) gnus-topic-alist)))
(newsrc (cdr gnus-newsrc-alist))
group)
(while (setq topic (pop alist))
(while (cdr topic)
(if (and (cadr topic)
- (gnus-gethash (cadr topic) gnus-newsrc-hashtb))
+ (gnus-group-entry (cadr topic)))
(setq topic (cdr topic))
(setcdr topic (cddr topic)))))))
(let ((topic-name (pop topic))
group filtered-topic)
(while (setq group (pop topic))
- (when (and (or (gnus-gethash group gnus-active-hashtb)
+ (when (and (or (gnus-active group)
(gnus-info-method (gnus-get-info group)))
(not (gnus-gethash group gnus-killed-hashtb)))
(push group filtered-topic)))
? ))
(yanked (list group))
alist talist end)
- ;; Then we enter the yanked groups into the topics they belong
- ;; to.
+ ;; Then we enter the yanked groups into the topics
+ ;; they belong to.
(when (setq alist (assoc (save-excursion
(forward-line -1)
(or
'("Topics"
["Toggle topics" gnus-topic-mode t]
("Groups"
- ["Copy" gnus-topic-copy-group t]
- ["Move" gnus-topic-move-group t]
+ ["Copy..." gnus-topic-copy-group t]
+ ["Move..." gnus-topic-move-group t]
["Remove" gnus-topic-remove-group t]
- ["Copy matching" gnus-topic-copy-matching t]
- ["Move matching" gnus-topic-move-matching t])
+ ["Copy matching..." gnus-topic-copy-matching t]
+ ["Move matching..." gnus-topic-move-matching t])
("Topics"
- ["Goto" gnus-topic-jump-to-topic t]
+ ["Goto..." gnus-topic-jump-to-topic t]
["Show" gnus-topic-show-topic t]
["Hide" gnus-topic-hide-topic t]
["Delete" gnus-topic-delete t]
- ["Rename" gnus-topic-rename t]
- ["Create" gnus-topic-create-topic t]
+ ["Rename..." gnus-topic-rename t]
+ ["Create..." gnus-topic-create-topic t]
["Mark" gnus-topic-mark-topic t]
["Indent" gnus-topic-indent t]
["Sort" gnus-topic-sort-topics t]
(when (gnus-visual-p 'topic-menu 'menu)
(gnus-topic-make-menu-bar))
(gnus-set-format 'topic t)
- (gnus-add-minor-mode 'gnus-topic-mode " Topic"
- gnus-topic-mode-map nil (lambda (&rest junk)
- (interactive)
- (gnus-topic-mode nil t)))
+ (add-minor-mode 'gnus-topic-mode " Topic" gnus-topic-mode-map)
(add-hook 'gnus-group-catchup-group-hook 'gnus-topic-update-topic)
(set (make-local-variable 'gnus-group-prepare-function)
'gnus-group-prepare-topics)
'gnus-group-sort-topic)
(setq gnus-group-change-level-function 'gnus-topic-change-level)
(setq gnus-goto-missing-group-function 'gnus-topic-goto-missing-group)
- (make-local-hook 'gnus-check-bogus-groups-hook)
+ (gnus-make-local-hook 'gnus-check-bogus-groups-hook)
(add-hook 'gnus-check-bogus-groups-hook 'gnus-topic-clean-alist
nil 'local)
(setq gnus-topology-checked-p nil)
If performed over a topic line, toggle folding the topic."
(interactive "P")
+ (when (and (eobp) (not (gnus-group-group-name)))
+ (forward-line -1))
(if (gnus-group-topic-p)
(let ((gnus-group-list-mode
(if all (cons (if (numberp all) all 7) t) gnus-group-list-mode)))
(gnus-message 5 "Expiring groups in %s..." topic)
(let ((gnus-group-marked
(mapcar (lambda (entry) (car (nth 2 entry)))
- (gnus-topic-find-groups topic gnus-level-killed t))))
+ (gnus-topic-find-groups topic gnus-level-killed t
+ nil t))))
(gnus-group-expire-articles nil))
(gnus-message 5 "Expiring groups in %s...done" topic))))
(save-excursion
(let* ((groups
(mapcar (lambda (entry) (car (nth 2 entry)))
- (gnus-topic-find-groups topic gnus-level-killed t)))
+ (gnus-topic-find-groups topic gnus-level-killed t
+ nil t)))
(buffer-read-only nil)
(gnus-group-marked groups))
(gnus-group-catchup-current)
(let ((use-marked (and (not n) (not (gnus-region-active-p))
gnus-group-marked t))
(groups (gnus-group-process-prefix n)))
- (mapcar
+ (mapc
(lambda (group)
(gnus-group-remove-mark group use-marked)
(let ((topicl (assoc (gnus-current-topic) gnus-topic-alist))
(setcar (cdr (cadr topic)) 'visible)
(gnus-group-list-groups)))))
-(defun gnus-topic-mark-topic (topic &optional unmark recursive)
+(defun gnus-topic-mark-topic (topic &optional unmark non-recursive)
"Mark all groups in the TOPIC with the process mark.
-If RECURSIVE is t, mark its subtopics too."
+If NON-RECURSIVE (which is the prefix) is t, don't mark its subtopics."
(interactive (list (gnus-group-topic-name)
nil
(and current-prefix-arg t)))
(call-interactively 'gnus-group-mark-group)
(save-excursion
(let ((groups (gnus-topic-find-groups topic gnus-level-killed t nil
- recursive)))
+ (not non-recursive))))
(while groups
(funcall (if unmark 'gnus-group-remove-mark 'gnus-group-set-mark)
(gnus-info-group (nth 2 (pop groups)))))))))
-(defun gnus-topic-unmark-topic (topic &optional dummy recursive)
+(defun gnus-topic-unmark-topic (topic &optional dummy non-recursive)
"Remove the process mark from all groups in the TOPIC.
-If RECURSIVE is t, unmark its subtopics too."
+If NON-RECURSIVE (which is the prefix) is t, don't unmark its subtopics."
(interactive (list (gnus-group-topic-name)
nil
(and current-prefix-arg t)))
(if (not topic)
(call-interactively 'gnus-group-unmark-group)
- (gnus-topic-mark-topic topic t recursive)))
+ (gnus-topic-mark-topic topic t non-recursive)))
(defun gnus-topic-get-new-news-this-topic (&optional n)
"Check for new news in the current topic."
(gnus-topic-kill-group)
(push (cdar gnus-topic-killed-topics) gnus-topic-alist)
(gnus-topic-create-topic
- topic parent nil (cdaar gnus-topic-killed-topics))
+ topic parent nil (cdar (car gnus-topic-killed-topics)))
(pop gnus-topic-killed-topics)
(or (gnus-topic-goto-topic topic)
(gnus-topic-goto-topic parent))))))
(push (cdar gnus-topic-killed-topics) gnus-topic-alist)
(gnus-topic-create-topic
topic grandparent (gnus-topic-next-topic parent)
- (cdaar gnus-topic-killed-topics))
+ (cdar (car gnus-topic-killed-topics)))
(pop gnus-topic-killed-topics)
(gnus-topic-goto-topic topic))))
top)
(defun gnus-topic-sort-topics (&optional topic reverse)
- "Sort topics in TOPIC alphabeticaly by topic name.
+ "Sort topics in TOPIC alphabetically by topic name.
If REVERSE, reverse the sorting order."
(interactive
(list (completing-read "Sort topics in : " gnus-topic-alist nil t
(if (gnus-topic-find-topology to current-top 0);; Don't care the level
(error "Can't move `%s' to its sub-level" current))
(gnus-topic-find-topology current nil nil 'delete)
- (while (cdr to-top)
- (setq to-top (cdr to-top)))
- (setcdr to-top (list current-top))
+ (setcdr (last to-top) (list current-top))
(gnus-topic-enter-dribble)
(gnus-group-list-groups)
(gnus-topic-goto-topic current)))
(provide 'gnus-topic)
+;;; arch-tag: bf176856-f30c-40f0-ae77-e41529a1134c
;;; gnus-topic.el ends here