1 Return-Path: <BATV+bfcd26d6da2a49b2fc9f+2418+infradead.org+hohndel@bombadil.srs.infradead.org>
\r
2 X-Original-To: notmuch@notmuchmail.org
\r
3 Delivered-To: notmuch@notmuchmail.org
\r
4 Received: from localhost (localhost [127.0.0.1])
\r
5 by olra.theworths.org (Postfix) with ESMTP id 9B2234196F0
\r
6 for <notmuch@notmuchmail.org>; Tue, 6 Apr 2010 22:52:31 -0700 (PDT)
\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org
\r
11 X-Spam-Status: No, score=-4.2 tagged_above=-999 required=5
\r
12 tests=[BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3] autolearn=ham
\r
13 Received: from olra.theworths.org ([127.0.0.1])
\r
14 by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)
\r
15 with ESMTP id F21i+NaAOsCW for <notmuch@notmuchmail.org>;
\r
16 Tue, 6 Apr 2010 22:52:30 -0700 (PDT)
\r
17 Received: from bombadil.infradead.org (bombadil.infradead.org [18.85.46.34])
\r
18 by olra.theworths.org (Postfix) with ESMTP id 1BC29431FC1
\r
19 for <notmuch@notmuchmail.org>; Tue, 6 Apr 2010 22:52:30 -0700 (PDT)
\r
20 Received: from localhost ([::1] helo=localhost.localdomain)
\r
21 by bombadil.infradead.org with esmtp (Exim 4.69 #1 (Red Hat Linux))
\r
23 for notmuch@notmuchmail.org; Wed, 07 Apr 2010 05:52:29 +0000
\r
24 Received: by localhost.localdomain (Postfix, from userid 500)
\r
25 id D52BCC007F; Tue, 6 Apr 2010 22:52:28 -0700 (PDT)
\r
26 From: Dirk Hohndel <hohndel@infradead.org>
\r
27 To: notmuch <notmuch@notmuchmail.org>
\r
28 Subject: [RFC] reordering and cleanup of thread authors
\r
29 Date: Tue, 06 Apr 2010 22:52:28 -0700
\r
30 Message-ID: <m31veru7vn.fsf@x200.gr8dns.org>
\r
32 Content-Type: text/plain; charset=us-ascii
\r
33 X-SRS-Rewrite: SMTP reverse-path rewritten from <hohndel@infradead.org> by
\r
34 bombadil.infradead.org See http://www.infradead.org/rpr.html
\r
35 X-BeenThere: notmuch@notmuchmail.org
\r
36 X-Mailman-Version: 2.1.13
\r
38 List-Id: "Use and development of the notmuch mail system."
\r
39 <notmuch.notmuchmail.org>
\r
40 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,
\r
41 <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>
\r
42 List-Archive: <http://notmuchmail.org/pipermail/notmuch>
\r
43 List-Post: <mailto:notmuch@notmuchmail.org>
\r
44 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>
\r
45 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,
\r
46 <mailto:notmuch-request@notmuchmail.org?subject=subscribe>
\r
47 X-List-Received-Date: Wed, 07 Apr 2010 05:52:31 -0000
\r
50 This is based in part on some discussion on IRC today.
\r
51 When a thread is displayed in the search results, previously the authors
\r
52 were always displayed in chronological order. But if only part of the
\r
53 thread matches the query, that may or may not be the intuitive thing to
\r
55 Imagine the default "+inbox" query. Those mails in the thread that
\r
56 match the query are actually "new" (whatever that means). And some
\r
57 people seem to think that it would be much better to see those author
\r
58 names first. For example, imagine a long and drawn out thread that once
\r
59 was started by me; you have long read the older part of the thread and
\r
60 removed the inbox tag. Whenever a new email comes in on this thread, the
\r
61 author column in the search display will first show "Dirk Hohndel" - I
\r
62 think it should first show the actual author(s) of the new mail(s).
\r
64 The second cleanup that I've done in this context is to convert all
\r
65 author names into the much easier to parse "Firstname Lastname"
\r
66 format. Some broken mail systems (cough - Exchange - Cough) seem to
\r
67 prefer "Lastname, Firstname" - which makes the comma separated list of
\r
68 authors really hard to parse at one glance. Worse, it creates douplicate
\r
69 entries if a person happens to show in both orders. So this does a
\r
70 rather simplistic "look for a comma, if it's there, reorder" approach to
\r
71 cleaning up the author name.
\r
73 I don't think this is ready to be pulled. There was a strong request on
\r
74 IRC to make the re-ordering of the author names configurable. I think
\r
75 the cleanup of the names (First Last) should be configurable as well.
\r
76 And of course I wonder about my implementation, given that I'm still
\r
77 trying to wrap my mind around the current code base.
\r
83 diff --git a/lib/message.cc b/lib/message.cc
\r
84 index 721c9a6..ac0afd9 100644
\r
85 --- a/lib/message.cc
\r
86 +++ b/lib/message.cc
\r
87 @@ -35,6 +35,7 @@ struct _notmuch_message {
\r
92 notmuch_message_file_t *message_file;
\r
93 notmuch_message_list_t *replies;
\r
94 unsigned long flags;
\r
95 @@ -110,6 +111,7 @@ _notmuch_message_create (const void *talloc_owner,
\r
96 message->in_reply_to = NULL;
\r
97 message->filename = NULL;
\r
98 message->message_file = NULL;
\r
99 + message->author = NULL;
\r
101 message->replies = _notmuch_message_list_create (message);
\r
102 if (unlikely (message->replies == NULL)) {
\r
103 @@ -533,6 +535,20 @@ notmuch_message_get_tags (notmuch_message_t *message)
\r
104 return _notmuch_convert_tags(message, i, end);
\r
108 +notmuch_message_get_author (notmuch_message_t *message)
\r
110 + return message->author;
\r
114 +notmuch_message_set_author (notmuch_message_t *message,
\r
115 + const char *author)
\r
117 + message->author = talloc_strdup(message, author);
\r
122 _notmuch_message_set_date (notmuch_message_t *message,
\r
124 diff --git a/lib/notmuch.h b/lib/notmuch.h
\r
125 index 88da078..79638bb 100644
\r
126 --- a/lib/notmuch.h
\r
127 +++ b/lib/notmuch.h
\r
128 @@ -771,6 +771,17 @@ notmuch_message_set_flag (notmuch_message_t *message,
\r
130 notmuch_message_get_date (notmuch_message_t *message);
\r
132 +/* Set the author member of 'message' - this is the representation used
\r
133 + * when displaying the message
\r
136 +notmuch_message_set_author (notmuch_message_t *message, const char *author);
\r
138 +/* Get the author member of 'message'
\r
141 +notmuch_message_get_author (notmuch_message_t *message);
\r
143 /* Get the value of the specified header from 'message'.
\r
145 * The value will be read from the actual message file, not from the
\r
146 diff --git a/lib/thread.cc b/lib/thread.cc
\r
147 index 48c070e..c3c83a3 100644
\r
148 --- a/lib/thread.cc
\r
149 +++ b/lib/thread.cc
\r
150 @@ -32,6 +32,7 @@ struct _notmuch_thread {
\r
152 GHashTable *authors_hash;
\r
154 + char *nonmatched_authors;
\r
157 notmuch_message_list_t *message_list;
\r
158 @@ -69,8 +70,95 @@ _thread_add_author (notmuch_thread_t *thread,
\r
159 thread->authors = talloc_asprintf (thread, "%s, %s",
\r
164 thread->authors = talloc_strdup (thread, author);
\r
169 + * move authors of matched messages in the thread to
\r
170 + * the front of the authors list, but keep them in
\r
171 + * oldest first order within their group
\r
174 +_thread_move_matched_author (notmuch_thread_t *thread,
\r
175 + const char *author)
\r
177 + char *authorscopy;
\r
178 + char *currentauthor;
\r
179 + int idx,nmstart,author_len,authors_len;
\r
181 + if (thread->authors == NULL)
\r
183 + if (thread->nonmatched_authors == NULL)
\r
184 + thread->nonmatched_authors = thread->authors;
\r
185 + author_len = strlen(author);
\r
186 + authors_len = strlen(thread->authors);
\r
187 + if (author_len == authors_len) {
\r
188 + /* just one author */
\r
189 + thread->nonmatched_authors += author_len;
\r
192 + currentauthor = strcasestr(thread->authors, author);
\r
193 + if (currentauthor == NULL)
\r
195 + idx = currentauthor - thread->nonmatched_authors;
\r
197 + /* already among matched authors */
\r
200 + if (thread->nonmatched_authors + author_len < thread->authors + authors_len) {
\r
201 + /* we have to make changes, so let's get a temp copy */
\r
202 + authorscopy = strdup(thread->authors);
\r
203 + if (authorscopy == NULL)
\r
205 + /* nmstart is the offset into where the non-matched authors start */
\r
206 + nmstart = thread->nonmatched_authors - thread->authors;
\r
207 + /* copy this author and add the "| " - the if clause above tells us there's more */
\r
208 + strncpy(thread->nonmatched_authors,author,author_len);
\r
209 + strncpy(thread->nonmatched_authors+author_len,"| ",2);
\r
210 + thread->nonmatched_authors += author_len+2;
\r
212 + /* we are actually moving authors around, not just changing the separator
\r
213 + * first copy the authors that came BEFORE our author */
\r
214 + strncpy(thread->nonmatched_authors, authorscopy+nmstart, idx-2);
\r
215 + /* finally, if there are authors AFTER our author, copy those */
\r
216 + if(author_len+nmstart+idx < authors_len) {
\r
217 + strncpy(thread->nonmatched_authors + idx - 2,", ",2);
\r
218 + strncpy(thread->nonmatched_authors + idx, authorscopy+nmstart + idx + author_len + 2,
\r
219 + authors_len - (nmstart + idx + author_len + 2));
\r
222 + free(authorscopy);
\r
224 + thread->nonmatched_authors += author_len;
\r
229 +/* clean up the uggly "Lastname, Firstname" format to be "Firstname Lastname"
\r
232 +_thread_cleanup_author (notmuch_thread_t *thread,
\r
233 + const char *author)
\r
235 + char *cleanauthor;
\r
236 + const char *comma;
\r
239 + cleanauthor = talloc_strdup(thread, author);
\r
240 + if (cleanauthor == NULL)
\r
242 + comma = strchr(author,',');
\r
244 + lname = comma - author;
\r
245 + fname = strlen(author) - lname - 2;
\r
246 + strncpy(cleanauthor, comma + 2, fname);
\r
247 + *(cleanauthor+fname) = ' ';
\r
248 + strncpy(cleanauthor + fname + 1, author, lname);
\r
249 + *(cleanauthor+fname+1+lname) = '\0';
\r
251 + return cleanauthor;
\r
254 /* Add 'message' as a message that belongs to 'thread'.
\r
255 @@ -87,6 +175,7 @@ _thread_add_message (notmuch_thread_t *thread,
\r
256 InternetAddressList *list;
\r
257 InternetAddress *address;
\r
258 const char *from, *author;
\r
259 + char *cleanauthor;
\r
261 _notmuch_message_list_add_message (thread->message_list,
\r
262 talloc_steal (thread, message));
\r
263 @@ -107,7 +196,9 @@ _thread_add_message (notmuch_thread_t *thread,
\r
264 mailbox = INTERNET_ADDRESS_MAILBOX (address);
\r
265 author = internet_address_mailbox_get_addr (mailbox);
\r
267 - _thread_add_author (thread, author);
\r
268 + cleanauthor = _thread_cleanup_author (thread, author);
\r
269 + _thread_add_author (thread, cleanauthor );
\r
270 + notmuch_message_set_author (message, cleanauthor);
\r
272 g_object_unref (G_OBJECT (list));
\r
274 @@ -150,6 +241,7 @@ _thread_add_matched_message (notmuch_thread_t *thread,
\r
275 notmuch_message_set_flag (hashed_message,
\r
276 NOTMUCH_MESSAGE_FLAG_MATCH, 1);
\r
278 + _thread_move_matched_author (thread,notmuch_message_get_author(hashed_message));
\r
282 @@ -251,6 +343,7 @@ _notmuch_thread_create (void *ctx,
\r
283 thread->authors_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
\r
285 thread->authors = NULL;
\r
286 + thread->nonmatched_authors = NULL;
\r
287 thread->tags = g_hash_table_new_full (g_str_hash, g_str_equal,
\r
294 Intel Open Source Technology Center
\r