fields: make combi-fields introspectable
And add the display of combination-fields to 'mu info fields'.
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
|
||||||
@ -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
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user