fields: make combi-fields introspectable

And add the display of combination-fields to 'mu info fields'.
This commit is contained in:
Dirk-Jan C. Binnema
2024-11-30 22:58:15 +02:00
parent 0200cfd647
commit 8c7db59972
3 changed files with 112 additions and 44 deletions

View File

@ -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
@ -19,11 +19,59 @@
#include "mu-fields.hh" #include "mu-fields.hh"
#include "mu-flags.hh" #include "mu-flags.hh"
#include "utils/mu-utils.hh"
#include "utils/mu-test-utils.hh" #include "utils/mu-test-utils.hh"
using namespace Mu; 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 std::string
Field::xapian_term(const std::string& s) const Field::xapian_term(const std::string& s) const
{ {

View File

@ -402,7 +402,7 @@ static constexpr std::array<Field, Field::id_size()>
{}, {},
'r', 'r',
Field::Flag::Value | Field::Flag::Value |
Field::Flag::BooleanTerm | Field::Flag::BooleanTerm |
Field::Flag::IncludeInSexp Field::Flag::IncludeInSexp
}, },
{ {
@ -534,6 +534,25 @@ Option<Field> field_from_name(const std::string& name) {
} }
} }
using FieldsVec = std::vector<Field>; /**< 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<CombiField>; /**< vec of combi-fields */
/**
* Get information about the combination fields
*
* @return vector with information.
*/
const CombiFields& combi_fields();
/** /**
* Return combination-fields such * Return combination-fields such
* as "contact", "recip" and "" (empty) * as "contact", "recip" and "" (empty)
@ -542,48 +561,16 @@ Option<Field> field_from_name(const std::string& name) {
* *
* @return list of matching fields * @return list of matching fields
*/ */
using FieldsVec = std::vector<Field>; const FieldsVec& fields_from_name(const std::string& name);
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";
}
/**
* 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 * Get the Field::Id for some number, or nullopt if it does not match

View File

@ -136,6 +136,37 @@ topic_fields(const Options& opts)
return Ok(); return Ok();
} }
static Result<void>
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{"<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<void> static Result<void>
topic_flags(const Options& opts) topic_flags(const Options& opts)
{ {
@ -290,7 +321,9 @@ Mu::mu_cmd_info(const Mu::Store& store, const Options& opts)
else if (topic == "fields") { else if (topic == "fields") {
topic_fields(opts); topic_fields(opts);
std::cout << std::endl; std::cout << std::endl;
return topic_flags(opts); topic_combi_fields(opts);
std::cout << std::endl;
topic_flags(opts);
} else if (topic == "mu") { } else if (topic == "mu") {
return topic_mu(opts); return topic_mu(opts);
} else { } else {