unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
From: Dirk Hohndel <hohndel@infradead.org>
To: notmuch <notmuch@notmuchmail.org>
Subject: [PATCH] Reordering of thread authors to list matching authors first
Date: Wed, 21 Apr 2010 20:58:27 -0700	[thread overview]
Message-ID: <m38w8gyw7w.fsf@x200.gr8dns.org> (raw)
In-Reply-To: <m3aaswyw9t.fsf@x200.gr8dns.org>


When displaying threads as result of a search it makes sense to list those
authors first who match the search. The matching authors are separated from the
non-matching ones with a '|' instead of a ','

Imagine the default "+inbox" query. Those mails in the thread that
match the query are actually "new" (whatever that means). And some
people seem to think that it would be much better to see those author
names first. For example, imagine a long and drawn out thread that once
was started by me; you have long read the older part of the thread and
removed the inbox tag. Whenever a new email comes in on this thread,
prior to this patch the author column in the search display will first show
"Dirk Hohndel" - I think it should first show the actual author(s) of the new
mail(s).

Signed-off-by: Dirk Hohndel <hohndel@infradead.org>
---
 lib/message.cc |   16 ++++++++++++
 lib/notmuch.h  |   11 ++++++++
 lib/thread.cc  |   74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 101 insertions(+), 0 deletions(-)

