mu-sexp: add -unix output for json tstamps
The json output (for mu-find etc.) just showed the converted sexp output, including the clumsy emacs-style tstamps (for changed/date). Add unix timestamps as well, which are easier to work with outside emacs. This handles #2770.
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright (C) 2022-2023 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
** Copyright (C) 2022-2024 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||||
**
|
**
|
||||||
** This program is free software; you can redistribute it and/or modify it
|
** 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
|
** under the terms of the GNU General Public License as published by the
|
||||||
@ -60,15 +60,18 @@ parse_list(const std::string& expr, size_t& pos)
|
|||||||
Sexp lst{};
|
Sexp lst{};
|
||||||
|
|
||||||
++pos;
|
++pos;
|
||||||
while (expr[pos] != ')' && pos != expr.size()) {
|
while (pos < expr.size() && expr[pos] != ')') {
|
||||||
if (auto&& item = parse(expr, pos); item)
|
if (auto&& item = parse(expr, pos); item)
|
||||||
lst.add(std::move(*item));
|
lst.add(std::move(*item));
|
||||||
else
|
else
|
||||||
return Err(item.error());
|
return Err(item.error());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expr[pos] != ')')
|
if (pos >= expr.size())
|
||||||
|
return Err(parsing_error(pos, "expected: ')'"));
|
||||||
|
else if (expr[pos] != ')')
|
||||||
return Err(parsing_error(pos, "expected: ')' but got '{}'", expr[pos]));
|
return Err(parsing_error(pos, "expected: ')' but got '{}'", expr[pos]));
|
||||||
|
|
||||||
++pos;
|
++pos;
|
||||||
return Ok(std::move(lst));
|
return Ok(std::move(lst));
|
||||||
}
|
}
|
||||||
@ -209,6 +212,17 @@ Sexp::to_string(Format fopts) const
|
|||||||
|
|
||||||
// LCOV_EXCL_START
|
// LCOV_EXCL_START
|
||||||
|
|
||||||
|
// convert emacs-timestamp (a list) to a unix-tstamp
|
||||||
|
static uint64_t
|
||||||
|
unix_tstamp(const Sexp& emacs_tstamp)
|
||||||
|
{
|
||||||
|
if (!emacs_tstamp.listp() || emacs_tstamp.list().size() < 2)
|
||||||
|
throw std::runtime_error("unexpected type");
|
||||||
|
|
||||||
|
const auto& lst{emacs_tstamp.list()};
|
||||||
|
return (lst.at(0).number() << 16) | lst.at(1).number();
|
||||||
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
Sexp::to_json_string(Format fopts) const
|
Sexp::to_json_string(Format fopts) const
|
||||||
{
|
{
|
||||||
@ -222,11 +236,18 @@ Sexp::to_json_string(Format fopts) const
|
|||||||
auto it{list().begin()};
|
auto it{list().begin()};
|
||||||
bool first{true};
|
bool first{true};
|
||||||
while (it != list().end()) {
|
while (it != list().end()) {
|
||||||
sstrm << (first ? "" : ",") << quote(it->symbol().name) << ":";
|
const auto key{it->symbol().name};
|
||||||
|
sstrm << (first ? "" : ",") << quote(key) << ":";
|
||||||
++it;
|
++it;
|
||||||
sstrm << it->to_json_string();
|
const auto emacs_tstamp{*it};
|
||||||
|
sstrm << emacs_tstamp.to_json_string();
|
||||||
++it;
|
++it;
|
||||||
first = false;
|
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") << ":"
|
||||||
|
<< unix_tstamp(emacs_tstamp);
|
||||||
}
|
}
|
||||||
sstrm << "}";
|
sstrm << "}";
|
||||||
if (any_of(fopts & Format::SplitList))
|
if (any_of(fopts & Format::SplitList))
|
||||||
|
|||||||
Reference in New Issue
Block a user