mu-find: implement format=json2
Implement a new experimental json2 format for mu-find, which gets rid of the ":" prefixes for fields, i.e., "subject" instead of ":subject". Document it as well.
This commit is contained in:
14
NEWS.org
14
NEWS.org
@ -35,6 +35,12 @@
|
||||
is a bit easier to manipulate than the emacs-style timestamps (same value,
|
||||
but expressed as a list).
|
||||
|
||||
- With 1.12.10, there is also an experimental ~--format=json2~, where key-names
|
||||
are no longer prefixed with ~:~, so for example, "*subject"* instead of
|
||||
"*:subject"*.
|
||||
|
||||
- With 1.12.9, the cleanup phase after indexing is significantly faster now
|
||||
|
||||
- with 1.12.7, ~mu~ indexing is single-threaded again, to avoid cases of
|
||||
database-corruption. In *mu4e* that means you need to _wait_ until indexing is
|
||||
ready before you can continue (*mu4e* will warn you).
|
||||
@ -47,8 +53,6 @@
|
||||
in the mu4e version in its main-page; however, since this is optional no
|
||||
longer, the suffix has been removed.
|
||||
|
||||
- the cleanup phase after indexing is significantly faster now
|
||||
|
||||
*** mu4e
|
||||
|
||||
- message composition has been completely reworked to avoid a number of
|
||||
@ -69,9 +73,9 @@
|
||||
result you expected.
|
||||
|
||||
- When you ask for bookmarks or maildirs through ~mu4e-search-bookmark~ or
|
||||
~mu4e-search-maildir~, unread counts are displayed in the (default) completions
|
||||
UI next to the maildir or bookmark. If you don't want to see these counts,
|
||||
set ~mu4e-hide-short-counts~ to non-~nil~.
|
||||
~mu4e-search-maildir~, unread counts are displayed in the (default)
|
||||
completions UI next to the maildir or bookmark. If you don't want to see
|
||||
these counts, set ~mu4e-hide-short-counts~ to non-~nil~.
|
||||
|
||||
- A (experimental) "transient" menu has been added for mu4e. You can use it
|
||||
e.g., with something like:
|
||||
|
||||
@ -228,6 +228,13 @@ Sexp::to_json_string(Format fopts) const
|
||||
{
|
||||
std::stringstream sstrm;
|
||||
|
||||
const auto sym_name=[&](const std::string& sym) {
|
||||
if (any_of(fopts & Format::NoColon) && sym[0] == ':')
|
||||
return sym.substr(1); // remove colon
|
||||
else
|
||||
return sym;
|
||||
};
|
||||
|
||||
switch (type()) {
|
||||
case Type::List: {
|
||||
// property-lists become JSON objects
|
||||
@ -237,16 +244,18 @@ Sexp::to_json_string(Format fopts) const
|
||||
bool first{true};
|
||||
while (it != list().end()) {
|
||||
const auto key{it->symbol().name};
|
||||
sstrm << (first ? "" : ",") << quote(key) << ":";
|
||||
sstrm << (first ? "" : ",")
|
||||
<< quote(sym_name(key)) << ":";
|
||||
++it;
|
||||
const auto emacs_tstamp{*it};
|
||||
sstrm << emacs_tstamp.to_json_string();
|
||||
sstrm << emacs_tstamp.to_json_string(fopts);
|
||||
++it;
|
||||
first = false;
|
||||
// special-case: tstamp-fields also get a "unix" value,
|
||||
// which are easier to work with than the "emacs" timestamps
|
||||
if (key == ":date" || key == ":changed")
|
||||
sstrm << "," << quote(key + "-unix") << ":"
|
||||
sstrm << "," << quote(sym_name(key) + "-unix")
|
||||
<< ":"
|
||||
<< unix_tstamp(emacs_tstamp);
|
||||
}
|
||||
sstrm << "}";
|
||||
@ -256,7 +265,7 @@ Sexp::to_json_string(Format fopts) const
|
||||
sstrm << '[';
|
||||
bool first{true};
|
||||
for (auto&& child : list()) {
|
||||
sstrm << (first ? "" : ", ") << child.to_json_string();
|
||||
sstrm << (first ? "" : ", ") << child.to_json_string(fopts);
|
||||
first = false;
|
||||
}
|
||||
sstrm << ']';
|
||||
@ -287,7 +296,6 @@ Sexp::to_json_string(Format fopts) const
|
||||
}
|
||||
|
||||
|
||||
|
||||
Sexp&
|
||||
Sexp::del_prop(const std::string& pname)
|
||||
{
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2020-2023 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
** Copyright (C) 2020-2025 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the GNU General Public License as published by the
|
||||
@ -264,6 +264,8 @@ struct Sexp {
|
||||
Default = 0, /**< Nothing in particular */
|
||||
SplitList = 1 << 0, /**< Insert newline after list item */
|
||||
TypeInfo = 1 << 1, /**< Show type-info */
|
||||
NoColon = 1 << 2, /**< In the Json output, remove the colon
|
||||
* prefixes for property keys */
|
||||
};
|
||||
|
||||
/**
|
||||
@ -272,7 +274,7 @@ struct Sexp {
|
||||
* @return str
|
||||
*/
|
||||
std::string to_string(Format fopts=Format::Default) const;
|
||||
std::string to_json_string(Format fopts=Format::Default) const;
|
||||
std::string to_json_string(Format fopts) const;
|
||||
|
||||
Sexp& del_prop(const std::string& pname);
|
||||
|
||||
|
||||
@ -34,8 +34,9 @@ would find all messages in 2009 with `snow' in the subject field, e.g:
|
||||
#+end_example
|
||||
|
||||
Note, this the default, plain-text output, which is the default, so you don't
|
||||
have to use *--format=plain*. For other types of output (such as symlinks, XML or
|
||||
s-expressions), see the discussion in the *OPTIONS*-section below about *--format*.
|
||||
have to use *--format=plain*. For other types of output (such as symlinks, XML,
|
||||
s-expressions or JSON), see the discussion in the *OPTIONS*-section below about
|
||||
*--format*.
|
||||
|
||||
The search pattern is taken as a command-line parameter. If the search
|
||||
parameter consists of multiple parts (as in the example) they are
|
||||
@ -114,13 +115,15 @@ Note, if you specify a sortfield, by default, messages are sorted in reverse
|
||||
choice, but for dates it may be more useful to sort in the opposite direction.
|
||||
|
||||
** -n, --maxnum _number_
|
||||
|
||||
If _number_ > 0, display maximally that number of entries. If not specified, all
|
||||
matching entries are displayed.
|
||||
|
||||
** --summary-len _number_
|
||||
|
||||
If _number_ > 0, use that number of lines of the message to provide a summary.
|
||||
|
||||
** --format plain|links|xml|sexp
|
||||
** --format plain|links|xml|sexp|json|json2
|
||||
|
||||
Output results in the specified format.
|
||||
|
||||
@ -131,8 +134,13 @@ Output results in the specified format.
|
||||
- *xml* formats the search results as XML.
|
||||
- *sexp* formats the search results as an s-expression as used in Lisp programming
|
||||
environments.
|
||||
- *json* formats the output as JSON; it is a direct translation of the *sexp* format
|
||||
- *json2* is a slightly more idiomatic JSON, for now the only difference with *json*
|
||||
is that the latter avoids the ':' prefix in key-names (e.g., "subject" instead
|
||||
of ":subject"). *json2* is still experimental.
|
||||
|
||||
** --linksdir _dir_ and -c, --clearlinks
|
||||
|
||||
When using *--format=links*, output the results as a maildir with symbolic links
|
||||
to the found messages. This enables easy integration with mail-clients (see
|
||||
below for more information). *mu* will create the maildir if it does not exist
|
||||
@ -152,6 +160,7 @@ it automatically inserts a _.noindex_ file, to exclude the directory from *mu
|
||||
index*.
|
||||
|
||||
** --after _timestamp_
|
||||
|
||||
Only show messages whose message files were last modified (*mtime*) after
|
||||
_timestamp_. _timestamp_ is a UNIX *time_t* value, the number of seconds since
|
||||
1970-01-01 (in UTC).
|
||||
@ -279,8 +288,6 @@ After restarting Wanderlust, the virtual folders should appear.
|
||||
|
||||
*mu find* output is encoded according to the locale for *--format=plain* (the
|
||||
default format), and UTF-8 for all other formats (=sexp=, =xml=).
|
||||
|
||||
|
||||
* PERFORMANCE
|
||||
|
||||
Some notes on performance, comparing the timings between some recent releases;
|
||||
@ -289,7 +296,6 @@ taking the total number for 10 test runs.
|
||||
1. time (repeat 10 mu find "" -n 50000 > /dev/null)
|
||||
2. time (repeat 10 mu find "" -n 50000 --include-related --threads > /dev/null)
|
||||
|
||||
|
||||
#+ATTR_MAN: :disable-caption t
|
||||
| release | time 1 (sec) | time 2 (sec) |
|
||||
|---------------+--------------+--------------|
|
||||
@ -299,9 +305,6 @@ taking the total number for 10 test runs.
|
||||
| 1.10 | 9.8s | 30.6s |
|
||||
| 1.11 (master) | 10.1s | 29.5s |
|
||||
|
||||
|
||||
|
||||
|
||||
#+include: "exit-code.inc" :minlevel 1
|
||||
|
||||
#+include: "bugs.inc" :minlevel 1
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2008-2024 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
** Copyright (C) 2008-2025 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the GNU General Public License as published by the
|
||||
@ -383,7 +383,10 @@ output_json(const Option<Message>& msg, const OutputInfo& info, const Options& o
|
||||
if (!msg)
|
||||
return Ok();
|
||||
|
||||
mu_println("{}{}", msg->sexp().to_json_string(), info.last ? "" : ",");
|
||||
const Sexp::Format frm{opts.find.format == Format::Json2 ? Sexp::Format::NoColon :
|
||||
Sexp::Format::Default};
|
||||
|
||||
mu_println("{}{}", msg->sexp().to_json_string(frm), info.last ? "" : ",");
|
||||
|
||||
return Ok();
|
||||
}
|
||||
@ -443,6 +446,7 @@ get_output_func(const Options& opts)
|
||||
case Format::Sexp:
|
||||
return output_sexp;
|
||||
case Format::Json:
|
||||
case Format::Json2:
|
||||
return output_json;
|
||||
default:
|
||||
throw Error(Error::Code::Internal,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2022-2024 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
** Copyright (C) 2022-2025 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the GNU General Public License as published by the
|
||||
@ -339,6 +339,9 @@ sub_find(CLI::App& sub, Options& opts)
|
||||
{ Format::Json,
|
||||
{"json", "JSON"}
|
||||
},
|
||||
{ Format::Json2,
|
||||
{"json2", "more idiomatic JSON"}
|
||||
},
|
||||
}};
|
||||
|
||||
sub.add_flag("--threads,-t", opts.find.threads,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
** Copyright (C) 2022-2023 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
** Copyright (C) 2022-2025 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the GNU General Public License as published by the
|
||||
@ -149,7 +149,7 @@ struct Options {
|
||||
std::string bookmark; /**< use bookmark */
|
||||
bool analyze; /**< analyze query */
|
||||
|
||||
enum struct Format { Plain, Links, Xml, Json, Sexp, Exec };
|
||||
enum struct Format { Plain, Links, Xml, Json, Json2, Sexp, Exec };
|
||||
Format format; /**< Output format */
|
||||
std::string exec; /**< cmd to execute on matches */
|
||||
bool skip_dups; /**< show only first with msg id */
|
||||
|
||||
Reference in New Issue
Block a user