scm: mfind: use cons instead of append, eval lazy
For the list building, using cons is much faster. So traverse the results _backwards_, and then cons gives us the right order. Don't eval when creating the list, but do so lazily (when requested in the message, in mu-scm.scm)
This commit is contained in:
@ -42,7 +42,6 @@ using MessageMap = std::unordered_map<std::string, MessageObject>;
|
|||||||
static MessageMap message_map;
|
static MessageMap message_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const Message&
|
static const Message&
|
||||||
to_message(SCM scm, const char *func, int pos)
|
to_message(SCM scm, const char *func, int pos)
|
||||||
{
|
{
|
||||||
@ -138,8 +137,9 @@ subr_cc_message_plist(SCM message_scm) try {
|
|||||||
constexpr auto func{"cc-message-plist"};
|
constexpr auto func{"cc-message-plist"};
|
||||||
|
|
||||||
const auto& message{to_message(message_scm, func, 1)};
|
const auto& message{to_message(message_scm, func, 1)};
|
||||||
const auto plist{"'" + message.sexp().to_string()};
|
// return the serialized (mu4e) message
|
||||||
return scm_c_eval_string(plist.c_str());
|
const auto plist{message.sexp().to_string()};
|
||||||
|
return to_scm(plist);
|
||||||
|
|
||||||
} catch (const ScmError& err) {
|
} catch (const ScmError& err) {
|
||||||
err.throw_scm();
|
err.throw_scm();
|
||||||
|
|||||||
@ -157,23 +157,19 @@ subr_cc_store_mfind(SCM store_scm, SCM query_scm, SCM related_scm, SCM skip_dups
|
|||||||
(related ? QueryFlags::IncludeRelated: QueryFlags::None ) |
|
(related ? QueryFlags::IncludeRelated: QueryFlags::None ) |
|
||||||
(reverse ? QueryFlags::Descending : QueryFlags::None);
|
(reverse ? QueryFlags::Descending : QueryFlags::None);
|
||||||
|
|
||||||
SCM msgs{SCM_EOL};
|
|
||||||
std::lock_guard lock{store.lock()};
|
std::lock_guard lock{store.lock()};
|
||||||
const auto qres = store.run_query(query, sort_field_id, qflags, maxnum);
|
const auto qres{store.run_query(query, sort_field_id, qflags, maxnum)};
|
||||||
|
|
||||||
if (!qres)
|
if (!qres)
|
||||||
throw ScmError{ScmError::Id::WrongArg, func, 2, query_scm, ""};
|
throw ScmError{ScmError::Id::WrongArg, func, 2, query_scm, ""};
|
||||||
|
|
||||||
for (const auto& mi: *qres) {
|
SCM msgs{SCM_EOL};
|
||||||
if (auto plist{mi.document()->get_data()}; plist.empty())
|
// iterate in reverse order, so the message get consed
|
||||||
continue;
|
// into the list in the right order.
|
||||||
else {
|
for (auto it{qres->end()}; it-- != qres->begin();)
|
||||||
SCM scm_plist{scm_c_eval_string(("'" + plist).c_str())};
|
if (auto plist{it.document()->get_data()}; !plist.empty())
|
||||||
msgs = scm_append_x(scm_list_2( msgs, scm_list_1(scm_plist)));
|
msgs = scm_cons(to_scm(plist), msgs);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return msgs;
|
return msgs;
|
||||||
|
|
||||||
} catch (const ScmError& err) {
|
} catch (const ScmError& err) {
|
||||||
err.throw_scm();
|
err.throw_scm();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -239,8 +239,8 @@ Otherwise, trying to overwrite an existing file raises an error."
|
|||||||
;; Message
|
;; Message
|
||||||
(define-class <message> ()
|
(define-class <message> ()
|
||||||
(cc-message #:init-value #f #:init-keyword #:cc-message)
|
(cc-message #:init-value #f #:init-keyword #:cc-message)
|
||||||
|
(serialized #:init-value #f #:init-keyword #:serialized)
|
||||||
(parts #:init-value #f #:init-keyword #:parts)
|
(parts #:init-value #f #:init-keyword #:parts)
|
||||||
(plist #:init-value #f #:init-keyword #:plist)
|
|
||||||
(alist #:init-value #f))
|
(alist #:init-value #f))
|
||||||
|
|
||||||
(set-documentation!
|
(set-documentation!
|
||||||
@ -253,33 +253,33 @@ these are the slots:
|
|||||||
- cc-message: this is a foreign-object representing the mu
|
- cc-message: this is a foreign-object representing the mu
|
||||||
message object, and needs to be passed to some 'cc-' methods.
|
message object, and needs to be passed to some 'cc-' methods.
|
||||||
- parts: a list of <mime-part> objects
|
- parts: a list of <mime-part> objects
|
||||||
- plist: this is an Emacs-style property list which is cached
|
- data: this is a string containing an Emacs-style property list
|
||||||
for each message in the store; this was originally added
|
which is cached for each message in the store; this was
|
||||||
for use in mu4e, but we re-use it here.
|
originally added for use in mu4e, but we re-use it here.
|
||||||
- alist: an association list; this is just more 'scheme-like'
|
- alist: an association list; an alist with properties, as
|
||||||
version of the plist, it is created on-demand (message->alist).
|
created from the data (converted from the plist)
|
||||||
|
|
||||||
A message that came from a search such as 'mfind' initially only
|
A message that came from a search such as 'mfind' initially only
|
||||||
has the plist, but when a message is loaded from file, either
|
has the data, but when a message is loaded from file, either
|
||||||
through make-message or by calling a function that needs a
|
through make-message or by calling a function that needs a
|
||||||
full message, such as header or body, the cc-message is initialized.
|
full message, such as header or body, the cc-message is initialized.")
|
||||||
|
|
||||||
Only having a plist is cheaper.")
|
|
||||||
|
|
||||||
(define (make-message path)
|
(define (make-message path)
|
||||||
"Create a <message> from file at PATH."
|
"Create a <message> from file at PATH."
|
||||||
(make <message> #:cc-message (cc-message-make path)))
|
(make <message> #:cc-message (cc-message-make path)))
|
||||||
|
|
||||||
(define-method (plist (message <message>))
|
|
||||||
"Get the PLIST for this MESSAGE."
|
|
||||||
(when (not (slot-ref message 'plist))
|
|
||||||
(slot-set! message 'plist (cc-message-plist (cc-message message))))
|
|
||||||
(slot-ref message 'plist))
|
|
||||||
|
|
||||||
(define-method (message->alist (message <message>))
|
(define-method (message->alist (message <message>))
|
||||||
"Get an association-list (alist) representation for MESSAGE."
|
"Get an association-list (alist) representation for MESSAGE."
|
||||||
(when (not (slot-ref message 'alist))
|
(when (not (slot-ref message 'alist))
|
||||||
(slot-set! message 'alist (plist->alist (plist message))))
|
(let* ((serialized
|
||||||
|
(or (slot-ref message 'serialized)
|
||||||
|
(cc-message-plist (slot-ref message 'cc-message))))
|
||||||
|
;; parse the serialized message (the mu4e plist)
|
||||||
|
;; and convert into alist. We need to _quote_ the
|
||||||
|
;; the serialized string before we can parse it.
|
||||||
|
(alist (plist->alist (eval-string (string-append "'" serialized)))))
|
||||||
|
(slot-set! message 'alist alist)
|
||||||
|
(slot-set! message 'serialized #f))) ;; no longer needed
|
||||||
(slot-ref message 'alist))
|
(slot-ref message 'alist))
|
||||||
|
|
||||||
(define-method (cc-message (message <message>))
|
(define-method (cc-message (message <message>))
|
||||||
@ -290,13 +290,6 @@ path of the message."
|
|||||||
(slot-set! message 'cc-message (cc-message-make (path message))))
|
(slot-set! message 'cc-message (cc-message-make (path message))))
|
||||||
(slot-ref message 'cc-message))
|
(slot-ref message 'cc-message))
|
||||||
|
|
||||||
(define-method (sexp (message <message>))
|
|
||||||
"Get the s-expression (plist) for this MESSAGE.
|
|
||||||
|
|
||||||
This is an internal data-structure, originally for use with mu4e, but useful
|
|
||||||
here as well. However, the precise details are not part of mu-scm API."
|
|
||||||
(plist message))
|
|
||||||
|
|
||||||
;; Accessors for the fields
|
;; Accessors for the fields
|
||||||
|
|
||||||
(define-method (subject (message <message>))
|
(define-method (subject (message <message>))
|
||||||
@ -540,10 +533,11 @@ The query is mandatory, the other (keyword) arguments are optional.
|
|||||||
#:sort-field? field to sort by, a symbol. Default: date
|
#:sort-field? field to sort by, a symbol. Default: date
|
||||||
#:reverse? sort in descending order (z-a)
|
#:reverse? sort in descending order (z-a)
|
||||||
#:max-results max. number of matches. Default: false (unlimited))."
|
#:max-results max. number of matches. Default: false (unlimited))."
|
||||||
(map (lambda (plist)
|
(map (lambda (data)
|
||||||
(make <message> #:plist plist))
|
(make <message> #:serialized data))
|
||||||
(cc-store-mfind (cc-store store) query
|
(cc-store-mfind (cc-store store) query
|
||||||
related? skip-dups? sort-field reverse? max-results)))
|
related? skip-dups? sort-field
|
||||||
|
reverse? max-results)))
|
||||||
|
|
||||||
(define* (mcount
|
(define* (mcount
|
||||||
#:key
|
#:key
|
||||||
|
|||||||
Reference in New Issue
Block a user