]> code.delx.au - gnu-emacs-elpa/commitdiff
Merge commit '3e5c11a13981a1ff613cb4442ad644285c44e481' from gnorb
authorEric Abrahamsen <eric@ericabrahamsen.net>
Thu, 23 Apr 2015 08:54:11 +0000 (16:54 +0800)
committerEric Abrahamsen <eric@ericabrahamsen.net>
Thu, 23 Apr 2015 08:54:11 +0000 (16:54 +0800)
1  2 
packages/gnorb/README.org
packages/gnorb/gnorb-bbdb.el
packages/gnorb/gnorb-gnus.el
packages/gnorb/gnorb-org.el
packages/gnorb/gnorb-registry.el
packages/gnorb/gnorb-utils.el
packages/gnorb/gnorb.el
packages/gnorb/gnorb.info
packages/gnorb/gnorb.org
packages/gnorb/gnorb.texi
packages/gnorb/nngnorb.el

index 1f8f82f86f62c5060a52a9ee410eddad78fa60c8,9e2f9bd12231b366adeab7dc929d7bc29076d90f..9e2f9bd12231b366adeab7dc929d7bc29076d90f
@@@ -16,7 -16,31 +16,31 @@@ mini mailboxes
  *Note for previous users*: If you were using Gnorb from Github before
  it shifted to the Elpa repository, the email tracking mechanism has
  changed, please see the manual for details.
+ ** Known bugs/issues
+ *** Gnus Registry
+ Prior to late December, 2014, the Gnus registry had some issues with
+ preserving "precious" entries while pruning.
  
+ When the registry approaches its maximum size it will delete excess
+ entries, a process referred to as "pruning". "Precious" entries are
+ those that contain important information: they should not be pruned.
+ Gnorb uses the registry to track associations between messages and Org
+ headings, and marks those entries as precious. The entire process of
+ tracking, in fact, relies on these entries being preserved, and Gnorb
+ goes to some lengths to protect this information. Older versions of
+ the registry could nevertheless delete those entries.
+ These issues are fixed circa the end of December, 2014, around "Ma
+ Gnus v0.12", whatever that means. If you think there's a possibility
+ your registry is full, and associations are being deleted, you might
+ consider upgrading to a recent Gnus.
+ *** Multiple Associations
+ Gnorb theoretically supports email messages being associated with
+ multiple Org headings. In practice, however, this situation hasn't
+ been thought through completely, and you may experience weirdness. If
+ you do, and you have some ideas about how it should be handled, please
+ contact the author and suggest them.
  ** Installation
  
  It's easiest to install Gnorb from Elpa: run `list-packages' and look
@@@ -60,7 -84,10 +84,10 @@@ composing messages from... Or maybe it'
  Provide an Org Agenda command that does an email search for messages
  received in the visible date span, or day under point, etc. Make it
  work in the calendar, as well?
- *** TODO Capture to child/subtree trigger actions
+ *** DONE Capture to child/subtree trigger actions
+ :LOGBOOK:
+ - State "DONE"       from "TODO"       [2015-03-17 Tue 17:42]
+ :END:
  Add trigger actions that create new sibling or child headings on the
  original Org heading.
  *** TODO Gnus message tagging
index 572a4b92729f61be852aa236973ef6ff425f20a2,eb2f6eb02511f615aa662c7ebcceb647a2a37d3c..eb2f6eb02511f615aa662c7ebcceb647a2a37d3c
@@@ -150,8 -150,6 +150,6 @@@ be composed, just as in `gnus-posting-s
  An example value might look like:"
    :group 'gnorb-bbdb)
  
- (defvar message-mode-hook)
  (when (fboundp 'bbdb-record-xfield-string)
    (fset (intern (format "bbdb-read-xfield-%s"
                        gnorb-bbdb-org-tag-field))
@@@ -207,6 -205,8 +205,8 @@@ Org tags are stored in the `gnorb-bbdb-
         (insert
          (bbdb-indent-string (concat val "\n") indent)))))))
  
+ (defvar message-mode-hook)
  ;;;###autoload
  (defun gnorb-bbdb-mail (records &optional subject n verbose)
    "\\<bbdb-mode-map>Acts just like `bbdb-mail', except runs
@@@ -392,14 -392,16 +392,16 @@@ both, use \"C-u\" before the \"*\".
         (mapconcat
          'identity
          (delete-dups
-          (cl-mapcan (lambda (r)
-                    (bbdb-record-xfield-split r gnorb-bbdb-org-tag-field))
-                  records))
+          (cl-mapcan
+           (lambda (r)
+             (bbdb-record-xfield-split r gnorb-bbdb-org-tag-field))
+           records))
          "|")))
      (if tag-string
        ;; C-u = all headings, not just todos
-       (org-tags-view (not (equal current-prefix-arg '(4)))
-                        tag-string)
+       (if (equal current-prefix-arg '(4))
+           (org-tags-view nil tag-string)
+         (org-tags-view t tag-string))
        (error "No org-tags field present"))))
  
  ;;;###autoload
@@@ -424,9 -426,9 +426,9 @@@ a prefix arg and \"*\", the prefix arg 
      (when (equal current-prefix-arg '(4))
        (setq search-string
            (read-from-minibuffer
-            (format "%s search string: " (cl-first backend)) search-string)))
+            (format "%s search string: " (first backend)) search-string)))
      (funcall (cl-third backend) search-string)
-     (delete-other-windows)))  
+     (delete-other-windows)))
  
  ;;;###autoload
  (defun gnorb-bbdb-cite-contact (rec)
       mail-string)))
  
  ;;; Field containing links to recent messages
  (when (boundp 'bbdb-xfield-label-list)
-   (add-to-list 'bbdb-xfield-label-list gnorb-bbdb-messages-field nil 'eq))
+  (add-to-list 'bbdb-xfield-label-list gnorb-bbdb-messages-field nil 'eq))
  
  (defun gnorb-bbdb-display-messages (record format)
    "Show links to the messages collected in the
@@@ -594,16 -595,10 +595,10 @@@ to a message into the record's `gnorb-b
                          (parse-time-string (mail-header-date heads))))
             (subject (mail-header-subject heads))
             (id (mail-header-id heads))
-            (group gnus-newsgroup-name)
+            (group (gnorb-get-real-group-name
+                    gnus-newsgroup-name
+                    art-no))
             link)
