mirror of https://github.com/djcb/mu.git
mu4e: improve sorting of contacts for completion
set up the extra machinery for making sure emacs does not try to re-sort our already-sorted contacts.... Also try to improve the sorting strategy itself.
This commit is contained in:
parent
7dff782c58
commit
f645a12075
|
@ -250,12 +250,22 @@ appear on disk."
|
|||
(mu4e-message "Saved (%d lines)" (count-lines (point-min) (point-max)))
|
||||
;; update the file on disk -- ie., without the separator
|
||||
(mu4e~proc-add (buffer-file-name) mu4e~draft-drafts-folder)) nil t))
|
||||
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; address completion; inspired by org-contacts.el and
|
||||
;; https://github.com/nordlow/elisp/blob/master/mine/completion-styles-cycle.el
|
||||
(defun mu4e~compose-complete-handler (str pred action)
|
||||
(cond
|
||||
((eq action nil)
|
||||
(try-completion str mu4e~contacts-for-completion pred))
|
||||
((eq action t)
|
||||
(all-completions str mu4e~contacts-for-completion pred))
|
||||
((eq action 'metadata)
|
||||
;; our contacts are already sorted - just need to tell the
|
||||
;; completion machinery not to try to undo that...
|
||||
'(metadata
|
||||
(display-sort-function . identity) ;; i.e., alphabetically
|
||||
(cycle-sort-function . identity)))))
|
||||
|
||||
(defun mu4e~compose-complete-contact (&optional start)
|
||||
"Complete the text at START with a contact.
|
||||
|
@ -276,8 +286,8 @@ Ie. either 'name <email>' or 'email')."
|
|||
(re-search-backward "\\(\\`\\|[\n:,]\\)[ \t]*")
|
||||
(goto-char (match-end 0))
|
||||
(point)))))
|
||||
(list start end mu4e~contacts-for-completion)))))
|
||||
|
||||
(list start end 'mu4e~compose-complete-handler)))))
|
||||
|
||||
(defun mu4e~compose-setup-completion ()
|
||||
"Set up auto-completion of addresses."
|
||||
(set (make-local-variable 'completion-ignore-case) t)
|
||||
|
@ -311,8 +321,8 @@ message-thread by removing the In-Reply-To header."
|
|||
(progn
|
||||
(use-local-map mu4e-compose-mode-map)
|
||||
|
||||
(set (make-local-variable 'global-mode-string) '(:eval (mu4e-context-label)))
|
||||
|
||||
(set (make-local-variable 'global-mode-string) '(:eval (mu4e-context-label)))
|
||||
|
||||
(set (make-local-variable 'message-signature) mu4e-compose-signature)
|
||||
;; set this to allow mu4e to work when gnus-agent is unplugged in gnus
|
||||
(set (make-local-variable 'message-send-mail-real-function) nil)
|
||||
|
|
|
@ -638,16 +638,32 @@ process."
|
|||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
(defsubst mu4e~process-contact (contact)
|
||||
"Process CONTACT, possibly rewriting it, or return nil if
|
||||
should be removed."
|
||||
"Process CONTACT, and either return nil when it should not be included,
|
||||
or (rfc822-string . CONTACT) otherwise."
|
||||
(when mu4e-contact-rewrite-function
|
||||
(setq contact (funcall mu4e-contact-rewrite-function contact)))
|
||||
(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))
|
||||
(if name (format "%s <%s>" (mu4e~rfc822-quoteit name) mail) 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
|
||||
(lambda (c1 c2)
|
||||
(let* ((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)))))))
|
||||
|
||||
;; start and stopping
|
||||
(defun mu4e~fill-contacts (contacts)
|
||||
"We receive a list of contacts, which each contact of the form
|
||||
|
@ -656,25 +672,8 @@ 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."
|
||||
(setq
|
||||
mu4e~contact-list contacts
|
||||
mu4e~contacts-for-completion nil)
|
||||
(let ((lst)
|
||||
;; sort by the frequency (ascending), then timestamp (ascending)
|
||||
;; note -- this the opposite order we'd want, but the
|
||||
;; `push' below reverses the order
|
||||
|
||||
;; FIXME: sadly, the emacs completion subsystem re-sorts the list
|
||||
;; before showing candidates, so this doesn't do anything useful yet.
|
||||
(contacts (sort contacts
|
||||
(lambda (c1 c2)
|
||||
(let ((freq1 (plist-get c1 :freq))
|
||||
(tstamp1 (plist-get c1 :tstamp))
|
||||
(freq2 (plist-get c2 :freq))
|
||||
(tstamp2 (plist-get c2 :tstamp)))
|
||||
(if (equal freq1 freq2)
|
||||
(< tstamp1 tstamp2)
|
||||
(< freq1 freq2)))))))
|
||||
(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))))
|
||||
|
@ -1173,6 +1172,5 @@ the view and compose modes."
|
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
|
||||
(provide 'mu4e-utils)
|
||||
;;; End of mu4e-utils.el
|
||||
|
|
|
@ -771,10 +771,6 @@ for an example.")
|
|||
This is used by the completion functions in mu4e-compose, filled
|
||||
when mu4e starts.")
|
||||
|
||||
(defvar mu4e~contact-list nil
|
||||
"List of contacts, where each contact is a plist
|
||||
(:name NAME :mail EMAIL :tstamp TIMESTAMP :freq FREQUENCY).")
|
||||
|
||||
(defvar mu4e~server-props nil
|
||||
"Properties we receive from the mu4e server process.
|
||||
\(in the 'pong-handler').")
|
||||
|
|
Loading…
Reference in New Issue