mu/mu4e: improve in contacts completion

mu: cleanup server side; make sure not to loose 'personal' flag when
    seeing same contact in non-personal context
mu4e: tweak the sorting algorithm a bit to take the personal flag into
    account
This commit is contained in:
djcb 2015-12-30 15:33:27 +02:00
parent 74aa4679d3
commit 02620af4c2
3 changed files with 53 additions and 33 deletions

View File

@ -286,14 +286,14 @@ gboolean
mu_contacts_add (MuContacts *self, const char *addr, const char *name,
gboolean personal, time_t tstamp)
{
ContactInfo *cinfo;
const char *group;
ContactInfo *cinfo;
const char *group;
g_return_val_if_fail (self, FALSE);
g_return_val_if_fail (addr, FALSE);
group = encode_email_address (addr);
group = encode_email_address (addr);
cinfo = (ContactInfo*) g_hash_table_lookup (self->_hash, group);
if (!cinfo) {
char *addr_dc;
@ -304,6 +304,11 @@ mu_contacts_add (MuContacts *self, const char *addr, const char *name,
tstamp, 1);
g_hash_table_insert (self->_hash, g_strdup(group), cinfo);
} else {
/* if the contact is ever user in a personal way, it's
* personal */
if (personal)
cinfo->_personal = TRUE;
if (cinfo->_tstamp < tstamp) {
if (!mu_str_is_empty(name)) {
/* update the name to the last one used, unless it's

View File

@ -578,7 +578,7 @@ static void
each_contact_sexp (const char *email, const char *name, gboolean personal,
time_t tstamp, unsigned freq, SexpData *sdata)
{
char *escmail;
char *escmail, *escname;
/* (maybe) only include 'personal' contacts */
if (sdata->personal && !personal)
@ -594,19 +594,18 @@ each_contact_sexp (const char *email, const char *name, gboolean personal,
return;
escmail = mu_str_escape_c_literal (email, TRUE);
escname = name ? mu_str_escape_c_literal (name, TRUE) : NULL;
if (name) {
char *escname;
escname = mu_str_escape_c_literal (name, TRUE);
g_string_append_printf (sdata->gstr,
"(:name %s :mail %s :tstamp %u :freq %u)\n",
escname, escmail, (unsigned)tstamp, freq);
g_free (escname);
} else
g_string_append_printf (sdata->gstr,
"(:mail %s :tstamp %u :freq %u)\n",
escmail, (unsigned)tstamp, freq);
g_string_append_printf (
sdata->gstr,
"(:mail %s :name %s :tstamp %u :freq %u :personal %s)\n",
escmail,
escname ? escname : "nil",
(unsigned)tstamp,
freq,
sdata->personal ? "t" : "nil");
g_free (escname);
g_free (escmail);
}

View File

@ -645,24 +645,37 @@ or (rfc822-string . CONTACT) otherwise."
(when contact
(let ((name (plist-get contact :name))
(mail (plist-get contact :mail)))
(unless (and mail (string-match mu4e-compose-complete-ignore-address-regexp mail))
(unless (and mail
(string-match mu4e-compose-complete-ignore-address-regexp mail))
(cons
(if name (format "%s <%s>" (mu4e~rfc822-quoteit name) mail) mail)
contact)))))
(defun mu4e~sort-contacts (contacts)
"Sort the contacts (only for cycling). Sort by last-use when
that is at most 10 days old. Otherwise, sort by frequency."
(let ((recent (- (float-time) (* 10 24 3600))))
(sort contacts
(defsubst mu4e~sort-contacts (contacts)
"Destructively sort contacts (only for cycling). Sort by
last-use when that is at most 10 days old. Otherwise, sort by
frequency."
(let* ((now (+ (float-time) 3600)) ;; allow for clock diffs
(recent (- (float-time) (* 30 24 3600))))
(sort* contacts
(lambda (c1 c2)
(let* ((freq1 (plist-get c1 :freq))
(let* ( (c1 (cdr c1)) (c2 (cdr c2))
(personal1 (plist-get c1 :personal))
(personal2 (plist-get c2 :personal))
(freq1 (plist-get c1 :freq))
(freq2 (plist-get c2 :freq))
(tstamp1 (plist-get c1 :tstamp))
(tstamp2 (plist-get c2 :tstamp)))
(if (or (> tstamp1 recent) (> tstamp2 recent))
(< tstamp1 tstamp2)
(< freq1 freq2)))))))
;; personal contacts come first
(if (or personal1 personal2)
(if personal1 t nil)
;; then come recently seen ones; but only if they're not in
;; the future (as seen in spams)
(if (and (<= tstamp1 now) (<= tstamp2 now)
(or (> tstamp1 recent) (> tstamp2 recent)))
(> tstamp1 tstamp2)
;; otherwise, use the frequency
(> freq1 freq2))))))))
;; start and stopping
(defun mu4e~fill-contacts (contacts)
@ -672,13 +685,16 @@ and fill the list `mu4e~contacts-for-completion' with it, with
each element looking like
name <email>
This is used by the completion function in mu4e-compose."
(let ((contacts (mu4e~sort-contacts contacts)))
(setq mu4e~contacts-for-completion nil)
(dolist (contact contacts)
(let ((contact (mu4e~process-contact contact)))
(when contact (push contact mu4e~contacts-for-completion))))
(mu4e-index-message "Contacts received: %d"
(length mu4e~contacts-for-completion))))
(setq mu4e~contacts-for-completion nil)
(dolist (contact contacts)
(let ((contact (mu4e~process-contact contact)))
;; note, this gives cells (rfc822-address . contact)
(when contact (push contact mu4e~contacts-for-completion))))
(setq mu4e~contacts-for-completion
(mapcar 'car ;; strip off the other stuff again
(mu4e~sort-contacts mu4e~contacts-for-completion)))
(mu4e-index-message "Contacts received: %d"
(length mu4e~contacts-for-completion)))
(defun mu4e~check-requirements ()