;;; gnus-group.el --- group mode commands for Gnus
-;; Copyright (C) 1996-2011
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1996-2011 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: news
"M" gnus-group-list-all-matching
"l" gnus-group-list-level
"c" gnus-group-list-cached
- "?" gnus-group-list-dormant)
+ "?" gnus-group-list-dormant
+ "!" gnus-group-list-ticked)
(gnus-define-keys (gnus-group-list-limit-map "/" gnus-group-list-map)
"k" gnus-group-list-limit
["List all groups matching..." gnus-group-list-all-matching t]
["List active file" gnus-group-list-active t]
["List groups with cached" gnus-group-list-cached t]
- ["List groups with dormant" gnus-group-list-dormant t])
+ ["List groups with dormant" gnus-group-list-dormant t]
+ ["List groups with ticked" gnus-group-list-ticked t])
("Sort"
["Default sort" gnus-group-sort-groups t]
["Sort by method" gnus-group-sort-groups-by-method t]
'((gnus-group-post-news "mail/compose")
;; Some useful agent icons? I don't use the agent so agent users should
;; suggest useful commands:
- (gnus-agent-toggle-plugged "disconnect" t
+ (gnus-agent-toggle-plugged "unplugged" t
:help "Gnus is currently unplugged. Click to work online."
:visible (and gnus-agent (not gnus-plugged)))
- (gnus-agent-toggle-plugged "connect" t
+ (gnus-agent-toggle-plugged "plugged" t
:help "Gnus is currently plugged. Click to work offline."
:visible (and gnus-agent gnus-plugged))
;; FIXME: gnus-agent-toggle-plugged (in gnus-agent-group-make-menu-bar)
(gnus-group-mode)))
(defun gnus-group-name-charset (method group)
- (if (null method)
- (setq method (gnus-find-method-for-group group)))
- (let ((item (or (assoc method gnus-group-name-charset-method-alist)
- (and (consp method)
- (assoc (list (car method) (cadr method))
- gnus-group-name-charset-method-alist))))
- (alist gnus-group-name-charset-group-alist)
- result)
- (if item
- (cdr item)
- (while (setq item (pop alist))
- (if (string-match (car item) group)
- (setq alist nil
- result (cdr item))))
- result)))
+ (unless method
+ (setq method (gnus-find-method-for-group group)))
+ (when (stringp method)
+ (setq method (gnus-server-to-method method)))
+ (if (eq (car method) 'nnimap)
+ ;; IMAP groups should not be encoded, since they do the encoding
+ ;; in utf7 in the protocol.
+ nil
+ (let ((item (or (assoc method gnus-group-name-charset-method-alist)
+ (and (consp method)
+ (assoc (list (car method) (cadr method))
+ gnus-group-name-charset-method-alist))))
+ (alist gnus-group-name-charset-group-alist)
+ result)
+ (if item
+ (cdr item)
+ (while (setq item (pop alist))
+ (if (string-match (car item) group)
+ (setq alist nil
+ result (cdr item))))
+ result))))
(defun gnus-group-name-decode (string charset)
;; Fixme: Don't decode in unibyte mode.
(gnus-dribble-enter
(concat "(gnus-group-set-info '"
(gnus-prin1-to-string (nth 2 entry))
- ")")))
+ ")")
+ (concat "^(gnus-group-set-info '(\"" (regexp-quote group) "\"")))
(setq gnus-group-indentation (gnus-group-group-indentation))
(gnus-delete-line)
(gnus-group-insert-group-line-info group)
(gnus-activate-group group)
(gnus-get-unread-articles-in-group (gnus-get-info group)
(gnus-active group))
- (gnus-group-update-group group t))
+ (gnus-group-update-group group))
-(defun gnus-group-update-group (group &optional visible-only)
+(defun gnus-group-update-group (group &optional visible-only
+ info-unchanged)
"Update all lines where GROUP appear.
If VISIBLE-ONLY is non-nil, the group won't be displayed if it isn't
-already."
+already. If INFO-UNCHANGED is non-nil, dribble buffer is not updated."
(with-current-buffer gnus-group-buffer
(save-excursion
;; The buffer may be narrowed.
(let ((ident (gnus-intern-safe group gnus-active-hashtb))
(loc (point-min))
found buffer-read-only)
- ;; Enter the current status into the dribble buffer.
- (let ((entry (gnus-group-entry group)))
- (when (and entry
- (not (gnus-ephemeral-group-p group)))
- (gnus-dribble-enter
- (concat "(gnus-group-set-info '"
- (gnus-prin1-to-string (nth 2 entry))
- ")"))))
+ (unless info-unchanged
+ ;; Enter the current status into the dribble buffer.
+ (let ((entry (gnus-group-entry group)))
+ (when (and entry
+ (not (gnus-ephemeral-group-p group)))
+ (gnus-dribble-enter
+ (concat "(gnus-group-set-info '"
+ (gnus-prin1-to-string (nth 2 entry))
+ ")")
+ (concat "^(gnus-group-set-info '(\""
+ (regexp-quote group) "\"")))))
;; Find all group instances. If topics are in use, each group
;; may be listed in more than once.
(while (setq loc (text-property-any
(gnus-group-completing-read)
(gnus-read-method "From method")))
;; Transform the select method into a unique server.
+ (unless (gnus-alive-p)
+ (gnus-no-server))
(when (stringp method)
(setq method (gnus-server-to-method method)))
(setq method
`(-1 nil (,group
,gnus-level-default-subscribed nil nil ,method
,(cons
- (if quit-config
- (cons 'quit-config quit-config)
+ (cond
+ (quit-config
+ (cons 'quit-config quit-config))
+ ((assq gnus-current-window-configuration
+ gnus-buffer-configuration)
(cons 'quit-config
(cons gnus-summary-buffer
- gnus-current-window-configuration)))
+ gnus-current-window-configuration))))
parameters)))
gnus-newsrc-hashtb)
(push method gnus-ephemeral-servers)
gnus-fetch-old-ephemeral-headers))
(gnus-group-read-group (or number t) t group select-articles))
group)
- ;;(error nil)
(quit
- (message "Quit reading the ephemeral group")
+ (if debug-on-quit
+ (debug "Quit")
+ (message "Quit reading the ephemeral group"))
nil)))))
(defcustom gnus-gmane-group-download-format
(gnus-read-ephemeral-gmane-group group start range)))
(defcustom gnus-bug-group-download-format-alist
- '((emacs . "http://debbugs.gnu.org/%s;mbox=yes")
+ '((emacs . "http://debbugs.gnu.org/%s;mboxstat=yes")
(debian
- . "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=%s&mbox=yes"))
+ . "http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=%s&mbox=yes;mboxmaint=yes"))
"Alist of symbols for bug trackers and the corresponding URL format string.
The URL format string must contain a single \"%s\", specifying
the bug number, and browsing the URL must return mbox output."
:group 'gnus-group-foreign
- :version "23.2" ;; No Gnus
+ ;; Added mboxmaint=yes. This gets the version with the messages as
+ ;; they went out, not as they came in.
+ ;; Eg bug-gnu-emacs is replaced by ###@debbugs.
+ :version "24.1"
:type '(repeat (cons (symbol) (string :tag "URL format string"))))
-(defun gnus-read-ephemeral-bug-group (number mbox-url)
+(defun gnus-read-ephemeral-bug-group (ids mbox-url &optional window-conf)
"Browse bug NUMBER as ephemeral group."
(interactive (list (read-string "Enter bug number: "
(thing-at-point 'word) nil)
;; FIXME: Add completing-read from
;; `gnus-emacs-bug-group-download-format' ...
(cdr (assoc 'emacs gnus-bug-group-download-format-alist))))
- (when (stringp number)
- (setq number (string-to-number number)))
- (let ((tmpfile (mm-make-temp-file "gnus-temp-group-")))
+ (when (stringp ids)
+ (setq ids (string-to-number ids)))
+ (unless (listp ids)
+ (setq ids (list ids)))
+ (let ((tmpfile (mm-make-temp-file "gnus-temp-group-"))
+ (coding-system-for-write 'binary)
+ (coding-system-for-read 'binary))
(with-temp-file tmpfile
- (url-insert-file-contents (format mbox-url number))
+ (dolist (id ids)
+ (url-insert-file-contents (format mbox-url id)))
(goto-char (point-min))
;; Add the debbugs address so that we can respond to reports easily.
(while (re-search-forward "^To: " nil t)
(end-of-line)
- (insert (format ", %s@%s" number
+ (insert (format ", %s@%s" (car ids)
(gnus-replace-in-string
(gnus-replace-in-string mbox-url "^http://" "")
"/.*$" ""))))
(gnus-group-read-ephemeral-group
"gnus-read-ephemeral-bug"
`(nndoc ,tmpfile
- (nndoc-article-type mbox))))
+ (nndoc-article-type mbox))
+ nil window-conf))
(delete-file tmpfile)))
(defun gnus-read-ephemeral-debian-bug-group (number)
number
(cdr (assoc 'debian gnus-bug-group-download-format-alist))))
-(defun gnus-read-ephemeral-emacs-bug-group (number)
- "Browse Emacs bug NUMBER as ephemeral group."
- (interactive (list (read-string "Enter bug number: "
- (thing-at-point 'word) nil)))
+(defvar debbugs-gnu-bug-number) ; debbugs-gnu
+
+(defun gnus-read-ephemeral-emacs-bug-group (ids &optional window-conf)
+ "Browse Emacs bugs IDS as an ephemeral group."
+ (interactive (list (string-to-number
+ (read-string "Enter bug number: "
+ (thing-at-point 'word) nil))))
+ (unless (listp ids)
+ (setq ids (list ids)))
(gnus-read-ephemeral-bug-group
- number
- (cdr (assoc 'emacs gnus-bug-group-download-format-alist))))
+ ids
+ (cdr (assoc 'emacs gnus-bug-group-download-format-alist))
+ window-conf)
+ (when (fboundp 'debbugs-gnu-summary-mode)
+ (with-current-buffer (window-buffer (selected-window))
+ (debbugs-gnu-summary-mode 1)
+ (set (make-local-variable 'debbugs-gnu-bug-number) (car ids)))))
(defun gnus-group-jump-to-group (group &optional prompt)
"Jump to newsgroup GROUP.
`gnus-group-jump-to-group-prompt'."
(interactive
(list (gnus-group-completing-read
- nil nil (gnus-read-active-file-p)
+ nil nil nil
(if current-prefix-arg
(cdr (assq current-prefix-arg gnus-group-jump-to-group-prompt))
(or (and (stringp gnus-group-jump-to-group-prompt)
(unless (gnus-ephemeral-group-p name)
(gnus-dribble-enter
(concat "(gnus-group-set-info '"
- (gnus-prin1-to-string (cdr info)) ")")))
+ (gnus-prin1-to-string (cdr info)) ")")
+ (concat "^(gnus-group-set-info '(\"" (regexp-quote name) "\"")))
;; Insert the line.
(gnus-group-insert-group-line-info nname)
(forward-line -1)
directory will be used as a newsgroup. The directory should contain
mail messages or news articles in files that have numeric names."
(interactive
- (list (read-file-name "Create group from directory: ")))
+ (list (read-directory-name "Create group from directory: ")))
(unless (file-exists-p dir)
(error "No such directory"))
(unless (file-directory-p dir)
"Clear all marks and read ranges from the current group.
Obeys the process/prefix convention."
(interactive "P")
- (gnus-group-iterate arg
- (lambda (group)
- (let (info)
- (gnus-info-clear-data (setq info (gnus-get-info group)))
- (gnus-get-unread-articles-in-group info (gnus-active group) t)
- (when (gnus-group-goto-group group)
- (gnus-group-update-group-line))))))
+ (when (gnus-y-or-n-p "Really clear data? ")
+ (gnus-group-iterate arg
+ (lambda (group)
+ (let (info)
+ (gnus-info-clear-data (setq info (gnus-get-info group)))
+ (gnus-get-unread-articles-in-group info (gnus-active group) t)
+ (when (gnus-group-goto-group group)
+ (gnus-group-update-group-line)))))))
(defun gnus-group-clear-data-on-native-groups ()
"Clear all marks and read ranges from all native groups."
(gnus-add-marked-articles group 'tick nil nil 'force)
(gnus-add-marked-articles group 'dormant nil nil 'force))
;; Do auto-expirable marks if that's required.
- (when (gnus-group-auto-expirable-p group)
+ (when (and (gnus-group-auto-expirable-p group)
+ (not (gnus-group-read-only-p group)))
(gnus-range-map
(lambda (article)
(gnus-add-marked-articles group 'expire (list article))
(when gnus-agent
(gnus-agent-save-group-info
method (gnus-group-real-name group) active))
- (gnus-group-update-group group))
+ (gnus-group-update-group group nil t))
(if (eq (gnus-server-status (gnus-find-method-for-group group))
'denied)
- (gnus-error 3 "Server denied access")
+ (gnus-error 3 "Server previously determined to be down; not retrying")
(gnus-error 3 "%s error: %s" group (gnus-status-message group)))))
(when beg
(goto-char beg))
(defun gnus-group-set-params-info (group params)
(gnus-group-set-info params group 'params))
+;; Ad-hoc function for inserting data from a different newsrc.eld
+;; file. Use with caution, if at all.
+(defun gnus-import-other-newsrc-file (file)
+ (with-temp-buffer
+ (insert-file-contents file)
+ (let (form)
+ (while (ignore-errors
+ (setq form (read (current-buffer))))
+ (when (and (consp form)
+ (eq (cadr form) 'gnus-newsrc-alist))
+ (let ((infos (cadr (nth 2 form))))
+ (dolist (info infos)
+ (when (gnus-get-info (car info))
+ (gnus-set-info (car info) info)))))))))
+
(defun gnus-add-marked-articles (group type articles &optional info force)
;; Add ARTICLES of TYPE to the info of GROUP.
;; If INFO is non-nil, use that info. If FORCE is non-nil, don't
(goto-char (point-min))
(gnus-group-position-point))
+(defun gnus-group-list-ticked (level &optional lowest)
+ "List all groups with ticked articles.
+If the prefix LEVEL is non-nil, it should be a number that says which
+level to cut off listing groups.
+If LOWEST, don't list groups with level lower than LOWEST.
+
+This command may read the active file."
+ (interactive "P")
+ (when level
+ (setq level (prefix-numeric-value level)))
+ (when (or (not level) (>= level gnus-level-zombie))
+ (gnus-cache-open))
+ (funcall gnus-group-prepare-function
+ (or level gnus-level-subscribed)
+ #'(lambda (info)
+ (let ((marks (gnus-info-marks info)))
+ (assq 'tick marks)))
+ lowest
+ 'ignore)
+ (goto-char (point-min))
+ (gnus-group-position-point))
+
(defun gnus-group-listed-groups ()
"Return a list of listed groups."
(let (point groups)
(push n gnus-newsgroup-unselected))
(setq n (1+ n)))
(setq gnus-newsgroup-unselected
- (nreverse gnus-newsgroup-unselected)))))
+ (sort gnus-newsgroup-unselected '<)))))
(gnus-activate-group group)
(gnus-group-make-articles-read group (list article))
- (when (gnus-group-auto-expirable-p group)
+ (when (and (gnus-group-auto-expirable-p group)
+ (not (gnus-group-read-only-p group)))
(gnus-add-marked-articles
group 'expire (list article))))))