-       ;; check for both nnvirtual and nnir, and link to the real
-       ;; group in those cases
-       (when (eq (car (gnus-find-method-for-group group))
-                 'nnvirtual)
-         (setq group (car (nnvirtual-map-article art-no))))
-       (when (eq (car (gnus-find-method-for-group group))
-                 'nnir)
-         (setq group (nnir-article-group art-no)))
        (if (not (and date subject id group))
            (message "Could not save a link to this message")
          (setq link (make-gnorb-bbdb-link :subject subject :date date
                              (time-less-p
                               (gnorb-bbdb-link-date b)
                               (gnorb-bbdb-link-date a))))))
-         (setq val (cl-subseq val 0 gnorb-bbdb-collect-N-messages))
+         (setq val (cl-subseq val 0 (min (length val) gnorb-bbdb-collect-N-messages)))
          (bbdb-record-set-xfield record
                                  gnorb-bbdb-messages-field
                                  (delq nil val))
index 2d3c5b09cc4a56a2c88c670abb6c6e46cf857efa,a77a7ed5319661e0e0725ec099ddfb30322e8085..a77a7ed5319661e0e0725ec099ddfb30322e8085
@@@ -107,6 -107,12 +107,12 @@@ Basically behave as if all attachments 
    :group 'gnorb-gnus
    :type 'string)
  
+ (defcustom gnorb-gnus-summary-tracked-mark "&"
+   "Default mark to insert in the summary format line of articles
+   that are already tracked by TODO headings."
+   :group 'gnorb-gnus
+   :type 'string)
  (defcustom gnorb-gnus-trigger-refile-targets
    '((org-agenda-files :maxlevel . 4))
    "A value to use as an equivalent of `org-refile-targets' (which
@@@ -189,7 -195,7 +195,7 @@@ save them into `gnorb-tmp-dir'.
        (set-buffer (org-capture-get :original-buffer)))
      (unless (memq major-mode '(gnus-summary-mode gnus-article-mode))
        (error "Only works in Gnus summary or article buffers"))
-     (let ((article (gnus-summary-article-number)) 
+     (let ((article (gnus-summary-article-number))
          mime-handles)
        (when (or (null gnus-current-article)
                (null gnus-article-current)
  
  (add-hook 'org-capture-mode-hook 'gnorb-gnus-capture-attach)
  
+ (defvar org-note-abort)
  (defun gnorb-gnus-capture-abort-cleanup ()
-   (when (and org-note-abort
-            (org-capture-get :gnus-attachments))
-     ;; FIXME: Yuck: setting `abort-note' will fail as soon as org-capture.el is
-     ;; compiled with lexical-binding!
-     (condition-case nil
-       (progn (org-attach-delete-all)
-              (setq abort-note 'clean)
-              ;; remove any gnorb-mail-header values here
-              )
-       (error
-        (setq abort-note 'dirty)))))
+   (with-no-warnings ; For `org-note-abort'
+     (when (and org-note-abort
+              (or gnorb-gnus-capture-always-attach
+                  (org-capture-get :gnus-attachments)))
+      (condition-case error
+        (progn (org-attach-delete-all)
+               (setq abort-note 'clean)
+               ;; remove any gnorb-mail-header values here
+               )
+        (error
+       (setq abort-note 'dirty))))))
  
  (add-hook 'org-capture-prepare-finalize-hook
          'gnorb-gnus-capture-abort-cleanup)
@@@ -297,11 -305,14 +305,14 @@@ information about the outgoing message 
            ;; `gnorb-org-setup-message' may have put this here, but
            ;; if we're working from a draft, or triggering this from
            ;; a reply, it might not be there yet.
-           (add-to-list 'message-exit-actions
+           (add-to-list 'message-send-actions
                         'gnorb-org-restore-after-send t))
        (setq gnorb-message-org-ids nil)))))
  
- (add-hook 'message-header-hook 'gnorb-gnus-check-outgoing-headers)
+ ;; This sets the global value, but the hook is made buffer-local in
+ ;; `gnus-inews-add-send-actions', so this is ignored
+ ;(add-hook 'message-header-hook 'gnorb-gnus-check-outgoing-headers)
+ (add-hook 'message-send-hook 'gnorb-gnus-check-outgoing-headers t)
  
  ;;;###autoload
  (defun gnorb-gnus-outgoing-do-todo (&optional arg)
@@@ -379,10 -390,9 +390,9 @@@ work.
          (save-excursion
            (save-restriction
              (widen)
-             (setq message-exit-actions
-                   (remove 'gnorb-org-restore-after-send
-                           (remove 'gnorb-gnus-outgoing-make-todo-1
-                                   message-exit-actions)))
+             (setq message-send-actions
+                   (remove 'gnorb-gnus-outgoing-make-todo-1
+                           message-send-actions))
              (message-narrow-to-headers-or-head)
              (message-remove-header
               gnorb-mail-header)
                ;; message
                (push h header-ids)))))
        (goto-char compose-marker)
-       (add-to-list
-        'message-exit-actions
-        (if header-ids
-            'gnorb-org-restore-after-send
-          'gnorb-gnus-outgoing-make-todo-1)
-        t)
+       (unless header-ids
+         (add-to-list 'message-send-actions
+          'gnorb-gnus-outgoing-make-todo-1 t))
        (message
         (if header-ids
             "Message will trigger TODO state-changes after sending"
  (defun gnorb-gnus-incoming-do-todo (arg &optional id)
    "Call this function from a received gnus message to store a
  link to the message, prompt for a related Org heading, visit the
- heading, and either add a note or trigger a TODO state change.
- Set `gnorb-trigger-todo-default' to 'note or 'todo (you can
- get the non-default behavior by calling this function with a
- prefix argument), or to 'prompt to always be prompted.
- In some cases, Gnorb can guess for you which Org heading you
- probably want to trigger, which can save some time. It does this
- by looking in the References header, and seeing if any of the IDs
- there match the value of the `gnorb-org-msg-id-key' property for
- any headings. In order for this to work, you will have to have
- loaded org-id, and have the variable `org-id-track-globally' set
- to t (it is, by default)."
+ heading, and trigger an action on it \(see
+ `gnorb-org-trigger-actions'\).
+ If you've set up message tracking \(with
+ `gnorb-tracking-initialize'\), Gnorb can guess which Org heading
+ you probably want to trigger, which can save some time. It does
+ this by looking in the References header, and seeing if any of
+ the messages referenced there are already being tracked by any
+ headings.
+ If you mark several messages before calling this function, or
+ call it with a numerical prefix arg, those messages will be
+ \"bulk associated\" with the chosen Org heading: associations
+ will be made, but you won't be prompted to trigger an action, and
+ you'll stay in the Gnus summary buffer."
    (interactive "P")
    (when (not (memq major-mode '(gnus-summary-mode gnus-article-mode)))
      (user-error "Only works in gnus summary or article mode"))
    (setq gnorb-window-conf (current-window-configuration))
    (move-marker gnorb-return-marker (point))
    (setq gnorb-gnus-message-info nil)
-   (let* ((headers (gnus-data-header
-                  (gnus-data-find
-                   (gnus-summary-article-number))))
+   (let* ((articles (gnus-summary-work-articles arg))
+        (art-no (gnus-summary-article-number))
+        (headers (gnus-data-header
+                  (gnus-data-find art-no)))
         (msg-id (mail-header-id headers))
         (from (mail-header-from headers))
         (subject (mail-header-subject headers))
         (date (mail-header-date headers))
         (to (cdr (assoc 'To (mail-header-extra headers))))
-        (group gnus-newsgroup-name)
+        (group (gnorb-get-real-group-name
+                gnus-newsgroup-name
+                art-no))
         (link (call-interactively 'org-store-link))
         (org-refile-targets gnorb-gnus-trigger-refile-targets)
         (ref-msg-ids (concat (mail-header-references headers) " "
                     :link ,link :date ,date :refs ,ref-msg-ids
                     :group ,group))
      (gnorb-gnus-collect-all-attachments nil t)
-     ;; Delete other windows, users can restore with
-     ;; `gnorb-restore-layout'.
-     (delete-other-windows)
-     (if id
-       (gnorb-trigger-todo-action arg id)
-       ;; Flush out zombies (dead associations).
-       (setq related-headings
-           (cl-remove-if
-            (lambda (h)
-              (when (null (org-id-find-id-file h))
-                (when (y-or-n-p
-                       (format
-                        "ID %s no longer exists, disassociate message?"
-                        h))
-                  (gnorb-delete-association msg-id h))))
-            related-headings))
-       (if (catch 'target
-           (dolist (h related-headings nil)
-             (when (yes-or-no-p
-                    (format "Trigger action on %s"
-                            (gnorb-pretty-outline h)))
-               (throw 'target (setq targ h)))))
-         (gnorb-trigger-todo-action arg targ)
-       (setq targ (org-refile-get-location
-                   "Trigger heading" nil t))
-       (find-file (nth 1 targ))
-       (goto-char (nth 3 targ))
-       (gnorb-trigger-todo-action arg)))))
+     (condition-case err
+      (if id
+        (progn
+          (delete-other-windows)
+          (gnorb-trigger-todo-action nil id))
+        ;; Flush out zombies (dead associations).
+        (setq related-headings
+            (cl-remove-if
+             (lambda (h)
+               (when (null (org-id-find-id-file h))
+                 (when (y-or-n-p
+                        (format
+                         "ID %s no longer exists, disassociate message?"
+                         h))
+                   (gnorb-delete-association msg-id h))))
+             related-headings))
+        ;; See if one of the related headings is chosen.
+        (unless (catch 'target
+                (dolist (h related-headings nil)
+                  (when (yes-or-no-p
+                         (format "Trigger action on %s"
+                                 (gnorb-pretty-outline h)))
+                    (throw 'target (setq targ h)))))
+        ;; If not, use the refile interface to choose one.
+        (setq targ (org-refile-get-location
+                    "Trigger heading" nil t))
+        (setq targ
+              (save-window-excursion
+                (find-file (nth 1 targ))
+                (goto-char (nth 3 targ))
+                (org-id-get-create))))
+        ;; Either bulk associate multiple messages...
+        (if (> (length articles) 1)
+          (progn
+            (dolist (a articles)
+              (gnorb-registry-make-entry
+               (mail-header-id
+                (gnus-data-header
+                 (gnus-data-find a)))
+               from subject targ group)
+              (gnus-summary-remove-process-mark a))
+            (message "Associated %d messages with %s"
+                     (length articles) (gnorb-pretty-outline targ)))
+        ;; ...or just trigger the one.
+        (delete-other-windows)
+        (gnorb-trigger-todo-action nil targ)))
+      (error
+       ;; If these are left populated after an error, it plays hell
+       ;; with future trigger processes.
+       (setq gnorb-gnus-message-info nil)
+       (setq gnorb-gnus-capture-attachments nil)
+       (signal (car err) (cdr err))))))
+ ;;;###autoload
+ (defun gnorb-gnus-quick-reply ()
+   "Compose a reply to the message under point, and associate both
+ the original message and the reply with the selected heading.
+ Take no other action.
+ Use this when you want to compose a reply to a message on the
+ spot, and track both messages, without having to go through the
+ hassle of triggering an action on a heading, and then starting a
+ reply."
+   (interactive)
+   (when (not (memq major-mode '(gnus-summary-mode gnus-article-mode)))
+     (user-error "Only works in gnus summary or article mode"))
+   (let* ((art-no (gnus-summary-article-number))
+        (headers (gnus-data-header
+                  (gnus-data-find art-no)))
+        (msg-id (mail-header-id headers))
+        (from (mail-header-from headers))
+        (subject (mail-header-subject headers))
+        (group (gnorb-get-real-group-name
+                gnus-newsgroup-name
+                art-no))
+        (ref-msg-ids (concat (mail-header-references headers) " "
+                             msg-id))
+        (related-headings
+         (when ref-msg-ids
+           (gnorb-find-tracked-headings headers t)))
+        (targ (car-safe related-headings)))
+     (if targ
+       (let ((ret (make-marker)))
+         ;; Assume the first heading is the one we want.
+         (gnorb-registry-make-entry
+          msg-id from subject targ group)
+         (gnus-summary-wide-reply-with-original 1)
+         (move-marker ret (point))
+         (save-restriction
+           (widen)
+           (message-narrow-to-headers-or-head)
+           (goto-char (point-min))
+           (open-line 1)
+           (message-insert-header
+            (intern gnorb-mail-header) targ))
+         (goto-char ret)
+         (message
+          (format "Original message and reply will be associated with %s"
+                  (gnorb-pretty-outline targ))))
+       (message "No associated headings found"))))
  
  ;;;###autoload
- (defun gnorb-gnus-search-messages (str &optional ret)
+ (defun gnorb-gnus-search-messages (str persist &optional head-text ret)
    "Initiate a search for gnus message links in an org subtree.
  The arg STR can be one of two things: an Org heading id value
  \(IDs should be prefixed with \"id+\"\), in which case links will
@@@ -579,31 -664,46 +664,46 @@@ work.
    (let ((nnir-address
         (or (gnus-method-to-server '(nngnorb))
             (user-error
-             "Please add a \"nngnorb\" backend to your gnus installation."))))
+             "Please add a \"nngnorb\" backend to your gnus installation.")))
+       name method spec)
      (when (version= "5.13" gnus-version-number)
        (with-no-warnings                 ; All these variables are available.
        (setq nnir-current-query nil
              nnir-current-server nil
              nnir-current-group-marked nil
              nnir-artlist nil)))
-     (gnus-group-read-ephemeral-group
-      ;; in 24.4, the group name is mostly decorative. in 24.3, the
-      ;; query itself is read from there. It should look like (concat
-      ;; "nnir:" (prin1-to-string '((query str))))
-      (if (version= "5.13" gnus-version-number)
-        (concat "nnir:" (prin1-to-string `((query ,str))))
-        (concat "gnorb-" str))
-      (if (version= "5.13" gnus-version-number)
-        (list 'nnir nnir-address)
-        (list 'nnir "nnir"))
-      nil
-      ret
-      nil nil
-      ;; the following seems to simply be ignored under gnus 5.13
-      (list (cons 'nnir-specs (list (cons 'nnir-query-spec `((query . ,str)))
+     ;; In 24.4, the group name is mostly decorative, but in 24.3, the
+     ;; actual query is held there.
+     (setq name (if (version= "5.13" gnus-version-number)
+                  (concat "nnir:" (prin1-to-string `((query ,str))))
+                (if persist
+                    (read-string
+                     (format "Name for group (default %s): " head-text)
+                     nil head-text t)
+                  (concat "gnorb-" str))))
+     (setq method (if (version= "5.13" gnus-version-number)
+                    (list 'nnir nnir-address)
+                  (list 'nnir "Gnorb")))
+     (setq spec
+         (list
+          (cons 'nnir-specs (list (cons 'nnir-query-spec `((query . ,str)))
                                   (cons 'nnir-group-spec `((,nnir-address nil)))))
           (cons 'nnir-artlist nil)))
-     (gnorb-summary-minor-mode)))
+     (if persist
+       (progn
+         (switch-to-buffer gnus-group-buffer)
+         (gnus-group-make-group name method nil spec)
+         (gnus-group-select-group))
+      (gnus-group-read-ephemeral-group name method nil ret nil nil spec))))
+ (defun gnorb-gnus-summary-mode-hook ()
+   "Check if we've entered a Gnorb-generated group, and activate
+   `gnorb-summary-minor-mode', if so."
+   (let ((method (gnus-find-method-for-group gnus-newsgroup-name)))
+     (when (string-match-p "Gnorb" (cadr method))
+       (gnorb-summary-minor-mode))))
+ (add-hook 'gnus-summary-mode-hook #'gnorb-gnus-summary-mode-hook)
  
  ;;; Automatic noticing of relevant messages
  
@@@ -633,8 -733,7 +733,7 @@@ option `gnorb-gnus-hint-relevant-articl
           (tracked-headings (gnorb-find-tracked-headings headers))
           (key
            (where-is-internal 'gnorb-gnus-incoming-do-todo
-                              nil t))
-          rel-headings)
+                              nil t)))
        (cond (assoc-heading
             (message "Message is associated with %s"
                      (gnorb-pretty-outline (car assoc-heading) t)))
    (if (not (memq (car (gnus-find-method-for-group
                       gnus-newsgroup-name))
                 '(nnvirtual nnir)))
-       (if (gnorb-find-tracked-headings header)
-         gnorb-gnus-summary-mark
-       " ")
+       (cond ((gnus-registry-get-id-key
+             (mail-header-message-id header) 'gnorb-ids)
+            gnorb-gnus-summary-tracked-mark)
+           ((gnorb-find-tracked-headings header)
+            gnorb-gnus-summary-mark)
+           (t " "))
      " "))
  
  (fset (intern (concat "gnus-user-format-function-"
    (let* ((headers (gnus-data-header
                   (gnus-data-find
                    (gnus-summary-article-number))))
-          (tracked-headings
-           (gnorb-find-tracked-headings headers)))
+        (tracked-headings
+         (gnorb-find-tracked-headings headers)))
      (when tracked-headings
        (setq gnorb-window-conf (current-window-configuration))
        (move-marker gnorb-return-marker (point))
index 6d3772d74b19c1c9a256e298ea81e244278057ed,d54e9bae2e67bc882084dcaa930ffc1e1cdb69fc..339211172708b269cb520701378bdaebae83b42a
@@@ -43,9 -43,8 +43,8 @@@
      ("take note" . note)
      ("don't associate" . no-associate)
      ("only associate" . associate)
- ;    ("capture to child" . cap-child)
- ;    ("capture to sibling" . cap-sib)
- )
+     ("capture to child" . cap-child)
+     ("capture to sibling" . cap-sib))
    "List of potential actions that can be taken on headings.
  
  When triggering an Org heading after receiving or sending a
@@@ -56,8 -55,8 +55,8 @@@ todo state: Associate the message, and 
  take note: Associate the message, and take a note.
  don't associate: Do nothing at all, don't connect the message and TODO.
  only associate: Associate the message with this heading, do nothing else.
- capture to child: [not yet implemented] Associate this message with a new child heading.
- capture to sibling: [not yet implemented] Associate this message with a new sibling heading.
+ capture to child: Associate this message with a new child heading.
+ capture to sibling: Associate this message with a new sibling heading.
  
  You can reorder this list or remove items as suits your workflow.
  The two \"capture\" options will use the value of
@@@ -177,9 -176,10 +176,10 @@@ we came from.
            (cond ((eq gnorb-org-mail-scan-scope 'all)
                   strings)
                  ((numberp gnorb-org-mail-scan-scope)
-                  (delq nil
-                        (cl-subseq
-                         strings 0 (1+ gnorb-org-mail-scan-scope))))
+                  (cl-subseq
+                   strings 0 (min
+                              (length strings)
+                              (1+ gnorb-org-mail-scan-scope))))
                  ;; We could provide more options here. 'tree vs
                  ;; 'subtree, for instance.
                  (t
@@@ -271,10 -271,14 +271,14 @@@ headings.
      (when messages
        (insert ", "))
      (insert (mapconcat 'identity mails ", ")))
-   ;; Return us after message is sent.
-   (add-to-list 'message-exit-actions
-              'gnorb-org-restore-after-send t)
-   ;; Set headers from MAIL_* properties (from, cc, and bcc).
+   ;; Commenting this out because
+   ;; `gnorb-gnus-check-outgoing-headers' is set unconditionally in the
+   ;; `message-send-hook, so this should be redundant.  Also, we've
+   ;; switched to using message-send-actions.
+   
+   ;; (add-to-list
+   ;; 'message-exit-actions 'gnorb-org-restore-after-send t) Set
+   ;; headers from MAIL_* properties (from, cc, and bcc).
    (cl-flet ((sh (h)
                (when (cdr h)
                  (funcall (intern (format "message-goto-%s" (car h))))
@@@ -503,8 -507,7 +507,8 @@@ default set of parameters.
           "Export backend: "
           (mapcar (lambda (b)
                     (symbol-name (org-export-backend-name b)))
 -                 org-export--registered-backends) nil t))
 +                 org-export--registered-backends)
 +           nil t))
         (backend-symbol (intern backend-string))
         (f-or-t (org-completing-read "Export as file or text? "
                                      '("file" "text") nil t))
@@@ -614,7 -617,9 +618,9 @@@ search.
                        (let ((rec-tags (bbdb-record-xfield
                                         r gnorb-bbdb-org-tag-field)))
                          (and rec-tags
-                              (let ((tags-list (org-split-string rec-tags ":"))
+                              (let ((tags-list (if (stringp rec-tags)
+                                                   (org-split-string rec-tags ":")
+                                                 rec-tags))
                                     (case-fold-search t)
                                     (org-trust-scanner-tags t))
                                 (eval tag-clause)))))
  ;;; Groups from the gnorb gnus server backend
  
  ;;;###autoload
- (defun gnorb-org-view ()
+ (defun gnorb-org-view (arg)
    "Search the subtree at point for links to gnus messages, and
- then show them in an ephemeral group, in gnus.
+ then show them in an ephemeral group, in Gnus.
+ With a prefix arg, create a search group that will persist across
+ Gnus sessions, and can be refreshed.
  
  This won't work unless you've added a \"nngnorb\" server to
  your gnus select methods."
    ;; this should also work on the active region, if there is one.
-   (interactive)
+   (interactive "P")
    (require 'gnorb-gnus)
    (setq gnorb-window-conf (current-window-configuration))
    (move-marker gnorb-return-marker (point))
        (org-back-to-heading)
        (setq id (concat "id+" (org-id-get-create)))
        (gnorb-gnus-search-messages
-        id
+        id arg
+        (replace-regexp-in-string
+       org-bracket-link-regexp "\\3"
+       (nth 4 (org-heading-components)))
         `(when (and (window-configuration-p gnorb-window-conf)
                   gnorb-return-marker)
          (set-window-configuration gnorb-window-conf)
index f7b402cd4df8fa3d98acf232ff408c0b5a2736e4,bcd5adc2c999369ec070abba9693c4a70ad4e9f1..bcd5adc2c999369ec070abba9693c4a70ad4e9f1
@@@ -49,6 -49,7 +49,7 @@@
  ;;; Code:
  
  (require 'gnus-registry)
+ (require 'gnorb-utils)
  (require 'cl-lib)
  
  (defgroup gnorb-registry nil
@@@ -85,32 -86,27 +86,27 @@@ to the message's registry entry, under 
               (memq major-mode '(gnus-summary-mode gnus-article-mode)))
             (not org-note-abort))
      (let* ((msg-id
-           (format "<%s>" (plist-get org-store-link-plist :message-id)))
-          (entry (gnus-registry-get-or-make-entry msg-id))
-          (org-ids
-           (gnus-registry-get-id-key msg-id 'gnorb-ids))
-          (new-org-id (org-id-get-create)))
-       (plist-put org-capture-plist :gnorb-id new-org-id)
-       (setq org-ids (cons new-org-id org-ids))
-       (setq org-ids (delete-dups org-ids))
-       (gnus-registry-set-id-key msg-id 'gnorb-ids org-ids))))
+           (gnorb-bracket-message-id
+            (plist-get org-store-link-plist :message-id)))
+          (org-id (org-id-get-create)))
+       (plist-put org-capture-plist :gnorb-id org-id)
+       (gnorb-registry-make-entry msg-id nil nil org-id nil))))
  
  
  (defun gnorb-registry-capture-abort-cleanup ()
    (when (and (org-capture-get :gnorb-id)
             org-note-abort)
-     (condition-case nil
-       (let* ((msg-id (format "<%s>" (plist-get org-store-link-plist :message-id)))
-              (existing-org-ids (gnus-registry-get-id-key msg-id 'gnorb-ids))
-              (org-id (org-capture-get :gnorb-id)))
-         (when (member org-id existing-org-ids)
-           (gnus-registry-set-id-key msg-id 'gnorb-ids
-                                     (remove org-id existing-org-ids)))
-           ;; FIXME: Yuck!  This will fail as soon as org-capture.el is compiled
-           ;; with lexical-binding.
-         (setq abort-note 'clean))
-       (error
-        (setq abort-note 'dirty)))))
+     (with-no-warnings ; For `abort-note'
+       (condition-case error
+         (let* ((msg-id (format "<%s>" (plist-get org-store-link-plist :message-id)))
+                (existing-org-ids (gnus-registry-get-id-key msg-id 'gnorb-ids))
+                (org-id (org-capture-get :gnorb-id)))
+           (when (member org-id existing-org-ids)
+             (gnus-registry-set-id-key msg-id 'gnorb-ids
+                                       (remove org-id existing-org-ids)))
+           (setq abort-note 'clean))
+       (error
+        (setq abort-note 'dirty))))))
  
  (defun gnorb-find-visit-candidates (ids &optional include-zombies)
    "For all message-ids in IDS (which should be a list of
@@@ -150,25 -146,113 +146,113 @@@ the MSG-ID.
        (gnus-registry-set-id-key msg-id 'gnorb-ids
                                (remove org-id org-ids)))))
  
- (defun gnorb-delete-all-assocations (org-id)
+ (defun gnorb-delete-all-associations (org-id)
    "Delete all message associations for an Org heading.
  
  The heading is identified by ORG-ID. This is suitable for use
  after an Org heading is deleted, for instance."
-   (let ((assoc-msgs (gnorb-registry-org-id-search org-id)))
+   (let ((assoc-msgs (gnorb-registry-org-id-search org-id))
+       (gnorb-id-tracker
+        (registry-lookup-secondary gnus-registry-db 'gnorb-ids)))
      (mapcar
       (lambda (msg-id)
         (let ((org-ids
              (gnus-registry-get-id-key msg-id 'gnorb-ids)))
         (gnus-registry-set-id-key
          msg-id 'gnorb-ids (remove org-id org-ids))))
-      assoc-msgs)))
+      assoc-msgs)
+     (remhash org-id gnorb-id-tracker)))
+ (defun gnorb-flush-dead-associations (&optional clean-archived)
+   "Clean the registry of associations with nonexistent headings.
+ Gnus will not prune registry entries that appear to be associated
+ with an Org heading.  If your registry is limited to a very small
+ size, you may end up with a full registry.  Use this function to
+ remove dead associations, and free up more entries for possible
+ pruning.
+ By default, associations are considered \"live\" if the Org
+ heading exists in an Org file or in an Org archive file.  When
+ optional CLEAN_ARCHIVED is non-nil, delete associations from
+ archived headings as well."
+   (interactive "P")
+   (let ((gnorb-id-tracker
+        (registry-lookup-secondary gnus-registry-db 'gnorb-ids))
+       (deleted-count 0))
+     (require 'org-id)
+     (maphash
+      (lambda (k _)
+        (let ((file (org-id-find-id-file k)))
+        (when (or (not file)
+                  (and clean-archived
+                       (string-match-p "org_archive$" file)))
+          (gnorb-delete-all-associations k)
+          (incf deleted-count))))
+      gnorb-id-tracker)
+     (message "Deleted %d invalid associations"
+            deleted-count)))
  
  (defun gnorb-registry-org-id-search (id)
    "Find all messages that have the org ID in their 'gnorb-ids
  key."
    (registry-search gnus-registry-db :member `((gnorb-ids ,id))))
  
+ (defun gnorb-registry-tracked-messages ()
+   "Return all message-ids that have non-empty 'gnorb-ids keys."
+   (registry-search gnus-registry-db :regex `((gnorb-ids ".+"))))
+ (defun gnorb-registry-tracked-headings ()
+   "Return all Org heading ids that are associated with messages."
+   (hash-table-keys
+    (registry-lookup-secondary gnus-registry-db 'gnorb-ids)))
+ (defun gnorb-report-tracking-usage ()
+   "Pop up a temporary window reporting on Gnorb usage of the Gnus
+ registry to track message/heading associations.  Reports the
+ number of tracked messages, the number of tracked headings, and how much of the registry is occupied."
+   (interactive)
+   (progn
+     (pop-to-buffer
+      (get-buffer-create "*Gnorb Usage*")
+      '(nil . ((window-height . 10))))
+     (gnorb-refresh-usage-status)
+     (special-mode)
+     (setq revert-buffer-function #'gnorb-refresh-usage-status)
+     (local-set-key (kbd "d") (lambda ()
+                              (interactive)
+                              (progn
+                                (gnorb-flush-dead-associations)
+                                (gnorb-refresh-usage-status))))
+     (local-set-key (kbd "D") (lambda ()
+                              (interactive)
+                              (progn
+                                (gnorb-flush-dead-associations t)
+                                (gnorb-refresh-usage-status))))))
+ (defun gnorb-refresh-usage-status (&optional ignore-auto noconfirm)
+   "Clear and re-format the *Gnorb Usage* buffer."
+   (let ((messages (length (gnorb-registry-tracked-messages)))
+       (headings (length (gnorb-registry-tracked-headings)))
+       (reg-size (registry-size gnus-registry-db))
+       (reg-max-size (oref gnus-registry-db max-size)))
+     (with-current-buffer "*Gnorb Usage*"
+       (let ((inhibit-read-only t))
+        (erase-buffer)
+        (insert
+       (format
+        "Tracking %d Gnus messages associated with %d Org headings."
+        messages headings))
+        (insert "\n\n")
+        (insert
+       (format
+        "Occupying %.2f%% (%d/%d) of the registry (max %d)."
+        (* 100 (/ (float messages) reg-size))
+        messages reg-size reg-max-size))
+        (insert "\n\n")
+        (insert "Press 'd' to delete associations for non-existent Org headings.\n")
+        (insert "Press 'D' to delete associations for both non-existent and archived Org headings.")))))
  (defun gnorb-registry-transition-from-props (arg)
    "Helper function for transitioning the old tracking system to the new.
  
index 29185a17b7b968b65d56371300de8aea61e48eaa,d7f5e8651f28a73cbb2dc6277b0716e5cea8a92f..d7f5e8651f28a73cbb2dc6277b0716e5cea8a92f
@@@ -24,6 -24,8 +24,8 @@@
  
  ;;; Code:
  
+ (require 'cl-lib)
  (require 'mailcap)
  (mailcap-parse-mimetypes)
  
@@@ -72,6 -74,11 +74,11 @@@ are sent, or Org headings triggered."
    "Return point here after various actions, to be used together
  with `gnorb-window-conf'.")
  
+ (defvar gnorb-trigger-capture-location nil
+   "Marker pointing at the location where we want to place capture
+   templates, for the capture-to-child and capture-to-sibling
+   trigger actions.")
  (defcustom gnorb-mail-header "X-Org-ID"
    "Name of the mail header used to store the ID of a related Org
    heading. Only used locally: always stripped when the mail is
@@@ -211,38 -218,32 +218,32 @@@ window.
  we were in the agenda when this was called, then keep us in the
  agenda. Then let the user choose an action from the value of
  `gnorb-org-trigger-actions'."
-   (let ((agenda-p (eq major-mode 'org-agenda-mode))
-       (action (cdr (assoc
-                     (org-completing-read
-                      "Action to take: "
-                      gnorb-org-trigger-actions nil t)
-                     gnorb-org-trigger-actions)))
-       (root-marker (make-marker)))
-     ;; Place the marker for the relevant TODO heading.
-     (cond (agenda-p
-          (setq root-marker
+   (let* ((agenda-p (eq major-mode 'org-agenda-mode))
+        (root-marker
+         (cond (agenda-p
                 (copy-marker
-                 (org-get-at-bol 'org-hd-marker))))
-         ((derived-mode-p 'org-mode)
-          (move-marker root-marker (point-at-bol)))
-         (id
-          (save-excursion
-            (org-id-goto id)
-            (move-marker root-marker (point-at-bol)))))
+                 (org-get-at-bol 'org-hd-marker)))
+               ((derived-mode-p 'org-mode)
+                (save-excursion
+                  (org-back-to-heading)
+                  (point-marker)))
+               (id
+                (save-excursion
+                  (org-id-goto id)
+                  (org-back-to-heading)
+                  (point-marker)))))
+        (id (or id
+                (org-with-point-at root-marker
+                  (org-id-get-create))))
+        (action (cdr (assoc
+                      (org-completing-read
+                       (format
+                        "Trigger action on %s: "
+                        (gnorb-pretty-outline id))
+                       gnorb-org-trigger-actions nil t)
+                      gnorb-org-trigger-actions))))
      (unless agenda-p
        (org-reveal))
-     ;; Query about attaching email attachments. No matter what
-     ;; happens, clear `gnorb-gnus-capture-attachments'.
-     (unwind-protect
-       (org-with-point-at root-marker
-         (map-y-or-n-p
-          (lambda (a)
-            (format "Attach %s to heading? "
-                    (file-name-nondirectory a)))
-          (lambda (a) (org-attach-attach a nil 'mv))
-          gnorb-gnus-capture-attachments
-          '("file" "files" "attach")))
-       (setq gnorb-gnus-capture-attachments nil))
      (cl-labels
        ((make-entry
          (id)
           id
           (plist-get gnorb-gnus-message-info :group))))
        ;; Handle our action.
-       (cond ((eq action 'note)
-            (org-with-point-at root-marker
-              (make-entry (org-id-get-create))
-              (call-interactively 'org-add-note)))
-           ((eq action 'todo)
-            (if agenda-p
-                (progn
-                  (org-with-point-at root-marker
-                   (make-entry (org-id-get-create)))
-                  (call-interactively 'org-agenda-todo))
-              (org-with-point-at root-marker
-                (make-entry (org-id-get-create))
-                (call-interactively 'org-todo))))
-           ((eq action 'no-associate)
-            nil)
-           ((eq action 'associate)
-            (org-with-point-at root-marker
-              (make-entry (org-id-get-create))))
-           ((fboundp action)
+       (if (fboundp action)
+         (org-with-point-at root-marker
+           (make-entry (org-id-get-create))
+           (funcall action gnorb-gnus-message-info))
+       (cl-case action
+         (note
+          (org-with-point-at root-marker
+            (make-entry (org-id-get-create))
+            (call-interactively 'org-add-note)))
+         (todo
+          (if agenda-p
+              (progn
+                (org-with-point-at root-marker
+                  (make-entry (org-id-get-create)))
+                (call-interactively 'org-agenda-todo))
             (org-with-point-at root-marker
               (make-entry (org-id-get-create))
-              (funcall action gnorb-gnus-message-info)))))))
+              (call-interactively 'org-todo))))
+         (no-associate
+          nil)
+         (associate
+          (org-with-point-at root-marker
+            (make-entry (org-id-get-create))))
+         ;; We're going to capture a new heading
+         ((cap-child cap-sib)
+          (org-with-point-at root-marker
+               (setq gnorb-trigger-capture-location (point-marker)))
+          (let ((entry
+                 ;; Pick a template.
+                 (copy-sequence (org-capture-select-template))))
+            ;; Do surgery on that template so that it finds its
+            ;; location using our function.
+            (setf (nth 3 entry)
+                  `(function
+                    ,(if (eq action 'cap-child)
+                         #'gnorb-trigger-capture-child
+                       #'gnorb-trigger-capture-sibling)))
+            ;; This will likely fail horribly for capture templates
+            ;; that aren't entries or list items.
+            (let ((org-capture-entry entry))
+              ;; When org-capture-entry is let-bound, the capture
+              ;; process will use that template instead of
+              ;; prompting the user. Also, `gnorb-registry-capture'
+              ;; will take care of making the registry entry for us.
+              (call-interactively 'org-capture)))))))
+     ;; Lastly, query about attaching email attachments. No matter what
+     ;; happens, clear `gnorb-gnus-capture-attachments'.
+     (unwind-protect
+       (org-with-point-at
+           (if (memq action '(cap-child cap-sib))
+               (point)
+             root-marker)
+         (map-y-or-n-p
+          (lambda (a)
+            (format "Attach %s to heading? "
+                    (file-name-nondirectory a)))
+          (lambda (a)
+            (with-demoted-errors
+                (org-attach-attach a nil 'mv)))
+          gnorb-gnus-capture-attachments
+          '("file" "files" "attach")))
+       (setq gnorb-gnus-capture-attachments nil))))
+ (defun gnorb-trigger-capture-child ()
+   ;; The capture process creates a child by default
+   (org-goto-marker-or-bmk gnorb-trigger-capture-location)
+   (org-back-to-heading))
+ (defun gnorb-trigger-capture-sibling ()
+   ;; This only works if we're not trying to create a sibling for a
+   ;; top-level heading, there appears to be no way to do that.  But in
+   ;; that case this trigger action isn't really necessary, just
+   ;; handle it with a regular capture.
+   (org-goto-marker-or-bmk gnorb-trigger-capture-location)
+   (org-up-heading-safe))
  
  (defun gnorb-pretty-outline (id &optional kw)
    "Return pretty outline path of the Org heading indicated by ID.
@@@ -383,6 -437,16 +437,16 @@@ child headings.
  ;; Common functions for extracting references and relevant headings
  ;; from the message under point. For use in gnorb-gnus.el functions.
  
+ (defun gnorb-get-real-group-name (group art-no)
+   "Find the original group name of a message in a virtual or nnir
+ group."
+   (cl-case (car (gnus-find-method-for-group group))
+     (nnvirtual
+      (setq group (car (nnvirtual-map-article art-no))))
+     (nnir
+      (setq group (nnir-article-group art-no))))
+   group)
  (defun gnorb-find-tracked-headings (headers &optional include-zombies)
    "Check HEADERS for message references and return relevant heading IDs.
  
diff --combined packages/gnorb/gnorb.el
index 22531d21018125342f2cc378deffb61ae587486e,cb7d908d7b5fe65e4b0272e1b4fe6fa069ef5194..0c9557eda728b3de58cbf0ce3ba4d730fd022963
  ;;; Code:
  
  (with-eval-after-load 'gnus
-  (require 'nngnorb)
-  (require 'gnorb-gnus)
-  (require 'gnorb-registry))
+   (require 'nngnorb)
+   (require 'gnorb-gnus)
+   (require 'gnorb-registry))
  (with-eval-after-load 'bbdb
    (require 'gnorb-bbdb))
  (with-eval-after-load 'org
-  (require 'gnorb-org))
+   (require 'gnorb-org))
  
 -
  (provide 'gnorb)
  ;;; gnorb.el ends here
index 08085e10a1b001cb12046d91b24e8344ad4f913a,52ca072707589130758c722fd0033ac614d51fdd..52ca072707589130758c722fd0033ac614d51fdd
@@@ -30,11 -30,13 +30,13 @@@ Gnorb Manua
  
  Email Tracking
  
+ * Basic Usage::
  * Email-Related Commands::
  * Trigger Actions::
  * Viewing Tracked Messages in *Summary* Buffers::
  * Hinting in Gnus::
  * Message Attachments::
+ * Registry Usage::
  * Likely Workflow::
  
  Misc BBDB
@@@ -138,29 -140,56 +140,56 @@@ IDs are associated with Org heading ids
  messages are collected on a heading (and/or its children).  You can
  compose new messages directly from the Org heading, and Gnorb will
  automatically associate your sent message with the conversation.  You
- can open temporary Gnus *Summary* buffers holding all the messages
- associated with an Org subtree, and reply from there.  When you receive
- new messages relevant to a conversation, Gnorb will notice them and
- prompt you to associate them with the appropriate Org heading.
- Attachments on incoming messages can be automatically saved as
- attachments on Org headings, using org-attach.
+ can open Gnus *Summary* buffers holding all the messages associated with
+ an Org subtree, and reply from there – these groups can be made
+ persistent, if you like.  When you receive new messages relevant to a
+ conversation, Gnorb will notice them and prompt you to associate them
+ with the appropriate Org heading.  Attachments on incoming messages can
be automatically saved as attachments on Org headings, using org-attach.
  
     In general, the goal is to keep track of whole conversations, reduce
  friction when moving between Gnus and Org, and keep you in the Org
  agenda rather than in Gnus.
  * Menu:
  
+ * Basic Usage::
  * Email-Related Commands::
  * Trigger Actions::
  * Viewing Tracked Messages in *Summary* Buffers::
  * Hinting in Gnus::
  * Message Attachments::
+ * Registry Usage::
  * Likely Workflow::
  
  \1f
- File: gnorb.info,  Node: Email-Related Commands,  Next: Trigger Actions,  Up: Email Tracking
+ File: gnorb.info,  Node: Basic Usage,  Next: Email-Related Commands,  Up: Email Tracking
+ 4.1 Basic Usage
+ ===============
+ The following sections might be a bit confusing to read if you haven’t
+ actually tried using Gnorb.  If you don’t want to dive in all the way
+ just yet, you can just dabble your toes.  First set up email tracking as
+ specified in *note Setup: Setup, then do the following:
+   1. Add “%ug” somewhere appropriate in your ‘gnus-summary-line-format’
+      variable.
+   2. If you don’t use a local archive method, add your sent message
+      groups to ‘gnorb-gnus-sent-groups’ (see the docstring).
+   3. Use Org capture from Gnus summary buffers to create reminders for
+      emails you need to reply to.
+   4. Reply to those emails by pressing “C-c t” on the TODO heading in
+      either the Agenda, or in regular Org files.
+   5. If you ever get confused about what’s associated with an Org
+      heading, press “C-c v” on the heading (works in either the Agenda,
+      or regular Org files).
+    That should be enough to get started.
  
- 4.1 Email-Related Commands
\1f
+ File: gnorb.info,  Node: Email-Related Commands,  Next: Trigger Actions,  Prev: Basic Usage,  Up: Email Tracking
+ 4.2 Email-Related Commands
  ==========================
  
  Email tracking starts in one of three ways:
    1. ‘gnorb-org-handle-mail’ is called on an Org heading to compose a
       new message.  By default, this will begin a reply to the most
       recent message in the conversation.  If there are no associated
-      messages to reply to (or you call the function with a double prefix
+      messages to reply to (or you call the function with a single prefix
       arg), Gnorb will look for mailto: or bbdb: links in the heading,
       and compose a new message to them.
  
-      The sent message will be associated with the Org heading, and
+      Calling the function with a double prefix arg will ignore all
+      associated messages and links, and compose a blank message.
+      Once sent, the message will be associated with the Org heading, and
       you’ll be brought back to the heading and asked to trigger an
       action on it.
  
       ‘gnorb-org-handle-mail’.  It does the same thing as the latter, but
       first exports the body of the subtree as either text or a file,
       then inserts the text into the message body, or attaches the file
-      to the message, depending on what you’ve chosen.
+      to the message, respectively.
    2. ‘gnorb-gnus-incoming-do-todo’ is called on a message in a Gnus
       *Summary* buffer.  You’ll be prompted for an Org heading, taken to
       that heading, and asked to trigger an action on it.
     Because these three commands all express a similar intent, but are
  called in different modes, it can make sense to give each of them the
  same keybinding in the keymaps for Org mode, Gnus summary mode, and
- Message mode, respectively.
+ Message mode.
+    An additional convenience command is available for use in Gnus
+ summary buffers: ‘gnorb-gnus-quick-reply’.  If you don’t want to go
+ through the whole round trip of triggering an action and then starting a
+ new reply, call this command on an incoming message to associate it with
+ a heading, start a reply, and associate your reply with the same
+ heading.
  
  \1f
  File: gnorb.info,  Node: Trigger Actions,  Next: Viewing Tracked Messages in *Summary* Buffers,  Prev: Email-Related Commands,  Up: Email Tracking
  
- 4.2 Trigger Actions
+ 4.3 Trigger Actions
  ===================
  
  After calling ‘gnorb-gnus-incoming-do-todo’ on a message, or after
  sending a message associated with an Org heading, you’ll be taken to the
  heading and asked to “trigger an action” on it.  At the moment there are
four different possibilities: triggering a TODO state-change on the
six different possibilities: triggering a TODO state-change on the
  heading, taking a note on the heading (both these options will associate
  the message with the heading), associating the message but doing nothing
- else, and lastly, doing nothing at all.
+ else, capturing a new Org heading as a sibling to the tracked heading,
+ capturing a new Org heading as a child, and lastly, doing nothing at
+ all.
  
-    More actions will be added in the future; it’s also possible to
+    More actions may be added in the future; it’s also possible to
  rearrange or delete existing actions, and add your own: see the
  docstring of ‘gnorb-org-trigger-actions’.
  
  \1f
  File: gnorb.info,  Node: Viewing Tracked Messages in *Summary* Buffers,  Next: Hinting in Gnus,  Prev: Trigger Actions,  Up: Email Tracking
  
- 4.3 Viewing Tracked Messages in *Summary* Buffers
+ 4.4 Viewing Tracked Messages in *Summary* Buffers
  =================================================
  
- Call ‘gnorb-org-view’ on an Org heading to open an nnir *Summary* buffer
- showing all the messages associated with that heading (this requires
- that you’ve added an nngnorb server to your Gnus backends).  A minor
- mode will be in effect, ensuring that any replies you send to messages
- in this buffer will automatically be associated with the original Org
- heading.  You can also invoke ‘gnorb-summary-disassociate-message’ (“C-c
- d”) to disassociate the message with the Org heading.
+ Call ‘gnorb-org-view’ on an Org heading to open an nnir summary buffer
+ showing all the messages associated with that heading and child headings
+ (this requires you to have added an nngnorb server to your Gnus
+ backends).  A minor mode is in effect, ensuring that any replies you
+ send to messages in this buffer will automatically be associated with
+ the original Org heading.  You can also invoke
+ ‘gnorb-summary-disassociate-message’ (“C-c d”) to disassociate the
+ message with the Org heading.
+    If you call ‘gnorb-org-view’ with a prefix argument, the search group
+ will be made persistent across Gnus sessions.  You can re-run the search
+ and update the group contents by hitting “M-g” on the group in the Gnus
+ *Group* buffer.
  
     As a bonus, it’s possible to go into Gnus’ *Server* buffer, find the
  line specifying your nngnorb server, and hit “G” (aka
@@@ -263,7 -310,7 +310,7 @@@ linked messages.  This is dog-slow at t
  \1f
  File: gnorb.info,  Node: Hinting in Gnus,  Next: Message Attachments,  Prev: Viewing Tracked Messages in *Summary* Buffers,  Up: Email Tracking
  
- 4.4 Hinting in Gnus
+ 4.5 Hinting in Gnus
  ===================
  
  When you receive new mails that might be relevant to existing Org TODOs,
@@@ -273,18 -320,19 +320,19 @@@ display a message in the minibuffer whe
  messages.  You can then use ‘gnorb-gnus-incoming-to-todo’ to trigger an
  action on the relevant TODO.
  
-    This hinting can happen in the Gnus summary buffer as well.  If you
- use the escape indicated by ‘gnorb-gnus-summary-mark-format-letter” as
- part of your ‘gnus-summary-line-format’, articles that are relevant to
- TODOs will be marked with a special character in the Summary buffer, as
- determined by ‘gnorb-gnus-summary-mark’.  By default, the format letter
- is “g” (meaning it is used as “%ug” in the format line), and the mark is
- “¡”.
+    This hinting can happen in the Gnus summary buffer as well. If you
+ use the escape indicated by ‘gnorb-gnus-summary-mark-format-letter’ as
+ part of your ‘gnus-summary-line-format’, articles that may be relevant
+ to TODOs will be marked with a special character in the Summary
+ buffer, as determined by ‘gnorb-gnus-summary-mark’. By default, the
+ format letter is “g” (meaning it is used as “%ug” in the format line),
+ and the mark is “&” for messages that are already tracked, and “¡” for
+ messages that may be relevant.
  
  \1f
- File: gnorb.info,  Node: Message Attachments,  Next: Likely Workflow,  Prev: Hinting in Gnus,  Up: Email Tracking
+ File: gnorb.info,  Node: Message Attachments,  Next: Registry Usage,  Prev: Hinting in Gnus,  Up: Email Tracking
  
- 4.5 Message Attachments
+ 4.6 Message Attachments
  =======================
  
  Gnorb simplifies the handling of attachments that you receive in emails.
@@@ -309,9 -357,21 +357,21 @@@ attach the files in the heading’s org
  message.
  
  \1f
- File: gnorb.info,  Node: Likely Workflow,  Prev: Message Attachments,  Up: Email Tracking
+ File: gnorb.info,  Node: Registry Usage,  Next: Likely Workflow,  Prev: Message Attachments,  Up: Email Tracking
+ 4.7 Registry Usage
+ ==================
+ You can see how many associations you’ve got stored in the registry by
+ calling ‘gnorb-report-tracking-usage’.  This will pop up a buffer
+ showing how much of the registry you’re using, and offering keybindings
+ for ‘gnorb-flush-dead-associations’, to help Gnorb clean up after
+ itself.
\1f
+ File: gnorb.info,  Node: Likely Workflow,  Prev: Registry Usage,  Up: Email Tracking
  
- 4.6 Likely Workflow
+ 4.8 Likely Workflow
  ===================
  
  You receive an email from Jimmy, who wants to rent a room in your house.
@@@ -635,9 -695,13 +695,13 @@@ File: gnorb.info,  Node: User Optionsxx
       relevant to Org TODOs.  Defaults to “g”, meaning it should be used
       as “%ug” in the format line.
  ‘`gnorb-gnus-summary-mark'’
-      The mark used to indicate relevant messages in the Summary buffer,
-      when ‘gnorb-gnus-summary-mark-format-letter’ is present in the
-      format line.  Defaults to “¡”.
+      The mark used to indicate potentially relevant messages in the
+      Summary buffer, when ‘gnorb-gnus-summary-mark-format-letter’ is
+      present in the format line.  Defaults to “¡”.
+ ‘`gnorb-gnus-summary-tracked-mark'’
+      The mark used to indicate already-tracked messages in the Summary
+      buffer, when ‘gnorb-gnus-summary-mark-format-letter’ is present in
+      the format line.  Defaults to “&”.
  
  \1f
  File: gnorb.info,  Node: Suggested Keybindings,  Prev: Misc Gnus,  Up: Top
            (org-defkey org-mode-map (kbd "C-c V") 'gnorb-org-popup-bbdb)
            (setq gnorb-org-agenda-popup-bbdb t)
            (eval-after-load "org-agenda"
-             '(progn (org-defkey org-agenda-mode-map (kbd "H") 'gnorb-org-handle-mail)
-                     (org-defkey org-agenda-mode-map (kbd "V") 'gnorb-org-popup-bbdb)))))
+             '(progn (org-defkey org-agenda-mode-map (kbd "C-c t") 'gnorb-org-handle-mail)
+                     (org-defkey org-agenda-mode-map (kbd "C-c v") 'gnorb-org-popup-bbdb)
+                     (org-defkey org-agenda-mode-map (kbd "V") 'gnorb-org-view)))))
  
       (eval-after-load "gnorb-gnus"
         '(progn
  \1f
  Tag Table:
  Node: Top\7f194
- Node: Introduction\7f1009
- Node: Installation\7f2118
- Node: Setup\7f2532
- Node: Email Tracking\7f3899
- Node: Email-Related Commands\7f5430
- Node: Trigger Actions\7f8440
- Node: Viewing Tracked Messages in *Summary* Buffers\7f9289
- Node: Hinting in Gnus\7f10523
- Node: Message Attachments\7f11531
- Node: Likely Workflow\7f12713
- Node: Restoring Window Layout\7f15518
- Node: Recent Mails From BBDB Contacts\7f15882
- Node: BBDB posting styles\7f16878
- Node: BBDB Org tagging\7f17794
- Node: Misc BBDB\7f18540
- Node: Searching for messages from BBDB contacts\7f18753
- Node: Citing BBDB contacts\7f19199
- Node: User Options\7f19520
- Node: Misc Org\7f21059
- Node: Inserting BBDB links\7f21234
- Node: User Optionsx\7f21489
- Node: Misc Gnus\7f24226
- Node: Viewing Org headlines relevant to a message\7f24439
- Node: User Optionsxx\7f24754
- Node: Suggested Keybindings\7f27518
+ Node: Introduction\7f1044
+ Node: Installation\7f2153
+ Node: Setup\7f2567
+ Node: Email Tracking\7f3934
+ Node: Basic Usage\7f5544
+ Node: Email-Related Commands\7f6617
+ Node: Trigger Actions\7f10112
+ Node: Viewing Tracked Messages in *Summary* Buffers\7f11064
+ Node: Hinting in Gnus\7f12551
+ Node: Message Attachments\7f13647
+ Node: Registry Usage\7f14828
+ Node: Likely Workflow\7f15279
+ Node: Restoring Window Layout\7f18079
+ Node: Recent Mails From BBDB Contacts\7f18443
+ Node: BBDB posting styles\7f19439
+ Node: BBDB Org tagging\7f20355
+ Node: Misc BBDB\7f21101
+ Node: Searching for messages from BBDB contacts\7f21314
+ Node: Citing BBDB contacts\7f21760
+ Node: User Options\7f22081
+ Node: Misc Org\7f23620
+ Node: Inserting BBDB links\7f23795
+ Node: User Optionsx\7f24050
+ Node: Misc Gnus\7f26787
+ Node: Viewing Org headlines relevant to a message\7f27000
+ Node: User Optionsxx\7f27315
+ Node: Suggested Keybindings\7f30322
  \1f
  End Tag Table
  
diff --combined packages/gnorb/gnorb.org
index e19422d874bb5d1c3433b621f7b300e700be3c80,58b03658a910e4f3672fd8c9d56962379a5084be..58b03658a910e4f3672fd8c9d56962379a5084be
@@@ -35,6 -35,9 +35,9 @@@ https://github.com/girzel/gnorb, and pu
  load-path. The Github site is also a good place to report bugs and
  other issues.
  * Setup
+ :PROPERTIES:
+ :ID:       9da59609-bb3c-4970-88f6-bddca18d2ad4
+ :END:
  Loading "gnorb" will make the basic functions available. Using Gnorb
  for email tracking takes a bit more setup, however:
  
@@@ -68,16 -71,36 +71,36 @@@ message IDs are associated with Org hea
  develops, messages are collected on a heading (and/or its children).
  You can compose new messages directly from the Org heading, and Gnorb
  will automatically associate your sent message with the conversation.
- You can open temporary Gnus *Summary* buffers holding all the messages
- associated with an Org subtree, and reply from there. When you receive
- new messages relevant to a conversation, Gnorb will notice them and
- prompt you to associate them with the appropriate Org heading.
- Attachments on incoming messages can be automatically saved as
- attachments on Org headings, using org-attach.
+ You can open Gnus *Summary* buffers holding all the messages
+ associated with an Org subtree, and reply from there -- these groups
+ can be made persistent, if you like. When you receive new messages
+ relevant to a conversation, Gnorb will notice them and prompt you to
+ associate them with the appropriate Org heading. Attachments on
+ incoming messages can be automatically saved as attachments on Org
+ headings, using org-attach.
  
  In general, the goal is to keep track of whole conversations, reduce
  friction when moving between Gnus and Org, and keep you in the Org
  agenda rather than in Gnus.
+ ** Basic Usage
+ The following sections might be a bit confusing to read if you haven't
+ actually tried using Gnorb. If you don't want to dive in all the way
+ just yet, you can just dabble your toes. First set up email tracking
+ as specified in [[id:9da59609-bb3c-4970-88f6-bddca18d2ad4][Setup]], then do the following:
+ 1. Add "%ug" somewhere appropriate in your `gnus-summary-line-format'
+    variable.
+ 2. If you don't use a local archive method, add your sent message
+    groups to `gnorb-gnus-sent-groups' (see the docstring).
+ 3. Use Org capture from Gnus summary buffers to create reminders for
+    emails you need to reply to.
+ 4. Reply to those emails by pressing "C-c t" on the TODO heading in
+    either the Agenda, or in regular Org files.
+ 5. If you ever get confused about what's associated with an Org
+    heading, press "C-c v" on the heading (works in either the Agenda,
+    or regular Org files).
+ That should be enough to get started.
  ** Email-Related Commands
  Email tracking starts in one of three ways:
  
@@@ -94,11 -117,14 +117,14 @@@ There are three main email-related comm
  1. `gnorb-org-handle-mail' is called on an Org heading to compose a
     new message. By default, this will begin a reply to the most recent
     message in the conversation. If there are no associated messages to
-    reply to (or you call the function with a double prefix arg), Gnorb
+    reply to (or you call the function with a single prefix arg), Gnorb
     will look for mailto: or bbdb: links in the heading, and compose a
     new message to them.
+    Calling the function with a double prefix arg will ignore all
+    associated messages and links, and compose a blank message.
     
-    The sent message will be associated with the Org heading, and
+    Once sent, the message will be associated with the Org heading, and
     you'll be brought back to the heading and asked to trigger an
     action on it.
     
     `gnorb-org-handle-mail'. It does the same thing as the latter, but
     first exports the body of the subtree as either text or a file,
     then inserts the text into the message body, or attaches the file
-    to the message, depending on what you've chosen.
+    to the message, respectively.
  2. `gnorb-gnus-incoming-do-todo' is called on a message in a Gnus
     *Summary* buffer. You'll be prompted for an Org heading, taken to
     that heading, and asked to trigger an action on it.
  Because these three commands all express a similar intent, but are
  called in different modes, it can make sense to give each of them the
  same keybinding in the keymaps for Org mode, Gnus summary mode, and
- Message mode, respectively.
+ Message mode.
+ An additional convenience command is available for use in Gnus summary
+ buffers: `gnorb-gnus-quick-reply'. If you don't want to go through the
+ whole round trip of triggering an action and then starting a new
+ reply, call this command on an incoming message to associate it with a
+ heading, start a reply, and associate your reply with the same
+ heading.
  ** Trigger Actions
  After calling `gnorb-gnus-incoming-do-todo' on a message, or after
  sending a message associated with an Org heading, you'll be taken to
  the heading and asked to "trigger an action" on it. At the moment
- there are four different possibilities: triggering a TODO state-change
+ there are six different possibilities: triggering a TODO state-change
  on the heading, taking a note on the heading (both these options will
  associate the message with the heading), associating the message but
- doing nothing else, and lastly, doing nothing at all.
+ doing nothing else, capturing a new Org heading as a sibling to the
+ tracked heading, capturing a new Org heading as a child, and lastly,
+ doing nothing at all.
  
- More actions will be added in the future; it's also possible to
+ More actions may be added in the future; it's also possible to
  rearrange or delete existing actions, and add your own: see the
  docstring of `gnorb-org-trigger-actions'.
  ** Viewing Tracked Messages in *Summary* Buffers
  :PROPERTIES:
  :END:
- Call `gnorb-org-view' on an Org heading to open an nnir *Summary*
- buffer showing all the messages associated with that heading (this
- requires that you've added an nngnorb server to your Gnus backends). A
- minor mode will be in effect, ensuring that any replies you send to
- messages in this buffer will automatically be associated with the
- original Org heading. You can also invoke
+ Call `gnorb-org-view' on an Org heading to open an nnir summary buffer
+ showing all the messages associated with that heading and child
+ headings (this requires you to have added an nngnorb server to your
+ Gnus backends). A minor mode is in effect, ensuring that any replies
+ you send to messages in this buffer will automatically be associated
with the original Org heading. You can also invoke
  `gnorb-summary-disassociate-message' ("C-c d") to disassociate the
  message with the Org heading.
  
+ If you call `gnorb-org-view' with a prefix argument, the search group
+ will be made persistent across Gnus sessions. You can re-run the
+ search and update the group contents by hitting "M-g" on the group in
+ the Gnus *Group* buffer.
  As a bonus, it's possible to go into Gnus' *Server* buffer, find the
  line specifying your nngnorb server, and hit "G" (aka
  `gnus-group-make-nnir-group'). At the query prompt, enter an Org-style
@@@ -179,11 -219,12 +219,12 @@@ action on the relevant TODO
  
  This hinting can happen in the Gnus summary buffer as well. If you use
  the escape indicated by `gnorb-gnus-summary-mark-format-letter" as
- part of your `gnus-summary-line-format', articles that are relevant to
- TODOs will be marked with a special character in the Summary buffer,
- as determined by `gnorb-gnus-summary-mark'. By default, the format
- letter is "g" (meaning it is used as "%ug" in the format line), and
- the mark is "¡".
+ part of your `gnus-summary-line-format', articles that may be relevant
+ to TODOs will be marked with a special character in the Summary
+ buffer, as determined by `gnorb-gnus-summary-mark'. By default, the
+ format letter is "g" (meaning it is used as "%ug" in the format line),
+ and the mark is "&" for messages that are already tracked, and "¡" for
+ messages that may be relevant.
  ** Message Attachments
  :PROPERTIES:
  :END:
@@@ -207,6 -248,12 +248,12 @@@ The same process works in reverse: whe
  heading using `gnorb-org-handle-mail', Gnorb will ask if you want to
  attach the files in the heading's org-attach directory to the outgoing
  message.
+ ** Registry Usage
+ You can see how many associations you've got stored in the registry by
+ calling `gnorb-report-tracking-usage'. This will pop up a buffer
+ showing how much of the registry you're using, and offering
+ keybindings for `gnorb-flush-dead-associations', to help Gnorb clean
+ up after itself.
  ** Likely Workflow
  You receive an email from Jimmy, who wants to rent a room in your
  house. "I'll respond to this later," you think.
@@@ -437,10 -484,14 +484,14 @@@ heading to jump to that heading
       use as part of your `gnus-summary-line-format', to indicate
       messages which might be relevant to Org TODOs. Defaults to "g",
       meaning it should be used as "%ug" in the format line.
- - `gnorb-gnus-summary-mark' :: The mark used to indicate relevant
-      messages in the Summary buffer, when
+ - `gnorb-gnus-summary-mark' :: The mark used to indicate potentially
+      relevant messages in the Summary buffer, when
       `gnorb-gnus-summary-mark-format-letter' is present in the format
       line. Defaults to "¡".
+ - `gnorb-gnus-summary-tracked-mark' :: The mark used to indicate
+      already-tracked messages in the Summary buffer, when
+      `gnorb-gnus-summary-mark-format-letter' is present in the format
+      line. Defaults to "&".
  * Suggested Keybindings
  :PROPERTIES:
  :ID:       de1b2579-86c2-4bb1-b77e-3467a3d2b3c7
         (org-defkey org-mode-map (kbd "C-c V") 'gnorb-org-popup-bbdb)
         (setq gnorb-org-agenda-popup-bbdb t)
         (eval-after-load "org-agenda"
-          '(progn (org-defkey org-agenda-mode-map (kbd "H") 'gnorb-org-handle-mail)
-                  (org-defkey org-agenda-mode-map (kbd "V") 'gnorb-org-popup-bbdb)))))
+          '(progn (org-defkey org-agenda-mode-map (kbd "C-c t") 'gnorb-org-handle-mail)
+                  (org-defkey org-agenda-mode-map (kbd "C-c v") 'gnorb-org-popup-bbdb)
+                  (org-defkey org-agenda-mode-map (kbd "V") 'gnorb-org-view)))))
  
    (eval-after-load "gnorb-gnus"
      '(progn
index f1fccc5cb2760a6d3f5f560eec56be0cd79cbd9e,cdd75762ffa7cf80c05deaa3fd32d5ee621de87c..cdd75762ffa7cf80c05deaa3fd32d5ee621de87c
  
  Email Tracking
  
+ * Basic Usage::
  * Email-Related Commands::
  * Trigger Actions::
  * Viewing Tracked Messages in *Summary* Buffers::
  * Hinting in Gnus::
  * Message Attachments::
+ * Registry Usage::
  * Likely Workflow::
  
  Misc BBDB
@@@ -146,25 -148,57 +148,57 @@@ message IDs are associated with Org hea
  develops, messages are collected on a heading (and/or its children).
  You can compose new messages directly from the Org heading, and Gnorb
  will automatically associate your sent message with the conversation.
- You can open temporary Gnus *Summary* buffers holding all the messages
- associated with an Org subtree, and reply from there. When you receive
- new messages relevant to a conversation, Gnorb will notice them and
- prompt you to associate them with the appropriate Org heading.
- Attachments on incoming messages can be automatically saved as
- attachments on Org headings, using org-attach.
+ You can open Gnus *Summary* buffers holding all the messages
+ associated with an Org subtree, and reply from there -- these groups
+ can be made persistent, if you like. When you receive new messages
+ relevant to a conversation, Gnorb will notice them and prompt you to
+ associate them with the appropriate Org heading. Attachments on
+ incoming messages can be automatically saved as attachments on Org
+ headings, using org-attach.
  
  In general, the goal is to keep track of whole conversations, reduce
  friction when moving between Gnus and Org, and keep you in the Org
  agenda rather than in Gnus.
  @menu
+ * Basic Usage::
  * Email-Related Commands::
  * Trigger Actions::
  * Viewing Tracked Messages in *Summary* Buffers::
  * Hinting in Gnus::
  * Message Attachments::
+ * Registry Usage::
  * Likely Workflow::
  @end menu
  
+ @node Basic Usage
+ @section Basic Usage
+ The following sections might be a bit confusing to read if you haven't
+ actually tried using Gnorb. If you don't want to dive in all the way
+ just yet, you can just dabble your toes. First set up email tracking
+ as specified in @ref{Setup,Setup}, then do the following:
+ @enumerate
+ @item
+ Add ``%ug'' somewhere appropriate in your `gnus-summary-line-format'
+ variable.
+ @item
+ If you don't use a local archive method, add your sent message
+ groups to `gnorb-gnus-sent-groups' (see the docstring).
+ @item
+ Use Org capture from Gnus summary buffers to create reminders for
+ emails you need to reply to.
+ @item
+ Reply to those emails by pressing ``C-c t'' on the TODO heading in
+ either the Agenda, or in regular Org files.
+ @item
+ If you ever get confused about what's associated with an Org
+ heading, press ``C-c v'' on the heading (works in either the Agenda,
+ or regular Org files).
+ @end enumerate
+ That should be enough to get started.
  @node Email-Related Commands
  @section Email-Related Commands
  
@@@ -190,11 -224,14 +224,14 @@@ There are three main email-related comm
  `gnorb-org-handle-mail' is called on an Org heading to compose a
  new message. By default, this will begin a reply to the most recent
  message in the conversation. If there are no associated messages to
- reply to (or you call the function with a double prefix arg), Gnorb
+ reply to (or you call the function with a single prefix arg), Gnorb
  will look for mailto: or bbdb: links in the heading, and compose a
  new message to them.
  
- The sent message will be associated with the Org heading, and
+ Calling the function with a double prefix arg will ignore all
+ associated messages and links, and compose a blank message.
+ Once sent, the message will be associated with the Org heading, and
  you'll be brought back to the heading and asked to trigger an
  action on it.
  
  `gnorb-org-handle-mail'. It does the same thing as the latter, but
  first exports the body of the subtree as either text or a file,
  then inserts the text into the message body, or attaches the file
- to the message, depending on what you've chosen.
+ to the message, respectively.
  @item
  `gnorb-gnus-incoming-do-todo' is called on a message in a Gnus
  *Summary* buffer. You'll be prompted for an Org heading, taken to
@@@ -233,7 -270,14 +270,14 @@@ sent message for this purpose
  Because these three commands all express a similar intent, but are
  called in different modes, it can make sense to give each of them the
  same keybinding in the keymaps for Org mode, Gnus summary mode, and
- Message mode, respectively.
+ Message mode.
+ An additional convenience command is available for use in Gnus summary
+ buffers: `gnorb-gnus-quick-reply'. If you don't want to go through the
+ whole round trip of triggering an action and then starting a new
+ reply, call this command on an incoming message to associate it with a
+ heading, start a reply, and associate your reply with the same
+ heading.
  
  @node Trigger Actions
  @section Trigger Actions
  After calling `gnorb-gnus-incoming-do-todo' on a message, or after
  sending a message associated with an Org heading, you'll be taken to
  the heading and asked to ``trigger an action'' on it. At the moment
- there are four different possibilities: triggering a TODO state-change
+ there are six different possibilities: triggering a TODO state-change
  on the heading, taking a note on the heading (both these options will
  associate the message with the heading), associating the message but
- doing nothing else, and lastly, doing nothing at all.
+ doing nothing else, capturing a new Org heading as a sibling to the
+ tracked heading, capturing a new Org heading as a child, and lastly,
+ doing nothing at all.
  
- More actions will be added in the future; it's also possible to
+ More actions may be added in the future; it's also possible to
  rearrange or delete existing actions, and add your own: see the
  docstring of `gnorb-org-trigger-actions'.
  
  @node Viewing Tracked Messages in *Summary* Buffers
  @section Viewing Tracked Messages in *Summary* Buffers
  
- Call `gnorb-org-view' on an Org heading to open an nnir *Summary*
- buffer showing all the messages associated with that heading (this
- requires that you've added an nngnorb server to your Gnus backends). A
- minor mode will be in effect, ensuring that any replies you send to
- messages in this buffer will automatically be associated with the
- original Org heading. You can also invoke
+ Call `gnorb-org-view' on an Org heading to open an nnir summary buffer
+ showing all the messages associated with that heading and child
+ headings (this requires you to have added an nngnorb server to your
+ Gnus backends). A minor mode is in effect, ensuring that any replies
+ you send to messages in this buffer will automatically be associated
with the original Org heading. You can also invoke
  `gnorb-summary-disassociate-message' (``C-c d'') to disassociate the
  message with the Org heading.
  
+ If you call `gnorb-org-view' with a prefix argument, the search group
+ will be made persistent across Gnus sessions. You can re-run the
+ search and update the group contents by hitting ``M-g'' on the group in
+ the Gnus *Group* buffer.
  As a bonus, it's possible to go into Gnus' *Server* buffer, find the
  line specifying your nngnorb server, and hit ``G'' (aka
  `gnus-group-make-nnir-group'). At the query prompt, enter an Org-style
@@@ -281,12 -332,13 +332,13 @@@ messages. You can then use `gnorb-gnus-
  action on the relevant TODO.
  
  This hinting can happen in the Gnus summary buffer as well. If you use
- the escape indicated by `gnorb-gnus-summary-mark-format-letter'' as
- part of your `gnus-summary-line-format', articles that are relevant to
- TODOs will be marked with a special character in the Summary buffer,
- as determined by `gnorb-gnus-summary-mark'. By default, the format
- letter is ``g'' (meaning it is used as ``%ug'' in the format line), and
- the mark is ``¡''.
+ the escape indicated by `gnorb-gnus-summary-mark-format-letter`` as
+ part of your `gnus-summary-line-format', articles that may be relevant
+ to TODOs will be marked with a special character in the Summary
+ buffer, as determined by `gnorb-gnus-summary-mark'. By default, the
+ format letter is ``g'' (meaning it is used as ``%ug'' in the format line),
+ and the mark is ``&'' for messages that are already tracked, and ``¡'' for
+ messages that may be relevant.
  
  @node Message Attachments
  @section Message Attachments
@@@ -312,6 -364,15 +364,15 @@@ heading using `gnorb-org-handle-mail', 
  attach the files in the heading's org-attach directory to the outgoing
  message.
  
+ @node Registry Usage
+ @section Registry Usage
+ You can see how many associations you've got stored in the registry by
+ calling `gnorb-report-tracking-usage'. This will pop up a buffer
+ showing how much of the registry you're using, and offering
+ keybindings for `gnorb-flush-dead-associations', to help Gnorb clean
+ up after itself.
  @node Likely Workflow
  @section Likely Workflow
  
@@@ -618,10 -679,15 +679,15 @@@ use as part of your `gnus-summary-line-
  messages which might be relevant to Org TODOs. Defaults to ``g'',
  meaning it should be used as ``%ug'' in the format line.
  @item `gnorb-gnus-summary-mark'
- The mark used to indicate relevant
- messages in the Summary buffer, when
+ The mark used to indicate potentially
relevant messages in the Summary buffer, when
  `gnorb-gnus-summary-mark-format-letter' is present in the format
  line. Defaults to ``¡''.
+ @item `gnorb-gnus-summary-tracked-mark'
+ The mark used to indicate
+ already-tracked messages in the Summary buffer, when
+ `gnorb-gnus-summary-mark-format-letter' is present in the format
+ line. Defaults to ``&''.
  @end table
  
  @node Suggested Keybindings
       (org-defkey org-mode-map (kbd "C-c V") 'gnorb-org-popup-bbdb)
       (setq gnorb-org-agenda-popup-bbdb t)
       (eval-after-load "org-agenda"
-        '(progn (org-defkey org-agenda-mode-map (kbd "H") 'gnorb-org-handle-mail)
-                (org-defkey org-agenda-mode-map (kbd "V") 'gnorb-org-popup-bbdb)))))
+        '(progn (org-defkey org-agenda-mode-map (kbd "C-c t") 'gnorb-org-handle-mail)
+                (org-defkey org-agenda-mode-map (kbd "C-c v") 'gnorb-org-popup-bbdb)
+                (org-defkey org-agenda-mode-map (kbd "V") 'gnorb-org-view)))))
  
  (eval-after-load "gnorb-gnus"
    '(progn
       (define-key message-mode-map (kbd "C-c t") 'gnorb-gnus-outgoing-do-todo)))
  @end lisp
  
- @c Emacs 25.0.50.8 (Org mode 8.3beta)
- @bye
+ @bye
+ @c Local Variables:
+ @c mode: texinfo
+ @c TeX-master: t
+ @c End:
index d1ed896556e0336bf0f30e9e04423db460eebaae,9d03e14ad33d6cf7a571cad366dc1de06ac75d6e..9d03e14ad33d6cf7a571cad366dc1de06ac75d6e
@@@ -52,7 -52,7 +52,7 @@@
  
  (make-variable-buffer-local 'nngnorb-attachment-file-list)
  
- (gnus-declare-backend "nngnorb" 'none)
+ (gnus-declare-backend "nngnorb" 'post-mail 'virtual)
  
  (add-to-list 'nnir-method-default-engines '(nngnorb . gnorb))
  
@@@ -79,14 -79,14 +79,14 @@@ be scanned for gnus messages, and thos
    ;; a property, and the new registry-based system, we're going to use
    ;; both methods to collect relevant messages. This could be a little
    ;; slower, but for the time being it will be safer.
-   (save-excursion
+   (save-window-excursion
      (let ((q (cdr (assq 'query query)))
          (buf (get-buffer-create nnir-tmp-buffer))
          msg-ids org-ids links vectors)
        (with-current-buffer buf
        (erase-buffer)
        (setq nngnorb-attachment-file-list nil))
-       (when (equal "5.13" gnus-version-number)
+       (when (and (equal "5.13" gnus-version-number) (version< emacs-version "24.4"))
        (setq q (car q)))
        (cond ((string-match "id\\+\\([[:alnum:]-]+\\)$" q)
             (with-demoted-errors "Error: %S"
        (dolist (i (delq nil org-ids))
        (let ((rel-msg-id (gnorb-registry-org-id-search i)))
          (when rel-msg-id
-           (setq msg-ids (append rel-msg-id msg-ids)))))
+           (setq msg-ids (append (delq nil rel-msg-id) msg-ids)))))
        (when msg-ids
          (dolist (id msg-ids)
            (let ((link (gnorb-msg-id-to-link id)))
@@@ -278,8 -278,12 +278,12 @@@ continue to provide tracking of sent me
        (message-insert-header
         (intern gnorb-mail-header)
         org-id)
-       (add-to-list 'message-exit-actions
-                    'gnorb-org-restore-after-send t))
+       ;; As with elsewhere, this should be redundant with
+       ;; `gnorb-gnus-check-outgoing-headers.'  Even if not, it
+       ;; should be switched to use `message-send-actions'
+       ;; (add-to-list 'message-exit-actions
+       ;; 'gnorb-org-restore-after-send t)
+       )
        (goto-char compose-marker))
      (when attachments
        (map-y-or-n-p
@@@ -309,7 -313,7 +313,7 @@@ the message being included in this sear
       (gnus-summary-article-number)))
    (let* ((msg-id (gnus-fetch-original-field "message-id"))
         (org-ids (gnus-registry-get-id-key msg-id 'gnorb-ids))
-        chosen)
+        chosen multiple-alist)
      (if org-ids
        (progn
          (if (= (length org-ids) 1)
              (progn (gnus-registry-set-id-key msg-id 'gnorb-ids nil)
                     (setq chosen (car org-ids)))
            ;; Multiple associated TODOs, prompt to choose one.
+           (setq multiple-alist
+                 (mapcar
+                  (lambda (h)
+                    (cons (gnorb-pretty-outline h) h))
+                  org-ids))
            (setq chosen
                  (cdr
-                  (org-completing-read
-                   "Choose a TODO to disassociate from: "
-                   (mapcar
-                    (lambda (h)
-                      (cons (gnorb-pretty-outline h) h))
-                    org-ids))))
+                  (assoc
+                   (org-completing-read
+                    "Choose a TODO to disassociate from: "
+                    multiple-alist)
+                   multiple-alist)))
            (gnus-registry-set-id-key msg-id 'gnorb-ids
                                      (remove chosen org-ids)))
          (message "Message disassociated from %s"