* mu4e: cleanup header sorting (and fix the sort-by-human-date case)

This commit is contained in:
djcb 2012-11-11 19:27:55 +02:00
parent 1c1f974807
commit f957a9ca89
3 changed files with 77 additions and 51 deletions

View File

@ -149,16 +149,6 @@ match.
* PARAM-FUNC is function that is evaluated once, and its value is then passed to
PREDICATE-FUNC as PARAM. This is useful for getting user-input.")
(defvar mu4e-headers-sortfield :date
"Field to sort the headers by.
Field must be a symbol, one of: :date, :subject, :size, :prio,
:from, :to.")
(defvar mu4e-headers-sort-revert t
"Whether to revert the sort-order.
i.e. Z>A instead of A>Z. When sorting by date, it's useful to go
from biggest to smallest, so newest messages come first.")
(defvar mu4e-headers-show-threads t
"Whether to show threads in the headers list.")
@ -181,7 +171,7 @@ followed by the docid, followed by `mu4e~headers-docid-post'.")
(defvar mu4e~headers-view-win nil
"The view window connected to this headers view.")
(defvar mu4e~headers-sortfield-choices
(defvar mu4e~headers-sort-field-choices
'( ("date" . :date)
("from" . :from)
("prio" . :prio)
@ -353,6 +343,8 @@ date. The formats used for date and time are
(format-time-string mu4e-headers-time-format date)
(format-time-string mu4e-headers-date-format date))))
;; note: this function is very performance-sensitive
(defun mu4e~headers-header-handler (msg &optional point)
"Create a one line description of MSG in this buffer, at POINT,
@ -599,9 +591,9 @@ after the end of the search results."
(define-key menumap [previous] '("Previous" . mu4e-headers-prev))
(define-key menumap [sepa4] '("--")))
map)))
(fset 'mu4e-headers-mode-map mu4e-headers-mode-map)
(defun mu4e~header-line-format ()
"Get the format for the header line."
(cons
@ -617,8 +609,8 @@ after the end of the search results."
(downarrow (if mu4e-use-fancy-chars "" " V"))
;; triangle to mark the sorted-by column
(arrow
(when (and sortable (eq (car item) mu4e-headers-sortfield))
(if mu4e-headers-sort-revert downarrow uparrow)))
(when (and sortable (eq (car item) mu4e~headers-sort-field))
(if (eq mu4e~headers-sort-direction 'descending) downarrow uparrow)))
(name (concat (plist-get info :shortname) arrow))
(map (make-sparse-keymap)))
(when sortable
@ -629,10 +621,9 @@ after the end of the search results."
(let* ((obj (posn-object (event-start e)))
(field
(and obj (get-text-property 0 'field (car obj)))))
(if (eq field mu4e-headers-sortfield)
(setq mu4e-headers-sort-revert (not mu4e-headers-sort-revert))
(setq mu4e-headers-sortfield field)))
(mu4e-headers-rerun-search))))
;; "t": if we're already sorted by field, the sort-order is
;; changed
(mu4e-headers-change-sorting field t)))))
(concat
(propertize
(if width
@ -812,6 +803,10 @@ docid is not found."
(delete-region (line-beginning-position) (line-beginning-position 2)))
(unless ignore-missing
(mu4e-error "Cannot find message with docid %S" docid)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun mu4e~headers-search-execute (expr ignore-history)
"Search in the mu database for EXPR, and switch to the output
@ -838,8 +833,8 @@ the query history stack."
(mu4e~proc-find
expr
mu4e-headers-show-threads
mu4e-headers-sortfield
mu4e-headers-sort-revert
mu4e~headers-sort-field
mu4e~headers-sort-direction
(unless mu4e-headers-full-search mu4e-search-results-limit))))
(defun mu4e~headers-redraw-get-view-window ()
@ -1088,26 +1083,50 @@ the last search expression."
(format "(%s) AND %s" mu4e~headers-last-query filter)))
(defun mu4e-headers-change-sorting (&optional dont-refresh)
"Interactively change the sorting/threading parameters.
With prefix-argument, do _not_ refresh the last search with the
new parameters."
(interactive "P")
(let* ((sortfield
(mu4e-read-option "Sortfield: " mu4e~headers-sortfield-choices))
(revert
(mu4e-read-option "Direction: "
'(("ascending" . nil) ("descending" . t)))))
(defvar mu4e~headers-sort-field :date
"Field to sort the headers by.
Field must be a symbol, one of: :date, :subject, :size, :prio,
:from, :to.")
(defvar mu4e~headers-sort-direction 'descending
"Direction to sort by; a symbol either `descending' (sorting
Z->A) or `ascending' (sorting A->Z).")
(defun mu4e-headers-change-sorting (&optional field dir)
"Change the sorting/threading parameters.
FIELD is the field to sort by; DIR is a symbol: either 'ascending,
'descending, 't (meaning: if FIELD is the same as the current
sortfield, change the sort-order) or nil (ask the user)."
(interactive)
(let* ((field
(or field
(mu4e-read-option "Sortfield: " mu4e~headers-sort-field-choices)))
;; note: 'sortable' is either a boolean (meaning: if non-nil, this is
;; sortable field), _or_ another field (meaning: sort by this other field).
(sortable (plist-get (cdr (assoc field mu4e-header-info)) :sortable))
;; error check
(sortable
(if sortable
sortable
(mu4e-error "Not a sortable field")))
(sortfield (if (booleanp sortable) field sortable))
(dir
(case dir
((ascending descending) dir)
;; change the sort order if field = curfield
(t
(if (eq sortfield mu4e~headers-sort-field)
(if (eq mu4e~headers-sort-direction 'ascending)
'descending 'ascending)))
(mu4e-read-option "Direction: "
'(("ascending" . 'ascending) ("descending" . 'descending))))))
(setq
mu4e-headers-sortfield sortfield
mu4e-headers-sort-revert revert) ;; "descending" means "revert"
(mu4e-message "Sorting by %s (%s)%s"
mu4e~headers-sort-field sortfield
mu4e~headers-sort-direction dir)
(mu4e-message "Sorting by %s (%s)"
(symbol-name sortfield)
(if revert "descending" "ascending")
(if dont-refresh
" (press 'g' to refresh)" ""))
(unless dont-refresh
(mu4e-headers-rerun-search))))
(symbol-name mu4e~headers-sort-direction))
(mu4e-headers-rerun-search)))
(defun mu4e-headers-toggle-threading (&optional dont-refresh)
"Toggle threading on/off for the search results.

View File

@ -317,23 +317,24 @@ In particular, backslashes and double-quotes."
(let ((esc (replace-regexp-in-string "\\\\" "\\\\\\\\" query)))
(replace-regexp-in-string "\"" "\\\\\"" esc)))
(defun mu4e~proc-find (query threads sortfield revert maxnum)
(defun mu4e~proc-find (query threads sortfield sortdir maxnum)
"Start a database query for QUERY.
If THREADS is non-nil, show results in threaded fasion, SORTFIELD
is a symbol describing the field to sort by (or nil); see
`mu4e~headers-sortfield-choices'. If REVERT is non-nil, sort Z->A
instead of A->Z. MAXNUM determines the maximum number of results
to return, or nil for 'unlimited'. For each result found, a
function is called, depending on the kind of result. The
variables `mu4e-error-func' contain the function that will be
called for, resp., a message (header row) or an error."
`mu4e~headers-sortfield-choices'. If SORT is `descending', sort
Z->A, if it's `ascending', sort A->Z. MAXNUM determines the maximum
number of results to return, or nil for 'unlimited'. For each
result found, a function is called, depending on the kind of
result. The variables `mu4e-error-func' contain the function that
will be called for, resp., a message (header row) or an error."
(mu4e~proc-send-command
"find query:\"%s\" threads:%s sortfield:%s reverse:%s maxnum:%d"
(mu4e~proc-escape-query query)
(if threads "true" "false")
;; sortfield is e.g. ':subject'; this removes the ':'
(if (null sortfield) "nil" (substring (symbol-name sortfield) 1))
(if revert "true" "false")
;; TODO: use ascending/descending in backend too (it's clearer than 'reverse'
(if (eq sortdir 'descending) "true" "false")
(if maxnum maxnum -1)))
(defun mu4e~proc-move (docid-or-msgid &optional maildir flags)

View File

@ -492,7 +492,7 @@ I.e. a message with the draft flag set."
( :name "Date"
:shortname "Date"
:help "Date/time when the message was written."
:sortable t))
:sortable :date))
(:flags .
( :name "Flags"
:shortname "Flgs"
@ -544,13 +544,19 @@ I.e. a message with the draft flag set."
:help "Recipient of the message"
:sortable t)))
"An alist of all possible header fields and information about them.
This is used in the UI (the column headers in the header list,
and the fields the message view).
This is used in the user-interface (the column headers in the header list, and
the fields the message view).
Most fields should be self-explanatory. A special one is
`:from-or-to', which is equal to `:from' unless `:from' matches
`mu4e-user-mail-address-regexp', in which case it will be equal
to `:to'.")
`mu4e-user-mail-address-regexp', in which case it will be equal to
`:to'.
Furthermore, the property `:sortable' determines whether we can
sort by this field. This can be either a boolean (nil or t), or a
symbol for /another/ field. For example, the `:human-date' field
uses `:date' for that.
")
(defvar mu4e-custom-header-info nil
"A list like `mu4e-custom-header-info', but for custom headers.