From 8c7db599727f42bf381fb4b636b462a82256dcf8 Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Sat, 30 Nov 2024 22:58:15 +0200 Subject: [PATCH] fields: make combi-fields introspectable And add the display of combination-fields to 'mu info fields'. --- lib/message/mu-fields.cc | 50 +++++++++++++++++++++++++++- lib/message/mu-fields.hh | 71 ++++++++++++++++------------------------ mu/mu-cmd-info.cc | 35 +++++++++++++++++++- 3 files changed, 112 insertions(+), 44 deletions(-) diff --git a/lib/message/mu-fields.cc b/lib/message/mu-fields.cc index f64df5fa..57399b59 100644 --- a/lib/message/mu-fields.cc +++ b/lib/message/mu-fields.cc @@ -1,5 +1,5 @@ /* -** Copyright (C) 2022-2023 Dirk-Jan C. Binnema +** Copyright (C) 2022-2024 Dirk-Jan C. Binnema ** ** 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 @@ -19,11 +19,59 @@ #include "mu-fields.hh" #include "mu-flags.hh" +#include "utils/mu-utils.hh" #include "utils/mu-test-utils.hh" using namespace Mu; +const Mu::CombiFields& +Mu::combi_fields() +{ + static CombiFields cfields = { + CombiField{ "recip", + { field_from_id(Field::Id::To), + field_from_id(Field::Id::Cc), + field_from_id(Field::Id::Bcc)}}, + CombiField { "contact", + { field_from_id(Field::Id::To), + field_from_id(Field::Id::Cc), + field_from_id(Field::Id::Bcc), + field_from_id(Field::Id::From)}}, + CombiField { "", + { field_from_id(Field::Id::To), + field_from_id(Field::Id::Cc), + field_from_id(Field::Id::Bcc), + field_from_id(Field::Id::From), + field_from_id(Field::Id::Subject), + field_from_id(Field::Id::BodyText), + field_from_id(Field::Id::EmbeddedText), + }} + }; + + return cfields; +} + +const Mu::FieldsVec& +Mu::fields_from_name(const std::string& name) { + + static const FieldsVec empty; + const auto& cfields{combi_fields()}; + const auto it = seq_find_if(cfields, [&](auto cfield) { + return cfield.name == name; + }); + + return it == cfields.end() ? empty : it->fields; +} + +bool +Mu::field_is_combi(const std::string& name) +{ + return name != "" && seq_some(combi_fields(),[&](auto cfield) { + return cfield.name == name; + }); +} + std::string Field::xapian_term(const std::string& s) const { diff --git a/lib/message/mu-fields.hh b/lib/message/mu-fields.hh index 63838aa1..afa40362 100644 --- a/lib/message/mu-fields.hh +++ b/lib/message/mu-fields.hh @@ -402,7 +402,7 @@ static constexpr std::array {}, 'r', Field::Flag::Value | - Field::Flag::BooleanTerm | + Field::Flag::BooleanTerm | Field::Flag::IncludeInSexp }, { @@ -534,6 +534,25 @@ Option field_from_name(const std::string& name) { } } +using FieldsVec = std::vector; /**< Vec of fields */ + +/** + * Describe a combination-field, i.e., a pseudo-field that + * expands to some real fields, as a query shortcut. + */ +struct CombiField { + std::string_view name; /**< name of the combi-field */ + FieldsVec fields; /**< fields this resolves to */ +}; +using CombiFields = std::vector; /**< vec of combi-fields */ + +/** + * Get information about the combination fields + * + * @return vector with information. + */ +const CombiFields& combi_fields(); + /** * Return combination-fields such * as "contact", "recip" and "" (empty) @@ -542,48 +561,16 @@ Option field_from_name(const std::string& name) { * * @return list of matching fields */ -using FieldsVec = std::vector; -static inline -const FieldsVec& fields_from_name(const std::string& name) { - - static const FieldsVec none{}; - static const FieldsVec recip_fields ={ - field_from_id(Field::Id::To), - field_from_id(Field::Id::Cc), - field_from_id(Field::Id::Bcc)}; - - static const FieldsVec contact_fields = { - field_from_id(Field::Id::To), - field_from_id(Field::Id::Cc), - field_from_id(Field::Id::Bcc), - field_from_id(Field::Id::From), - }; - static const FieldsVec empty_fields= { - field_from_id(Field::Id::To), - field_from_id(Field::Id::Cc), - field_from_id(Field::Id::Bcc), - field_from_id(Field::Id::From), - field_from_id(Field::Id::Subject), - field_from_id(Field::Id::BodyText), - field_from_id(Field::Id::EmbeddedText), - }; - - if (name == "recip") - return recip_fields; - else if (name == "contact") - return contact_fields; - else if (name.empty()) - return empty_fields; - else - return none; -} - -static inline bool -field_is_combi (const std::string& name) -{ - return name == "recip" || name == "contact"; -} +const FieldsVec& fields_from_name(const std::string& name); +/** + * Is the field a combination field? + * + * @param name name of the field + * + * @return true or false + */ +bool field_is_combi (const std::string& name); /** * Get the Field::Id for some number, or nullopt if it does not match diff --git a/mu/mu-cmd-info.cc b/mu/mu-cmd-info.cc index 923a59e6..257c9093 100644 --- a/mu/mu-cmd-info.cc +++ b/mu/mu-cmd-info.cc @@ -136,6 +136,37 @@ topic_fields(const Options& opts) return Ok(); } +static Result +topic_combi_fields(const Options& opts) +{ + using namespace std::string_literals; + + Table fields; + fields.add_row({"combi-field", "fields"}); + + seq_for_each(combi_fields(), [&](const auto& cfield) { + + std::string fnames; + seq_for_each(cfield.fields, [&](auto&& field) { + if (!fnames.empty()) + fnames += ", "; + fnames += mu_format("{}", field.name); + }); + + const std::string empty{""}; + + fields.add_row({cfield.name.empty() ? empty : mu_format("{}", cfield.name), + fnames}); + }); + + colorify(fields, opts); + std::cout << "# Combination fields\n" << fields << '\n'; + + return Ok(); +} + + + static Result topic_flags(const Options& opts) { @@ -290,7 +321,9 @@ Mu::mu_cmd_info(const Mu::Store& store, const Options& opts) else if (topic == "fields") { topic_fields(opts); std::cout << std::endl; - return topic_flags(opts); + topic_combi_fields(opts); + std::cout << std::endl; + topic_flags(opts); } else if (topic == "mu") { return topic_mu(opts); } else {