[PATCH v3 10/10] cli: address: Add --filter-by option to configure address filtering
Michal Sojka
sojkam1 at fel.cvut.cz
Fri Jan 9 08:31:22 PST 2015
On Fri, Jan 09 2015, Michal Sojka wrote:
> On Fri, Jan 09 2015, Tomi Ollila wrote:
>> On Fri, Jan 09 2015, Michal Sojka <sojkam1 at fel.cvut.cz> wrote:
>>
>>> Hi,
>>>
>>> sorry for longer response time :)
>>>
>>> On Thu, Jan 01 2015, Tomi Ollila wrote:
>>>> On Wed, Dec 31 2014, David Bremner <david at tethera.net> wrote:
>>>>
>>>>> Michal Sojka <sojkam1 at fel.cvut.cz> writes:
>>>>>
>>>>>> This option allows to configure the criterion for duplicate address
>>>>>> filtering. Without this option, all unique combinations of name and
>>>>>> address parts are printed. This option allows to filter the output
>>>>>> more, for example to only contain unique address parts.
>>>>>
>>>>> I had the feeling there was some "controversy" about the UI here, but
>>>>> following back the 3 versions of the series I didn't see it. Does that
>>>>> mean we just need to sanity check the code, or are there outstanding
>>>>> bikes to shed?
>>>
>>> I'd tend to rename this option to --unique as it was in some previous
>>> version of the patch. Another thing in my mind is the implementation of
>>> the --complete option mentioned in id:878uid9qjl.fsf at nautilus.nautilus.
>>> This would also involve some kind of address filtering. I'll look into
>>> this and send patches later.
>>>
>>>> I have intentionally been guiet on this during the review process of the
>>>> other patches to not slow down the acceptance of the others. I have not
>>>> got enough time to look the implemenentation or think this last patch
>>>> further -- from the user interface point of view I recall seeing there
>>>> both useless features (but which might be warranted by implementation
>>>> simplicity) and missing features (but which might not be there due to
>>>> difficulty in implementation). Also, I am not sure whether the --filter-by
>>>> is good option (and options descriptive...)...
>>>
>>> I'd be interested in what are these "missing features".
>>
>> Last night when I tried to catch sleep I was also thinking of this...
>> ... let's see what I remember...
>>
>> First, Currently if we have addresses:
>>
>> "Uni Que" <unique at example.org>
>> "Uni Que" <Unique at Example.Org>
>>
>> I presume these are thought as a separate addresses -- and an option to
>> thought these as the same would be useful.
>
> Yes, this would correspond to --unique=addrfold or --unique=nameaddrfold
> from my patch.
>
>> but let's consider second set of addresses:
>>
>> "Uni Que" <unique at example.org>
>> "Uni Keko" <unique at example.org>
>>
>> Now, if there were an option to consider these 2 as the same, that would
>> hide user from one of the names -- It is clear that "Uni Que" is the right
>> one but if only "Uni Keko" (sleepyhead, that is) is shown user don't have
>> a choice to select the right one. I am not sure what the use case for
>> "uniquing" these 2 were.
>
> For example, when you are interested in the number of people involved in
> a discussion. You care only about the address and not about the names.
> Perhaps you'd like to see only the addresses in the output and not the
> names in this case, wouldn't you?
I meant something like the patch bellow. Unique options would be
no/yes/yes-but-case-insensitive and the type of uniqueness would be
determined by the --output flags. I don't like one thing on this
approach: --output flags now determine visibility of both rows and
columns in the output. But this is already present in master, because we
have count column there.
-Michal
diff --git a/notmuch-search.c b/notmuch-search.c
index 14b9f01..760f59a 100644
--- a/notmuch-search.c
+++ b/notmuch-search.c
@@ -34,6 +34,8 @@ typedef enum {
OUTPUT_SENDER = 1 << 5,
OUTPUT_RECIPIENTS = 1 << 6,
OUTPUT_COUNT = 1 << 7,
+ OUTPUT_NAME = 1 << 8,
+ OUTPUT_ADDR = 1 << 9,
} output_t;
typedef enum {
@@ -43,6 +45,12 @@ typedef enum {
NOTMUCH_FORMAT_SEXP
} format_sel_t;
+typedef enum {
+ UNIQUE_NO = 0,
+ UNIQUE_YES,
+ UNIQUE_CASEFOLD,
+} unique_t;
+
typedef struct {
notmuch_database_t *notmuch;
format_sel_t format_sel;
@@ -55,6 +63,7 @@ typedef struct {
int limit;
int dupe;
GHashTable *addresses;
+ unique_t unique;
} search_context_t;
typedef struct {
@@ -243,18 +252,45 @@ do_search_threads (search_context_t *ctx)
return 0;
}
-/* Returns TRUE iff name and addr is duplicate. If not, stores the
- * name/addr pair in order to detect subsequent duplicates. */
+/* Returns TRUE iff name and/or addr is considered duplicate. If not,
+ * stores the name/addr pair in order to detect subsequent
+ * duplicates. */
static notmuch_bool_t
is_duplicate (const search_context_t *ctx, const char *name, const char *addr)
{
notmuch_bool_t duplicate;
char *key;
+ gchar *addrfold = NULL;
+ gchar *namefold = NULL;
mailbox_t *mailbox;
- key = talloc_asprintf (ctx->format, "%s <%s>", name, addr);
+ if (ctx->unique == UNIQUE_CASEFOLD) {
+ addrfold = g_utf8_casefold (addr, -1);
+ namefold = g_utf8_casefold (name, -1);
+ }
+
+ switch (ctx->output & (OUTPUT_NAME | OUTPUT_ADDR)) {
+ case OUTPUT_NAME | OUTPUT_ADDR:
+ key = talloc_asprintf (ctx->format, "%s <%s>", namefold ? namefold : name,
+ addrfold ? addrfold : addr);
+ break;
+ case OUTPUT_NAME:
+ key = talloc_strdup (ctx->format, namefold ? namefold : name); /* !name results in !key */
+ break;
+ case OUTPUT_ADDR:
+ key = talloc_strdup (ctx->format, addrfold ? addrfold : addr);
+ break;
+ default:
+ INTERNAL_ERROR("invalid --output flags");
+ }
+
+ if (addrfold) {
+ g_free (addrfold);
+ g_free (namefold);
+ }
+
if (! key)
- return FALSE;
+ return TRUE;
duplicate = g_hash_table_lookup_extended (ctx->addresses, key, NULL, (gpointer)&mailbox);
@@ -281,6 +317,7 @@ print_mailbox (const search_context_t *ctx, const mailbox_t *mailbox)
sprinter_t *format = ctx->format;
InternetAddress *ia = internet_address_mailbox_new (name, addr);
char *name_addr;
+ notmuch_bool_t no_name_and_addr = !(ctx->output & OUTPUT_NAME || ctx->output & OUTPUT_ADDR); /* Backward compatible behavior */
/* name_addr has the name part quoted if necessary. Compare
* 'John Doe <john at doe.com>' vs. '"Doe, John" <john at doe.com>' */
@@ -291,16 +328,27 @@ print_mailbox (const search_context_t *ctx, const mailbox_t *mailbox)
format->integer (format, count);
format->string (format, "\t");
}
- format->string (format, name_addr);
+ if ((ctx->output & OUTPUT_NAME && ctx->output & OUTPUT_ADDR) || no_name_and_addr)
+ format->string (format, name_addr);
+ else if (ctx->output & OUTPUT_NAME)
+ format->string (format, name);
+ else if (ctx->output & OUTPUT_ADDR)
+ format->string (format, addr);
format->separator (format);
} else {
format->begin_map (format);
- format->map_key (format, "name");
- format->string (format, name);
- format->map_key (format, "address");
- format->string (format, addr);
- format->map_key (format, "name-addr");
- format->string (format, name_addr);
+ if (ctx->output & OUTPUT_NAME || no_name_and_addr) {
+ format->map_key (format, "name");
+ format->string (format, name);
+ }
+ if (ctx->output & OUTPUT_ADDR || no_name_and_addr) {
+ format->map_key (format, "address");
+ format->string (format, addr);
+ }
+ if ((ctx->output & OUTPUT_NAME && ctx->output & OUTPUT_ADDR) || no_name_and_addr) {
+ format->map_key (format, "name-addr");
+ format->string (format, name_addr);
+ }
if (count > 0) {
format->map_key (format, "count");
format->integer (format, count);
@@ -631,6 +679,7 @@ static search_context_t search_context = {
.offset = 0,
.limit = -1, /* unlimited */
.dupe = -1,
+ .unique = UNIQUE_NO,
};
static const notmuch_opt_desc_t common_options[] = {
@@ -722,11 +771,18 @@ notmuch_address_command (notmuch_config_t *config, int argc, char *argv[])
(notmuch_keyword_t []){ { "sender", OUTPUT_SENDER },
{ "recipients", OUTPUT_RECIPIENTS },
{ "count", OUTPUT_COUNT },
+ { "name", OUTPUT_NAME },
+ { "addr", OUTPUT_ADDR },
{ 0, 0 } } },
{ NOTMUCH_OPT_KEYWORD, &ctx->exclude, "exclude", 'x',
(notmuch_keyword_t []){ { "true", NOTMUCH_EXCLUDE_TRUE },
{ "false", NOTMUCH_EXCLUDE_FALSE },
{ 0, 0 } } },
+ { NOTMUCH_OPT_KEYWORD, &ctx->unique, "unique", 'b',
+ (notmuch_keyword_t []){ { "no", UNIQUE_NO },
+ { "yes", UNIQUE_YES },
+ { "casefold", UNIQUE_CASEFOLD },
+ { 0, 0 } } },
{ NOTMUCH_OPT_INHERIT, &common_options, NULL, 0, 0 },
{ 0, 0, 0, 0, 0 }
};
More information about the notmuch
mailing list