diff --git a/lib/message.cc b/lib/message.cc
index 721c9a6..ac0afd9 100644
--- a/lib/message.cc
+++ b/lib/message.cc
@@ -35,6 +35,7 @@ struct _notmuch_message {
     char *thread_id;
     char *in_reply_to;
     char *filename;
+    char *author;
     notmuch_message_file_t *message_file;
     notmuch_message_list_t *replies;
     unsigned long flags;
@@ -110,6 +111,7 @@ _notmuch_message_create (const void *talloc_owner,
     message->in_reply_to = NULL;
     message->filename = NULL;
     message->message_file = NULL;
+    message->author = NULL;
 
     message->replies = _notmuch_message_list_create (message);
     if (unlikely (message->replies == NULL)) {
@@ -533,6 +535,20 @@ notmuch_message_get_tags (notmuch_message_t *message)
     return _notmuch_convert_tags(message, i, end);
 }
 
+const char *
+notmuch_message_get_author (notmuch_message_t *message)
+{
+    return message->author;
+}
+
+void
+notmuch_message_set_author (notmuch_message_t *message,
+			    const char *author)
+{
+    message->author = talloc_strdup(message, author);
+    return;
+}
+
 void
 _notmuch_message_set_date (notmuch_message_t *message,
 			   const char *date)
diff --git a/lib/notmuch.h b/lib/notmuch.h
index bae48a6..769f747 100644
--- a/lib/notmuch.h
+++ b/lib/notmuch.h
@@ -773,6 +773,17 @@ notmuch_message_set_flag (notmuch_message_t *message,
 time_t
 notmuch_message_get_date  (notmuch_message_t *message);
 
+/* Set the author member of 'message' - this is the representation used
+ * when displaying the message
+ */
+void
+notmuch_message_set_author (notmuch_message_t *message, const char *author);
+
+/* Get the author member of 'message'
+ */
+const char *
+notmuch_message_get_author (notmuch_message_t *message);
+
 /* Get the value of the specified header from 'message'.
  *
  * The value will be read from the actual message file, not from the
diff --git a/lib/thread.cc b/lib/thread.cc
index e514bf8..baa0d7f 100644
--- a/lib/thread.cc
+++ b/lib/thread.cc
@@ -32,6 +32,7 @@ struct _notmuch_thread {
     char *subject;
     GHashTable *authors_hash;
     char *authors;
+    char *nonmatched_authors;
     GHashTable *tags;
 
     notmuch_message_list_t *message_list;
@@ -73,6 +74,76 @@ _thread_add_author (notmuch_thread_t *thread,
 	thread->authors = talloc_strdup (thread, author);
 }
 
+/*
+ * move authors of matched messages in the thread to 
+ * the front of the authors list, but keep them in
+ * existing order within their group
+ */
+static void
+_thread_move_matched_author (notmuch_thread_t *thread,
+			     const char *author)
+{
+    char *authorscopy;
+    char *currentauthor;
+    char *lastpipe,*nextpipe;
+    int idx,nmstart,author_len,authors_len;
+
+    if (thread->authors == NULL || author == NULL)
+	return;
+    if (thread->nonmatched_authors == NULL)
+	thread->nonmatched_authors = thread->authors;
+    author_len = strlen(author);
+    authors_len = strlen(thread->authors);
+    if (author_len == authors_len) {
+	/* just one author */
+	thread->nonmatched_authors += author_len;
+	return;
+    }
+    currentauthor = strcasestr(thread->authors, author);
+    if (currentauthor == NULL)
+	return;
+    /* how far inside the nonmatched authors is our author? */
+    idx = currentauthor - thread->nonmatched_authors;
+    if (idx < 0) {
+	/* already among matched authors */
+	return;
+    }
+    /* are there any authors in the list after our author? */
+    if (thread->nonmatched_authors + author_len < thread->authors + authors_len) {
+	/* we have to make changes, so let's get a temp copy */
+	authorscopy = xstrdup(thread->authors);
+	/* nmstart is the offset into where the non-matched authors start */
+	nmstart = thread->nonmatched_authors - thread->authors;
+	/* copy this author and add the "| " - the if clause above tells us there's more */
+	strncpy(thread->nonmatched_authors,author,author_len);
+	strncpy(thread->nonmatched_authors+author_len,"| ",2);
+	thread->nonmatched_authors += author_len+2;	
+	if (idx > 0) {
+	  /* we are actually moving authors around, not just changing the separator
+	   * first copy the authors that came BEFORE our author */
+	  strncpy(thread->nonmatched_authors, authorscopy+nmstart, idx-2);
+	  /* finally, if there are authors AFTER our author, copy those */
+	  if(author_len+nmstart+idx < authors_len) {
+	    strncpy(thread->nonmatched_authors + idx - 2,", ",2);
+	    strncpy(thread->nonmatched_authors + idx, authorscopy+nmstart + idx + author_len + 2, 
+		    authors_len - (nmstart + idx + author_len + 2));
+	  }
+	}
+	free(authorscopy);
+	/* finally let's make sure there's just one '|' in the authors string */
+	lastpipe = strchr(thread->authors,'|');
+	while (lastpipe) {
+	    nextpipe = strchr(lastpipe+1,'|');
+	    if (nextpipe)
+		*lastpipe = ',';
+	    lastpipe = nextpipe;
+	}
+    } else {
+	thread->nonmatched_authors += author_len;
+    }
+    return;
+}
+
 /* Add 'message' as a message that belongs to 'thread'.
  *
  * The 'thread' will talloc_steal the 'message' and hold onto a
@@ -108,6 +179,7 @@ _thread_add_message (notmuch_thread_t *thread,
 		author = internet_address_mailbox_get_addr (mailbox);
 	    }
 	    _thread_add_author (thread, author);
+	    notmuch_message_set_author (message, author);
 	}
 	g_object_unref (G_OBJECT (list));
     }
@@ -162,6 +234,7 @@ _thread_add_matched_message (notmuch_thread_t *thread,
 	notmuch_message_set_flag (hashed_message,
 				  NOTMUCH_MESSAGE_FLAG_MATCH, 1);
     }
+    _thread_move_matched_author (thread,notmuch_message_get_author(hashed_message));
 }
 
 static void
@@ -283,6 +356,7 @@ _notmuch_thread_create (void *ctx,
     thread->authors_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
 						  free, NULL);
     thread->authors = NULL;
+    thread->nonmatched_authors = NULL;
     thread->tags = g_hash_table_new_full (g_str_hash, g_str_equal,
 					  free, NULL);
 
-- 
1.6.6.1


-- 
Dirk Hohndel
Intel Open Source Technology Center

  reply	other threads:[~2010-04-22  3:58 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-04-07  5:52 [RFC] reordering and cleanup of thread authors Dirk Hohndel
2010-04-09  6:07 ` Michal Sojka
2010-04-09 17:29   ` Dirk Hohndel
2010-04-10  1:53     ` Michal Sojka
2010-04-10  2:42       ` Dirk Hohndel
2010-04-22  3:57         ` Dirk Hohndel
2010-04-22  3:58           ` Dirk Hohndel [this message]
2010-04-24  0:21             ` [PATCH] Reordering of thread authors to list matching authors first Carl Worth
2010-04-24 17:35               ` Dirk Hohndel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://notmuchmail.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=m38w8gyw7w.fsf@x200.gr8dns.org \
    --to=hohndel@infradead.org \
    --cc=notmuch@notmuchmail.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://yhetil.org/notmuch.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).