X-Git-Url: http://cgit.sxemacs.org/?p=gnus;a=blobdiff_plain;f=lisp%2Fgnus-group.el;h=ad49824f028613d276385b32562955d57d8fca62;hp=f75ef37dadd05bae3d47b575a200c93750161676;hb=90f7e57cdbebca17652f43459b3f5dfbfb26d7fa;hpb=1092348813c6b3aee4ef30ae7f25998a2469430e diff --git a/lisp/gnus-group.el b/lisp/gnus-group.el index f75ef37da..ad49824f0 100644 --- a/lisp/gnus-group.el +++ b/lisp/gnus-group.el @@ -1,6 +1,6 @@ ;;; gnus-group.el --- group mode commands for Gnus -;; Copyright (C) 1996-2012 Free Software Foundation, Inc. +;; Copyright (C) 1996-2015 Free Software Foundation, Inc. ;; Author: Lars Magne Ingebrigtsen ;; Keywords: news @@ -24,10 +24,6 @@ ;;; Code: -;; For Emacs <22.2 and XEmacs. -(eval-and-compile - (unless (fboundp 'declare-function) (defmacro declare-function (&rest r)))) - (eval-when-compile (require 'cl)) (defvar tool-bar-mode) @@ -482,6 +478,26 @@ simple manner.") (defvar gnus-group-edit-buffer nil) +(defvar gnus-tmp-news-method) +(defvar gnus-tmp-colon) +(defvar gnus-tmp-news-server) +(defvar gnus-tmp-decoded-group) +(defvar gnus-tmp-header) +(defvar gnus-tmp-process-marked) +(defvar gnus-tmp-summary-live) +(defvar gnus-tmp-news-method-string) +(defvar gnus-tmp-group-icon) +(defvar gnus-tmp-moderated-string) +(defvar gnus-tmp-newsgroup-description) +(defvar gnus-tmp-comment) +(defvar gnus-tmp-qualified-group) +(defvar gnus-tmp-subscribed) +(defvar gnus-tmp-number-of-read) +(defvar gnus-inhibit-demon) +(defvar gnus-pick-mode) +(defvar gnus-tmp-marked-mark) +(defvar gnus-tmp-number-of-unread) + (defvar gnus-group-line-format-alist `((?M gnus-tmp-marked-mark ?c) (?S gnus-tmp-subscribed ?c) @@ -571,7 +587,6 @@ simple manner.") "p" gnus-group-prev-unread-group "\177" gnus-group-prev-unread-group [delete] gnus-group-prev-unread-group - [backspace] gnus-group-prev-unread-group "N" gnus-group-next-group "P" gnus-group-prev-group "\M-n" gnus-group-next-unread-group-same-level @@ -1105,7 +1120,7 @@ When FORCE, rebuild the tool bar." (set (make-local-variable 'tool-bar-map) map)))) gnus-group-tool-bar-map) -(defun gnus-group-mode () +(define-derived-mode gnus-group-mode fundamental-mode "Group" "Major mode for reading news. All normal editing commands are switched off. @@ -1122,17 +1137,12 @@ For more in-depth information on this mode, read the manual (`\\[gnus-info-find- The following commands are available: \\{gnus-group-mode-map}" - (interactive) - (kill-all-local-variables) (when (gnus-visual-p 'group-menu 'menu) (gnus-group-make-menu-bar) (gnus-group-make-tool-bar)) (gnus-simplify-mode-line) - (setq major-mode 'gnus-group-mode) - (setq mode-name "Group") (gnus-group-set-mode-line) (setq mode-line-process nil) - (use-local-map gnus-group-mode-map) (buffer-disable-undo) (setq truncate-lines t) (setq buffer-read-only t @@ -1143,16 +1153,14 @@ The following commands are available: (when gnus-use-undo (gnus-undo-mode 1)) (when gnus-slave - (gnus-slave-mode)) - (gnus-run-mode-hooks 'gnus-group-mode-hook)) + (gnus-slave-mode))) (defun gnus-update-group-mark-positions () (save-excursion (let ((gnus-process-mark ?\200) (gnus-group-update-hook nil) (gnus-group-marked '("dummy.group")) - (gnus-active-hashtb (make-vector 10 0)) - (topic "")) + (gnus-active-hashtb (make-vector 10 0))) (gnus-set-active "dummy.group" '(0 . 0)) (gnus-set-work-buffer) (gnus-group-insert-group-line "dummy.group" 0 nil 0 nil) @@ -1193,7 +1201,7 @@ The following commands are available: (defun gnus-group-setup-buffer () (set-buffer (gnus-get-buffer-create gnus-group-buffer)) - (unless (eq major-mode 'gnus-group-mode) + (unless (derived-mode-p 'gnus-group-mode) (gnus-group-mode))) (defun gnus-group-name-charset (method group) @@ -1585,7 +1593,7 @@ if it is a string, only list groups matching REGEXP." gnus-process-mark ? )) (buffer-read-only nil) beg end - header gnus-tmp-header) ; passed as parameter to user-funcs. + gnus-tmp-header) ; passed as parameter to user-funcs. (beginning-of-line) (setq beg (point)) (gnus-add-text-properties @@ -1603,20 +1611,31 @@ if it is a string, only list groups matching REGEXP." gnus-indentation ,gnus-group-indentation gnus-level ,gnus-tmp-level)) (setq end (point)) - (when gnus-group-update-tool-bar - (gnus-put-text-property beg end 'point-entered - 'gnus-tool-bar-update) - (gnus-put-text-property beg end 'point-left - 'gnus-tool-bar-update)) + (gnus-group--setup-tool-bar-update beg end) (forward-line -1) (when (inline (gnus-visual-p 'group-highlight 'highlight)) (gnus-group-highlight-line gnus-tmp-group beg end)) (gnus-run-hooks 'gnus-group-update-hook) (forward-line))) +(defun gnus-group--setup-tool-bar-update (beg end) + (when gnus-group-update-tool-bar + (if (fboundp 'cursor-sensor-mode) + (progn + (unless (bound-and-true-p cursor-sensor-mode) + (cursor-sensor-mode 1)) + (gnus-put-text-property beg end 'cursor-sensor-functions + '(gnus-tool-bar-update))) + (gnus-put-text-property beg end 'point-entered + #'gnus-tool-bar-update) + (gnus-put-text-property beg end 'point-left + #'gnus-tool-bar-update)))) + (defun gnus-group-update-eval-form (group list) "Eval `car' of each element of LIST, and return the first that return t. Some value are bound so the form can use them." + (defvar group-age) (defvar ticked) (defvar score) (defvar level) + (defvar mailp) (defvar total) (defvar unread) (when list (let* ((entry (gnus-group-entry group)) (unread (if (numberp (car entry)) (car entry) 0)) @@ -1667,7 +1686,7 @@ and ends at END." (let ((face (cdar (gnus-group-update-eval-form group gnus-group-highlight)))) - (unless (eq face (get-text-property beg 'face)) + (unless (eq face (gnus-get-text-property-excluding-characters-with-faces beg 'face)) (let ((inhibit-read-only t)) (gnus-put-text-property-excluding-characters-with-faces beg end 'face @@ -1795,7 +1814,9 @@ already. If INFO-UNCHANGED is non-nil, dribble buffer is not updated." "Get the name of the newsgroup on the current line." (let ((group (get-text-property (point-at-bol) 'gnus-group))) (when group - (symbol-name group)))) + (if (stringp group) + group + (symbol-name group))))) (defun gnus-group-group-level () "Get the level of the newsgroup on the current line." @@ -2147,7 +2168,7 @@ be permanent." (defun gnus-group-name-at-point () "Return a group name from around point if it exists, or nil." - (if (eq major-mode 'gnus-group-mode) + (if (derived-mode-p 'gnus-group-mode) (let ((group (gnus-group-group-name))) (when group (gnus-group-decoded-name group))) @@ -2290,9 +2311,12 @@ Return the name of the group if selection was successful." ;; (gnus-read-group "Group name: ") (gnus-group-completing-read) (gnus-read-method "From method"))) - ;; Transform the select method into a unique server. (unless (gnus-alive-p) - (gnus-no-server)) + (nnheader-init-server-buffer) + ;; Necessary because of funky inlining. + (require 'gnus-cache) + (setq gnus-newsrc-hashtb (gnus-make-hashtable))) + ;; Transform the select method into a unique server. (when (stringp method) (setq method (gnus-server-to-method method))) (let ((address-slot @@ -2307,23 +2331,28 @@ Return the name of the group if selection was successful." (let ((group (if (gnus-group-foreign-p group) group (gnus-group-prefixed-name (gnus-group-real-name group) method)))) + (gnus-set-active group nil) (gnus-sethash group `(-1 nil (,group ,gnus-level-default-subscribed nil nil ,method ,(cons - (cond - (quit-config - (cons 'quit-config quit-config)) - ((assq gnus-current-window-configuration - gnus-buffer-configuration) - (cons 'quit-config + (cons 'quit-config + (cond + (quit-config + quit-config) + ((assq gnus-current-window-configuration + gnus-buffer-configuration) (cons gnus-summary-buffer - gnus-current-window-configuration)))) + gnus-current-window-configuration)) + (t + (cons (current-buffer) + (current-window-configuration))))) parameters))) gnus-newsrc-hashtb) (push method gnus-ephemeral-servers) - (set-buffer gnus-group-buffer) + (when (gnus-buffer-live-p gnus-group-buffer) + (set-buffer gnus-group-buffer)) (unless (gnus-check-server method) (error "Unable to contact server: %s" (gnus-status-message method))) (when activate @@ -2381,7 +2410,7 @@ specified by `gnus-gmane-group-download-format'." group start (+ start range))) (write-region (point-min) (point-max) tmpfile) (gnus-group-read-ephemeral-group - (format "%s.start-%s.range-%s" group start range) + (format "nndoc+ephemeral:%s.start-%s.range-%s" group start range) `(nndoc ,tmpfile (nndoc-article-type mbox)))) (delete-file tmpfile))) @@ -2434,7 +2463,7 @@ Valid input formats include: (gnus-read-ephemeral-gmane-group group start range))) (defcustom gnus-bug-group-download-format-alist - '((emacs . "http://debbugs.gnu.org/%s;mboxmaint=yes;mboxstat=yes") + '((emacs . "http://debbugs.gnu.org/cgi/bugreport.cgi?bug=%s;mboxmaint=yes;mboxstat=yes") (debian . "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. @@ -2458,26 +2487,27 @@ the bug number, and browsing the URL must return mbox output." (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 - (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" (car ids) - (gnus-replace-in-string - (gnus-replace-in-string mbox-url "^http://" "") - "/.*$" "")))) - (write-region (point-min) (point-max) tmpfile) - (gnus-group-read-ephemeral-group - "gnus-read-ephemeral-bug" - `(nndoc ,tmpfile - (nndoc-article-type mbox)) - nil window-conf)) + (let ((tmpfile (mm-make-temp-file "gnus-temp-group-"))) + (let ((coding-system-for-write 'binary) + (coding-system-for-read 'binary)) + (with-temp-file tmpfile + (mm-disable-multibyte) + (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" (car ids) + (gnus-replace-in-string + (gnus-replace-in-string mbox-url "^http://" "") + "/.*$" "")))))) + (gnus-group-read-ephemeral-group + (format "nndoc+ephemeral:bug#%s" + (mapconcat 'number-to-string ids ",")) + `(nndoc ,tmpfile + (nndoc-article-type mbox)) + nil window-conf) (delete-file tmpfile))) (defun gnus-read-ephemeral-debian-bug-group (number) @@ -2726,7 +2756,7 @@ server." (interactive (list (gnus-read-group "Group name: ") - (gnus-read-method "From method"))) + (gnus-read-method "Select method for new group (use tab for completion)"))) (when (stringp method) (setq method (or (gnus-server-to-method method) method))) @@ -2787,14 +2817,21 @@ server." (lambda (group) (gnus-group-delete-group group nil t)))))) -(defun gnus-group-delete-articles (group) - "Delete all articles in the current group." - (interactive (list (gnus-group-group-name))) +(defun gnus-group-delete-articles (group &optional oldp) + "Delete all articles in the current group. +If OLDP (the prefix), only delete articles that are \"old\", +according to the expiry settings. Note that this will delete old +not-expirable articles, too." + (interactive (list (gnus-group-group-name) + current-prefix-arg)) (let ((articles (gnus-uncompress-range (gnus-active group)))) (when (gnus-yes-or-no-p (format "Do you really want to delete these %d articles forever? " (length articles))) - (gnus-request-expire-articles articles group 'force)))) + (gnus-request-expire-articles articles group + (if current-prefix-arg + nil + 'force))))) (defun gnus-group-delete-group (group &optional force no-prompt) "Delete the current group. Only meaningful with editable groups. @@ -2913,7 +2950,7 @@ and NEW-NAME will be prompted for." (gnus-info-params info)) (t info)) ;; The proper documentation. - (format + (gnus-format-message "Editing the %s for `%s'." (cond ((eq part 'method) "select method") @@ -3098,12 +3135,12 @@ If SOLID (the prefix), create a solid group." (gnus-group-read-ephemeral-group group method t (cons (current-buffer) - (if (eq major-mode 'gnus-summary-mode) 'summary 'group)))))) + (if (derived-mode-p 'gnus-summary-mode) 'summary 'group)))))) (defvar nnrss-group-alist) (eval-when-compile - (defun nnrss-discover-feed (arg)) - (defun nnrss-save-server-data (arg))) + (defun nnrss-discover-feed (_arg)) + (defun nnrss-save-server-data (_arg))) (defun gnus-group-make-rss-group (&optional url) "Given a URL, discover if there is an RSS feed. If there is, use Gnus to create an nnrss group" @@ -3213,7 +3250,7 @@ mail messages or news articles in files that have numeric names." (unless (gnus-group-read-ephemeral-group name method t (cons (current-buffer) - (if (eq major-mode 'gnus-summary-mode) + (if (derived-mode-p 'gnus-summary-mode) 'summary 'group))) (error "Couldn't enter %s" dir)))) @@ -3241,7 +3278,8 @@ mail messages or news articles in files that have numeric names." (error "%s is not an nnimap group" group)) (unless (setq acl (nnimap-acl-get mailbox (cadr method))) (error "Server does not support ACL's")) - (gnus-edit-form acl (format "Editing the access control list for `%s'. + (gnus-edit-form acl (gnus-format-message "\ +Editing the access control list for `%s'. An access control list is a list of (identifier . rights) elements. @@ -3250,7 +3288,7 @@ mail messages or news articles in files that have numeric names." Rights is a string listing a (possibly empty) set of alphanumeric characters, each character listing a set of operations which is being - controlled. Letters are reserved for ``standard'' rights, listed + controlled. Letters are reserved for \"standard\" rights, listed below. Digits are reserved for implementation or site defined rights. l - lookup (mailbox is visible to LIST/LSUB commands) @@ -3582,6 +3620,8 @@ Cross references (Xref: header) of articles are ignored." (interactive "P") (gnus-group-catchup-current n 'all)) +(declare-function gnus-sequence-of-unread-articles "gnus-sum" (group)) + (defun gnus-group-catchup (group &optional all) "Mark all articles in GROUP as read. If ALL is non-nil, all articles are marked as read. @@ -3643,6 +3683,10 @@ Uses the process/prefix convention." (expirable (if (gnus-group-total-expirable-p group) (cons nil (gnus-list-of-read-articles group)) (assq 'expire (gnus-info-marks info)))) + (articles-to-expire + (gnus-list-range-difference + (gnus-uncompress-sequence (cdr expirable)) + (cdr (assq 'unexist (gnus-info-marks info))))) (expiry-wait (gnus-group-find-parameter group 'expiry-wait)) (nnmail-expiry-target (or (gnus-group-find-parameter group 'expiry-target) @@ -3657,11 +3701,9 @@ Uses the process/prefix convention." ;; parameter. (let ((nnmail-expiry-wait-function nil) (nnmail-expiry-wait expiry-wait)) - (gnus-request-expire-articles - (gnus-uncompress-sequence (cdr expirable)) group)) + (gnus-request-expire-articles articles-to-expire group)) ;; Just expire using the normal expiry values. - (gnus-request-expire-articles - (gnus-uncompress-sequence (cdr expirable)) group)))) + (gnus-request-expire-articles articles-to-expire group)))) (gnus-close-group group)) (gnus-message 6 "Expiring articles in %s...done" (gnus-group-decoded-name group)) @@ -3748,7 +3790,7 @@ group line." nil nil (gnus-read-active-file-p)))) (let ((newsrc (gnus-group-entry group))) (cond - ((string-match "^[ \t]*$" group) + ((string-match "\\`[ \t]*\\'" group) (error "Empty group name")) (newsrc ;; Toggle subscription flag. @@ -4034,7 +4076,8 @@ otherwise all levels below ARG will be scanned too." (unless gnus-slave (gnus-master-read-slave-newsrc)) - (gnus-get-unread-articles arg nil one-level) + (gnus-get-unread-articles (gnus-group-default-level arg t) + nil one-level) ;; If the user wants it, we scan for new groups. (when (eq gnus-check-new-newsgroups 'always) @@ -4065,7 +4108,9 @@ If DONT-SCAN is non-nil, scan non-activated groups as well." (gnus-group-remove-mark group) ;; Bypass any previous denials from the server. (gnus-remove-denial (setq method (gnus-find-method-for-group group))) - (if (gnus-activate-group group (if dont-scan nil 'scan) nil method) + (if (or (and (not dont-scan) + (gnus-request-group-scan group (gnus-get-info group))) + (gnus-activate-group group (if dont-scan nil 'scan) nil method)) (let ((info (gnus-get-info group)) (active (gnus-active group))) (when info @@ -4298,10 +4343,15 @@ The hook `gnus-suspend-gnus-hook' is called before actually suspending." (unless (or (eq buf group-buf) (eq buf gnus-dribble-buffer) (with-current-buffer buf - (eq major-mode 'message-mode))) + (derived-mode-p 'message-mode))) (gnus-kill-buffer buf))) (setq gnus-backlog-articles nil) (gnus-kill-gnus-frames) + ;; Closing all the backends is useful (for instance) when when the + ;; IP addresses have changed and you need to reconnect. + (dolist (elem gnus-opened-servers) + (gnus-close-server (car elem)) + (setcar (cdr elem) 'closed)) (when group-buf (bury-buffer group-buf) (delete-windows-on group-buf t)))) @@ -4367,7 +4417,7 @@ The hook `gnus-exit-gnus-hook' is called before actually exiting." (defun gnus-group-browse-foreign-server (method) "Browse a foreign news server. If called interactively, this function will ask for a select method - (nntp, nnspool, etc.) and a server address (eg. nntp.some.where). + (nntp, nnspool, etc.) and a server address (e.g., nntp.some.where). If not, METHOD should be a list where the first element is the method and the second element is the address." (interactive @@ -4383,7 +4433,12 @@ and the second element is the address." ;; Suggested by mapjph@bath.ac.uk. (gnus-completing-read "Address" - gnus-secondary-servers)) + ;; FIXME? gnus-secondary-servers is obsolete, + ;; and it is not obvious that there is anything + ;; sensible to use instead in this particular case. + (if (boundp 'gnus-secondary-servers) + gnus-secondary-servers + (cdr gnus-select-method)))) ;; We got a server name. how)))) (gnus-browse-foreign-server method)) @@ -4442,12 +4497,6 @@ and the second element is the address." (gnus-list-of-unread-articles (car info)))))) (error "No such group: %s" (gnus-info-group info)))))) -(defun gnus-group-set-method-info (group select-method) - (gnus-group-set-info select-method group 'method)) - -(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) @@ -4489,6 +4538,8 @@ and the second element is the address." (sort (nconc (gnus-uncompress-range (cdr m)) (copy-sequence articles)) '<) t)))))) +(declare-function gnus-summary-add-mark "gnus-sum" (article type)) + (defun gnus-add-mark (group mark article) "Mark ARTICLE in GROUP with MARK, whether the group is displayed or not." (let ((buffer (gnus-summary-buffer-name group))) @@ -4653,6 +4704,9 @@ you the groups that have both dormant articles and cached articles." (let ((gnus-group-list-option 'limit)) (gnus-group-list-plus args))) +(declare-function gnus-mark-article-as-read "gnus-sum" (article &optional mark)) +(declare-function gnus-group-make-articles-read "gnus-sum" (group articles)) + (defun gnus-group-mark-article-read (group article) "Mark ARTICLE read." (let ((buffer (gnus-summary-buffer-name group)) @@ -4668,6 +4722,8 @@ you the groups that have both dormant articles and cached articles." (setq mark gnus-expirable-mark)) (setq mark (gnus-request-update-mark group article mark)) + (gnus-request-set-mark + group (list (list (list article) 'add '(read)))) (gnus-mark-article-as-read article mark) (setq gnus-newsgroup-active (gnus-active group)) (when active