[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.9 Threading

Gnus threads articles by default. To thread is to put responses to articles directly after the articles they respond to—in a hierarchical fashion.

Threading is done by looking at the References headers of the articles. In a perfect world, this would be enough to build pretty trees, but unfortunately, the References header is often broken or simply missing. Weird news propagation exacerbates the problem, so one has to employ other heuristics to get pleasing results. A plethora of approaches exists, as detailed in horrible detail in Customizing Threading.

First, a quick overview of the concepts:


The top-most article in a thread; the first article in the thread.


A tree-like article structure.


A small(er) section of this tree-like structure.

loose threads

Threads often lose their roots due to article expiry, or due to the root already having been read in a previous session, and not displayed in the summary buffer. We then typically have many sub-threads that really belong to one thread, but are without connecting roots. These are called loose threads.

thread gathering

An attempt to gather loose threads into bigger threads.

sparse threads

A thread where the missing articles have been “guessed” at, and are displayed as empty lines in the summary buffer.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.9.1 Customizing Threading

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Loose Threads


If non-nil, Gnus will gather all loose subtrees into one big tree and create a dummy root at the top. (Wait a minute. Root at the top? Yup.) Loose subtrees occur when the real root has expired, or you’ve read or killed the root in a previous session.

When there is no real root of a thread, Gnus will have to fudge something. This variable says what fudging method Gnus should use. There are four possible values:


Gnus will make the first of the orphaned articles the parent. This parent will adopt all the other articles. The adopted articles will be marked as such by pointy brackets (‘<>’) instead of the standard square brackets (‘[]’). This is the default method.


Gnus will create a dummy summary line that will pretend to be the parent. This dummy line does not correspond to any real article, so selecting it will just select the first real article after the dummy article. gnus-summary-dummy-line-format is used to specify the format of the dummy roots. It accepts only one format spec: ‘S’, which is the subject of the article. See section Formatting Variables. If you want all threads to have a dummy root, even the non-gathered ones, set gnus-summary-make-false-root-always to t.


Gnus won’t actually make any article the parent, but simply leave the subject field of all orphans except the first empty. (Actually, it will use gnus-summary-same-subject as the subject (see section Summary Buffer Format).)


Don’t make any article parent at all. Just gather the threads and display them after one another.


Don’t gather loose threads.


Loose threads are gathered by comparing subjects of articles. If this variable is nil, Gnus requires an exact match between the subjects of the loose threads before gathering them into one big super-thread. This might be too strict a requirement, what with the presence of stupid newsreaders that chop off long subject lines. If you think so, set this variable to, say, 20 to require that only the first 20 characters of the subjects have to match. If you set this variable to a really low number, you’ll find that Gnus will gather everything in sight into one thread, which isn’t very helpful.

If you set this variable to the special value fuzzy, Gnus will use a fuzzy string comparison algorithm on the subjects (see section Fuzzy Matching).


This can either be a regular expression or list of regular expressions that match strings that will be removed from subjects if fuzzy subject simplification is used.


If you set gnus-summary-gather-subject-limit to something as low as 10, you might consider setting this variable to something sensible:

(setq gnus-simplify-ignored-prefixes
          "wanted" "followup" "summary\\( of\\)?"
          "help" "query" "problem" "question"
          "answer" "reference" "announce"
          "How can I" "How to" "Comparison of"
          ;; ...
       "\\)\\s *\\("
       (mapconcat 'identity
                  '("for" "for reference" "with" "about")
       "\\)?\\]?:?[ \t]*"))

All words that match this regexp will be removed before comparing two subjects.


If non-nil, this variable overrides gnus-summary-gather-subject-limit. This variable should be a list of functions to apply to the Subject string iteratively to arrive at the simplified version of the string.

Useful functions to put in this list include:


Strip the leading ‘Re:’.


Simplify fuzzily.


Remove excessive whitespace.


Remove all whitespace.

You may also write your own functions, of course.


Since loose thread gathering is done on subjects only, that might lead to many false hits, especially with certain common subjects like ‘’ and ‘(none)’. To make the situation slightly better, you can use the regexp gnus-summary-gather-exclude-subject to say what subjects should be excluded from the gathering process.
The default is ‘^ *$\\|^(none)$’.


Gnus gathers threads by looking at Subject headers. This means that totally unrelated articles may end up in the same “thread”, which is confusing. An alternate approach is to look at all the Message-IDs in all the References headers to find matches. This will ensure that no gathered threads ever include unrelated articles, but it also means that people who have posted with broken newsreaders won’t be gathered properly. The choice is yours—plague or cholera:


This function is the default gathering function and looks at Subjects exclusively.


This function looks at References headers exclusively.

If you want to test gathering by References, you could say something like:

(setq gnus-summary-thread-gathering-function

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Filling In Threads


If non-nil, Gnus will attempt to build old threads by fetching more old headers—headers to articles marked as read. If you would like to display as few summary lines as possible, but still connect as many loose threads as possible, you should set this variable to some or a number. If you set it to a number, no more than that number of extra old headers will be fetched. In either case, fetching old headers only works if the back end you are using carries overview files—this would normally be nntp, nnspool, nnml, and nnmaildir. Also remember that if the root of the thread has been expired by the server, there’s not much Gnus can do about that.

This variable can also be set to invisible. This won’t have any visible effects, but is useful if you use the A T command a lot (see section Finding the Parent).

The server has to support NOV for any of this to work.

This feature can seriously impact performance it ignores all locally cached header entries. Setting it to t for groups for a server that doesn’t expire articles (such as news.gmane.org), leads to very slow summary generation.


Same as gnus-fetch-old-headers, but only used for ephemeral newsgroups.


Fetching old headers can be slow. A low-rent similar effect can be gotten by setting this variable to some. Gnus will then look at the complete References headers of all articles and try to string together articles that belong in the same thread. This will leave gaps in the threading display where Gnus guesses that an article is missing from the thread. (These gaps appear like normal summary lines. If you select a gap, Gnus will try to fetch the article in question.) If this variable is t, Gnus will display all these “gaps” without regard for whether they are useful for completing the thread or not. Finally, if this variable is more, Gnus won’t cut off sparse leaf nodes that don’t lead anywhere. This variable is nil by default.


This is a rather obscure variable that few will find useful. It’s intended for those non-news newsgroups where the back end has to fetch quite a lot to present the summary buffer, and where it’s impossible to go back to parents of articles. This is mostly the case in the web-based groups.

If you don’t use those, then it’s safe to leave this as the default nil. If you want to use this variable, it should be a regexp that matches the group name, or t for all groups.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] More Threading


If this variable is nil, no threading will be done, and all of the rest of the variables here will have no effect. Turning threading off will speed group selection up a bit, but it is sure to make reading slower and more awkward.


If non-nil, all threads will be hidden when the summary buffer is generated.

This can also be a predicate specifier (see section Predicate Specifiers). Available predicates are gnus-article-unread-p and gnus-article-unseen-p.

Here’s an example:

(setq gnus-thread-hide-subtree
      '(or gnus-article-unread-p

(It’s a pretty nonsensical example, since all unseen articles are also unread, but you get my drift.)


All threads that have a total score (as defined by gnus-thread-score-function) less than this number will be expunged. This variable is nil by default, which means that no threads are expunged.


if you kill a thread and this variable is non-nil, the subtree will be hidden.


Sometimes somebody changes the subject in the middle of a thread. If this variable is non-nil, which is the default, the subject change is ignored. If it is nil, a change in the subject will result in a new thread.


This is a number that says how much each sub-thread should be indented. The default is 4.


Sometimes, particularly with mailing lists, the order in which mails arrive locally is not necessarily the same as the order in which they arrived on the mailing list. Consequently, when sorting sub-threads using the default gnus-thread-sort-by-number, responses can end up appearing before the article to which they are responding to. Setting this variable to an alternate value (e.g., gnus-thread-sort-by-date), in a group’s parameters or in an appropriate hook (e.g., gnus-summary-generate-hook) can produce a more logical sub-thread ordering in such instances.

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ] Low-Level Threading


Hook run before parsing any headers.


If non-nil, this function will be called to allow alteration of article header structures. The function is called with one parameter, the article header vector, which it may alter in any way. For instance, if you have a mail-to-news gateway which alters the Message-IDs in systematic ways (by adding prefixes and such), you can use this variable to un-scramble the Message-IDs so that they are more meaningful. Here’s one example:

(setq gnus-alter-header-function 'my-alter-message-id)

(defun my-alter-message-id (header)
  (let ((id (mail-header-id header)))
    (when (string-match
           "\\(<[^<>@]*\\)\\.?cygnus\\..*@\\([^<>@]*>\\)" id)
       (concat (match-string 1 id) "@" (match-string 2 id))

[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

3.9.2 Thread Commands

T k

Mark all articles in the current (sub-)thread as read (gnus-summary-kill-thread). If the prefix argument is positive, remove all marks instead. If the prefix argument is negative, tick articles instead.

T l

Lower the score of the current (sub-)thread (gnus-summary-lower-thread).

T i

Increase the score of the current (sub-)thread (gnus-summary-raise-thread).

T #

Set the process mark on the current (sub-)thread (gnus-uu-mark-thread).

T M-#

Remove the process mark from the current (sub-)thread (gnus-uu-unmark-thread).


Toggle threading (gnus-summary-toggle-threads).

T s

Expose the (sub-)thread hidden under the current article, if any

T h

Hide the current (sub-)thread (gnus-summary-hide-thread).


Expose all hidden threads (gnus-summary-show-all-threads).


Hide all threads (gnus-summary-hide-all-threads).

T t

Re-thread the current article’s thread (gnus-summary-rethread-current). This works even when the summary buffer is otherwise unthreaded.

T ^

Make the current article the child of the marked (or previous) article (gnus-summary-reparent-thread).

T M-^

Make the current article the parent of the marked articles (gnus-summary-reparent-children).

The following commands are thread movement commands. They all understand the numeric prefix.

T n

Go to the next thread (gnus-summary-next-thread).

T p

Go to the previous thread (gnus-summary-prev-thread).

T d

Descend the thread (gnus-summary-down-thread).

T u

Ascend the thread (gnus-summary-up-thread).

T o

Go to the top of the thread (gnus-summary-top-thread).

If you ignore subject while threading, you’ll naturally end up with threads that have several different subjects in them. If you then issue a command like T k (gnus-summary-kill-thread) you might not wish to kill the entire thread, but just those parts of the thread that have the same subject as the current article. If you like this idea, you can fiddle with gnus-thread-operation-ignore-subject. If it is non-nil (which it is by default), subjects will be ignored when doing thread commands. If this variable is nil, articles in the same thread with different subjects will not be included in the operation in question. If this variable is fuzzy, only articles that have subjects fuzzily equal will be included (see section Fuzzy Matching).

[ < ] [ > ]   [ << ] [ Up ] [ >> ]

This document was generated on January 25, 2015 using texi2html 1.82.