2022-02-23 08:29:37 +01:00
|
|
|
/*
|
2023-09-17 08:59:38 +02:00
|
|
|
** Copyright (C) 2022-2023 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
2022-02-23 08:29:37 +01:00
|
|
|
**
|
|
|
|
** 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
|
|
|
|
** Free Software Foundation; either version 3, or (at your option) any
|
|
|
|
** later version.
|
|
|
|
**
|
|
|
|
** This program is distributed in the hope that it will be useful,
|
|
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
** GNU General Public License for more details.
|
|
|
|
**
|
|
|
|
** You should have received a copy of the GNU General Public License
|
|
|
|
** along with this program; if not, write to the Free Software Foundation,
|
|
|
|
** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
|
2022-03-19 17:56:10 +01:00
|
|
|
#ifndef MU_FIELDS_HH__
|
|
|
|
#define MU_FIELDS_HH__
|
2022-02-23 08:29:37 +01:00
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
#include <string_view>
|
|
|
|
#include <algorithm>
|
|
|
|
#include <array>
|
|
|
|
#include <xapian.h>
|
|
|
|
#include <utils/mu-utils.hh>
|
2022-03-26 15:19:08 +01:00
|
|
|
#include <utils/mu-option.hh>
|
2022-02-23 08:29:37 +01:00
|
|
|
|
|
|
|
namespace Mu {
|
|
|
|
|
2022-05-09 19:10:37 +02:00
|
|
|
// Xapian does not like terms much longer than this
|
|
|
|
constexpr auto MaxTermLength = 240;
|
|
|
|
// http://article.gmane.org/gmane.comp.search.xapian.general/3656 */
|
|
|
|
|
2022-03-19 17:56:10 +01:00
|
|
|
struct Field {
|
2022-02-23 08:29:37 +01:00
|
|
|
/**
|
|
|
|
* Field Ids.
|
|
|
|
*
|
2022-03-19 17:56:10 +01:00
|
|
|
* Note, the Ids are also used as indices in the Fields array,
|
2022-02-23 08:29:37 +01:00
|
|
|
* so their numerical values must be 0...Count.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
enum struct Id {
|
2022-04-30 00:17:31 +02:00
|
|
|
Bcc = 0, /**< Blind Carbon-Copy */
|
|
|
|
BodyText, /**< Text body */
|
|
|
|
Cc, /**< Carbon-Copy */
|
2022-05-05 00:22:14 +02:00
|
|
|
Changed, /**< Last change time (think 'ctime') */
|
2022-04-30 00:17:31 +02:00
|
|
|
Date, /**< Message date */
|
|
|
|
EmbeddedText, /**< Embedded text in message */
|
|
|
|
File, /**< Filename */
|
|
|
|
Flags, /**< Message flags */
|
|
|
|
From, /**< Message sender */
|
2023-05-11 22:22:29 +02:00
|
|
|
Language, /**< Body language */
|
2022-04-30 00:17:31 +02:00
|
|
|
Maildir, /**< Maildir path */
|
|
|
|
MailingList, /**< Mailing list */
|
|
|
|
MessageId, /**< Message Id */
|
2022-05-05 00:22:14 +02:00
|
|
|
MimeType, /**< MIME-Type */
|
2022-04-30 00:17:31 +02:00
|
|
|
Path, /**< File-system Path */
|
|
|
|
Priority, /**< Message priority */
|
|
|
|
References, /**< All references (incl. Reply-To:) */
|
|
|
|
Size, /**< Message size (in bytes) */
|
|
|
|
Subject, /**< Message subject */
|
|
|
|
Tags, /**< Message Tags */
|
|
|
|
ThreadId, /**< Thread Id */
|
|
|
|
To, /**< To: recipient */
|
2023-07-23 13:46:11 +02:00
|
|
|
//
|
|
|
|
_count_ /**< Number of Ids */
|
2022-02-23 08:29:37 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the number of Id values.
|
|
|
|
*
|
|
|
|
* @return the number.
|
|
|
|
*/
|
|
|
|
static constexpr size_t id_size()
|
|
|
|
{
|
|
|
|
return static_cast<size_t>(Id::_count_);
|
|
|
|
}
|
|
|
|
|
2022-03-03 23:02:52 +01:00
|
|
|
constexpr Xapian::valueno value_no() const {
|
|
|
|
return static_cast<Xapian::valueno>(id);
|
|
|
|
}
|
|
|
|
|
2022-02-23 08:29:37 +01:00
|
|
|
/**
|
|
|
|
* Field types
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
enum struct Type {
|
2022-04-28 21:53:31 +02:00
|
|
|
String, /**< String */
|
|
|
|
StringList, /**< List of strings */
|
|
|
|
ContactList, /**< List of contacts */
|
|
|
|
ByteSize, /**< Size in bytes */
|
|
|
|
TimeT, /**< A time_t value */
|
|
|
|
Integer, /**< An integer */
|
2022-02-23 08:29:37 +01:00
|
|
|
};
|
|
|
|
|
2022-03-03 23:02:52 +01:00
|
|
|
constexpr bool is_string() const { return type == Type::String; }
|
|
|
|
constexpr bool is_string_list() const { return type == Type::StringList; }
|
|
|
|
constexpr bool is_byte_size() const { return type == Type::ByteSize; }
|
|
|
|
constexpr bool is_time_t() const { return type == Type::TimeT; }
|
|
|
|
constexpr bool is_integer() const { return type == Type::Integer; }
|
|
|
|
constexpr bool is_numerical() const { return is_byte_size() || is_time_t() || is_integer(); }
|
|
|
|
|
2022-02-23 08:29:37 +01:00
|
|
|
/**
|
|
|
|
* Field flags
|
|
|
|
* note: the differences for our purposes between a xapian field and a
|
|
|
|
* term: - there is only a single value for some item in per document
|
|
|
|
* (msg), ie. one value containing the list of To: addresses - there
|
|
|
|
* can be multiple terms, each containing e.g. one of the To:
|
|
|
|
* addresses - searching uses terms, but to display some field, it
|
2023-09-17 08:59:38 +02:00
|
|
|
* must be in the value
|
2022-03-19 17:41:05 +01:00
|
|
|
*
|
|
|
|
* Rules (build-time enforced):
|
2023-09-17 08:59:38 +02:00
|
|
|
* - A field has at most one of PhrasableTerm, BooleanTerm, ContactTerm.
|
2022-02-23 08:29:37 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
enum struct Flag {
|
2022-03-19 17:41:05 +01:00
|
|
|
/*
|
2023-09-17 08:59:38 +02:00
|
|
|
* Different kind of terms; at most one is true, and cannot be combined with
|
|
|
|
* Contact. Compile-time enforced.
|
2022-03-19 17:41:05 +01:00
|
|
|
*/
|
2022-04-28 21:53:31 +02:00
|
|
|
NormalTerm = 1 << 0,
|
2022-02-23 08:29:37 +01:00
|
|
|
/**< Field is a searchable term */
|
2022-04-28 21:53:31 +02:00
|
|
|
BooleanTerm = 1 << 1,
|
|
|
|
/**< Field is a boolean search-term (i.e. at most one per message);
|
|
|
|
* wildcards do not work */
|
2023-09-17 08:59:38 +02:00
|
|
|
PhrasableTerm = 1 << 2,
|
|
|
|
/**< Field has phrasable/indexable text as term */
|
2022-03-19 17:41:05 +01:00
|
|
|
/*
|
|
|
|
* Contact flag cannot be combined with any of the term flags.
|
|
|
|
* This is compile-time enforced.
|
|
|
|
*/
|
2022-04-28 21:53:31 +02:00
|
|
|
Contact = 1 << 10,
|
2022-03-19 17:41:05 +01:00
|
|
|
/**< field contains one or more e-mail-addresses */
|
2022-04-28 21:53:31 +02:00
|
|
|
Value = 1 << 11,
|
2022-02-23 08:29:37 +01:00
|
|
|
/**< Field value is stored (so the literal value can be retrieved) */
|
2022-03-19 17:41:05 +01:00
|
|
|
|
2022-04-30 00:17:31 +02:00
|
|
|
Range = 1 << 21,
|
2022-05-05 00:22:14 +02:00
|
|
|
|
|
|
|
IncludeInSexp = 1 << 24,
|
|
|
|
/**< whether to include this field in the cached sexp. */
|
|
|
|
|
2022-03-19 17:41:05 +01:00
|
|
|
/**< whether this is a range field (e.g., date, size)*/
|
2022-05-05 00:22:14 +02:00
|
|
|
Internal = 1 << 26
|
2022-02-23 08:29:37 +01:00
|
|
|
};
|
|
|
|
|
2022-03-03 23:02:52 +01:00
|
|
|
constexpr bool any_of(Flag some_flag) const{
|
|
|
|
return (static_cast<int>(some_flag) & static_cast<int>(flags)) != 0;
|
|
|
|
}
|
|
|
|
|
2023-09-17 08:59:38 +02:00
|
|
|
constexpr bool is_phrasable_term() const { return any_of(Flag::PhrasableTerm); }
|
2022-03-19 17:41:05 +01:00
|
|
|
constexpr bool is_boolean_term() const { return any_of(Flag::BooleanTerm); }
|
|
|
|
constexpr bool is_normal_term() const { return any_of(Flag::NormalTerm); }
|
2023-09-17 08:59:38 +02:00
|
|
|
constexpr bool is_searchable() const { return is_phrasable_term() ||
|
2022-03-19 17:56:10 +01:00
|
|
|
is_boolean_term() ||
|
|
|
|
is_normal_term(); }
|
2022-11-22 22:16:37 +01:00
|
|
|
constexpr bool is_sortable() const { return is_value(); }
|
|
|
|
|
2022-03-19 17:56:10 +01:00
|
|
|
|
2022-03-19 17:41:05 +01:00
|
|
|
constexpr bool is_value() const { return any_of(Flag::Value); }
|
2022-04-30 00:17:31 +02:00
|
|
|
constexpr bool is_internal() const { return any_of(Flag::Internal); }
|
2022-03-19 17:41:05 +01:00
|
|
|
|
|
|
|
constexpr bool is_contact() const { return any_of(Flag::Contact); }
|
|
|
|
constexpr bool is_range() const { return any_of(Flag::Range); }
|
2022-03-19 17:56:10 +01:00
|
|
|
|
2022-05-05 00:22:14 +02:00
|
|
|
constexpr bool include_in_sexp() const { return any_of(Flag::IncludeInSexp);}
|
|
|
|
|
2022-02-23 08:29:37 +01:00
|
|
|
/**
|
|
|
|
* Field members
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
Id id; /**< Id of the message field */
|
|
|
|
Type type; /**< Type of the message field */
|
|
|
|
std::string_view name; /**< Name of the message field */
|
2022-05-05 00:22:14 +02:00
|
|
|
std::string_view alias; /**< Alternative name for the message field */
|
2022-02-23 08:29:37 +01:00
|
|
|
std::string_view description; /**< Decription of the message field */
|
|
|
|
std::string_view example_query; /**< Example query */
|
|
|
|
char shortcut; /**< Shortcut for the message field; a..z */
|
|
|
|
Flag flags; /**< Flags */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Convenience / helpers
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2022-11-07 17:22:31 +01:00
|
|
|
constexpr char xapian_prefix() const {
|
|
|
|
/* xapian uses uppercase shortcuts; toupper is not constexpr */
|
2022-02-23 08:29:37 +01:00
|
|
|
return shortcut == 0 ? 0 : shortcut - ('a' - 'A');
|
|
|
|
}
|
|
|
|
|
2022-04-28 21:53:31 +02:00
|
|
|
/**
|
|
|
|
* Get the xapian term; truncated to MaxTermLength and
|
|
|
|
* utf8-flattened.
|
|
|
|
*
|
|
|
|
* @param s
|
|
|
|
*
|
|
|
|
* @return the xapian term
|
|
|
|
*/
|
2022-03-03 23:02:52 +01:00
|
|
|
std::string xapian_term(const std::string& s="") const;
|
2022-04-28 21:53:31 +02:00
|
|
|
std::string xapian_term(std::string_view sv) const {
|
|
|
|
return xapian_term(std::string{sv});
|
|
|
|
}
|
|
|
|
std::string xapian_term(char c) const {
|
|
|
|
return xapian_term(std::string(1, c));
|
|
|
|
}
|
2022-02-23 08:29:37 +01:00
|
|
|
};
|
|
|
|
|
2023-09-09 10:59:00 +02:00
|
|
|
// equality
|
|
|
|
static inline constexpr bool operator==(const Field& f1, const Field& f2) { return f1.id == f2.id; }
|
|
|
|
static inline constexpr bool operator==(const Field& f1, const Field::Id id) { return f1.id == id; }
|
|
|
|
|
2023-06-04 13:29:57 +02:00
|
|
|
|
2022-03-19 17:56:10 +01:00
|
|
|
MU_ENABLE_BITOPS(Field::Flag);
|
2022-02-23 08:29:37 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Sequence of _all_ message fields
|
|
|
|
*/
|
2022-03-19 17:56:10 +01:00
|
|
|
static constexpr std::array<Field, Field::id_size()>
|
|
|
|
Fields = {
|
2022-02-23 08:29:37 +01:00
|
|
|
{
|
|
|
|
{
|
2022-03-19 17:56:10 +01:00
|
|
|
Field::Id::Bcc,
|
2022-04-28 21:53:31 +02:00
|
|
|
Field::Type::ContactList,
|
2022-05-05 00:22:14 +02:00
|
|
|
"bcc", {},
|
2022-02-23 08:29:37 +01:00
|
|
|
"Blind carbon-copy recipient",
|
|
|
|
"bcc:foo@example.com",
|
|
|
|
'h',
|
2022-03-19 17:56:10 +01:00
|
|
|
Field::Flag::Contact |
|
2022-05-05 00:22:14 +02:00
|
|
|
Field::Flag::Value |
|
2022-06-08 23:02:37 +02:00
|
|
|
Field::Flag::IncludeInSexp |
|
2023-09-17 08:59:38 +02:00
|
|
|
Field::Flag::NormalTerm |
|
|
|
|
Field::Flag::PhrasableTerm,
|
2022-03-19 17:41:05 +01:00
|
|
|
},
|
2022-02-23 08:29:37 +01:00
|
|
|
{
|
2022-03-19 17:56:10 +01:00
|
|
|
Field::Id::BodyText,
|
|
|
|
Field::Type::String,
|
2022-05-05 00:22:14 +02:00
|
|
|
"body", {},
|
2022-02-23 08:29:37 +01:00
|
|
|
"Message plain-text body",
|
2022-04-30 00:17:31 +02:00
|
|
|
"body:capybara",
|
2022-02-23 08:29:37 +01:00
|
|
|
'b',
|
2023-09-17 08:59:38 +02:00
|
|
|
Field::Flag::PhrasableTerm,
|
2022-03-19 17:41:05 +01:00
|
|
|
},
|
2022-02-23 08:29:37 +01:00
|
|
|
{
|
2022-03-19 17:56:10 +01:00
|
|
|
Field::Id::Cc,
|
2022-04-28 21:53:31 +02:00
|
|
|
Field::Type::ContactList,
|
2022-05-05 00:22:14 +02:00
|
|
|
"cc", {},
|
2022-02-23 08:29:37 +01:00
|
|
|
"Carbon-copy recipient",
|
|
|
|
"cc:quinn@example.com",
|
|
|
|
'c',
|
2022-03-19 17:56:10 +01:00
|
|
|
Field::Flag::Contact |
|
2022-05-05 00:22:14 +02:00
|
|
|
Field::Flag::Value |
|
2022-06-08 23:02:37 +02:00
|
|
|
Field::Flag::IncludeInSexp |
|
2023-09-17 08:59:38 +02:00
|
|
|
Field::Flag::NormalTerm |
|
|
|
|
Field::Flag::PhrasableTerm,
|
2022-05-05 00:22:14 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Field::Id::Changed,
|
|
|
|
Field::Type::TimeT,
|
|
|
|
"changed", {},
|
|
|
|
"Last change time",
|
2022-05-06 21:01:27 +02:00
|
|
|
"changed:30M..",
|
2022-05-05 00:22:14 +02:00
|
|
|
'k',
|
|
|
|
Field::Flag::Value |
|
|
|
|
Field::Flag::Range |
|
|
|
|
Field::Flag::IncludeInSexp
|
2022-04-28 21:53:31 +02:00
|
|
|
},
|
2022-04-30 00:17:31 +02:00
|
|
|
{
|
|
|
|
Field::Id::Date,
|
|
|
|
Field::Type::TimeT,
|
2022-05-05 00:22:14 +02:00
|
|
|
"date", {},
|
2022-04-30 00:17:31 +02:00
|
|
|
"Message date",
|
|
|
|
"date:20220101..20220505",
|
|
|
|
'd',
|
|
|
|
Field::Flag::Value |
|
2022-05-05 00:22:14 +02:00
|
|
|
Field::Flag::Range |
|
|
|
|
Field::Flag::IncludeInSexp
|
2022-04-30 00:17:31 +02:00
|
|
|
},
|
2022-02-23 08:29:37 +01:00
|
|
|
{
|
2022-03-19 17:56:10 +01:00
|
|
|
Field::Id::EmbeddedText,
|
|
|
|
Field::Type::String,
|
2022-05-05 00:22:14 +02:00
|
|
|
"embed", {},
|
2022-02-23 08:29:37 +01:00
|
|
|
"Embedded text",
|
|
|
|
"embed:war OR embed:peace",
|
|
|
|
'e',
|
2023-09-17 08:59:38 +02:00
|
|
|
Field::Flag::PhrasableTerm
|
2022-04-28 21:53:31 +02:00
|
|
|
},
|
2022-02-23 08:29:37 +01:00
|
|
|
{
|
2022-03-19 17:56:10 +01:00
|
|
|
Field::Id::File,
|
|
|
|
Field::Type::String,
|
2022-05-05 00:22:14 +02:00
|
|
|
"file", {},
|
2022-02-23 08:29:37 +01:00
|
|
|
"Attachment file name",
|
|
|
|
"file:/image\\.*.jpg/",
|
|
|
|
'j',
|
2022-05-05 00:22:14 +02:00
|
|
|
Field::Flag::BooleanTerm
|
2022-04-28 21:53:31 +02:00
|
|
|
},
|
2022-04-30 00:17:31 +02:00
|
|
|
{
|
|
|
|
Field::Id::Flags,
|
|
|
|
Field::Type::Integer,
|
2022-05-05 00:22:14 +02:00
|
|
|
"flags", "flag",
|
2022-04-30 00:17:31 +02:00
|
|
|
"Message properties",
|
2022-05-12 07:50:47 +02:00
|
|
|
"flag:unread AND flag:personal",
|
2022-04-30 00:17:31 +02:00
|
|
|
'g',
|
2022-05-05 00:22:14 +02:00
|
|
|
Field::Flag::BooleanTerm |
|
|
|
|
Field::Flag::Value |
|
|
|
|
Field::Flag::IncludeInSexp
|
2022-04-30 00:17:31 +02:00
|
|
|
},
|
2022-02-23 08:29:37 +01:00
|
|
|
{
|
2022-03-19 17:56:10 +01:00
|
|
|
Field::Id::From,
|
2022-04-28 21:53:31 +02:00
|
|
|
Field::Type::ContactList,
|
2022-05-05 00:22:14 +02:00
|
|
|
"from", {},
|
2022-02-23 08:29:37 +01:00
|
|
|
"Message sender",
|
|
|
|
"from:jimbo",
|
|
|
|
'f',
|
2022-03-19 17:56:10 +01:00
|
|
|
Field::Flag::Contact |
|
2022-05-05 00:22:14 +02:00
|
|
|
Field::Flag::Value |
|
2022-06-08 23:02:37 +02:00
|
|
|
Field::Flag::IncludeInSexp |
|
2023-09-17 08:59:38 +02:00
|
|
|
Field::Flag::NormalTerm |
|
|
|
|
Field::Flag::PhrasableTerm,
|
2022-04-28 21:53:31 +02:00
|
|
|
},
|
2023-05-11 22:22:29 +02:00
|
|
|
{
|
|
|
|
Field::Id::Language,
|
|
|
|
Field::Type::String,
|
|
|
|
"language", "lang",
|
|
|
|
"ISO 639-1 language code for body",
|
|
|
|
"lang:nl",
|
|
|
|
'a',
|
|
|
|
Field::Flag::BooleanTerm |
|
|
|
|
Field::Flag::Value |
|
|
|
|
Field::Flag::IncludeInSexp
|
|
|
|
},
|
2022-02-23 08:29:37 +01:00
|
|
|
{
|
2022-03-19 17:56:10 +01:00
|
|
|
Field::Id::Maildir,
|
|
|
|
Field::Type::String,
|
2022-05-05 00:22:14 +02:00
|
|
|
"maildir", {},
|
2022-02-23 08:29:37 +01:00
|
|
|
"Maildir path for message",
|
|
|
|
"maildir:/private/archive",
|
|
|
|
'm',
|
2022-04-28 21:53:31 +02:00
|
|
|
Field::Flag::BooleanTerm |
|
2022-05-05 00:22:14 +02:00
|
|
|
Field::Flag::Value |
|
|
|
|
Field::Flag::IncludeInSexp
|
2022-04-28 21:53:31 +02:00
|
|
|
},
|
2022-02-23 08:29:37 +01:00
|
|
|
{
|
2022-04-30 00:17:31 +02:00
|
|
|
Field::Id::MailingList,
|
2022-03-19 17:56:10 +01:00
|
|
|
Field::Type::String,
|
2022-05-07 19:48:21 +02:00
|
|
|
"list", {},
|
2022-04-30 00:17:31 +02:00
|
|
|
"Mailing list (List-Id:)",
|
|
|
|
"list:mu-discuss.example.com",
|
|
|
|
'v',
|
|
|
|
Field::Flag::BooleanTerm |
|
2022-05-05 00:22:14 +02:00
|
|
|
Field::Flag::Value |
|
|
|
|
Field::Flag::IncludeInSexp
|
2022-04-28 21:53:31 +02:00
|
|
|
},
|
2022-02-23 08:29:37 +01:00
|
|
|
{
|
2022-03-19 17:56:10 +01:00
|
|
|
Field::Id::MessageId,
|
|
|
|
Field::Type::String,
|
2022-05-05 00:22:14 +02:00
|
|
|
"message-id", "msgid",
|
2022-05-12 07:50:47 +02:00
|
|
|
"Message-Id",
|
2022-03-26 15:19:08 +01:00
|
|
|
"msgid:abc@123",
|
2022-02-23 08:29:37 +01:00
|
|
|
'i',
|
2022-04-28 21:53:31 +02:00
|
|
|
Field::Flag::BooleanTerm |
|
2022-05-05 00:22:14 +02:00
|
|
|
Field::Flag::Value |
|
|
|
|
Field::Flag::IncludeInSexp
|
2022-04-28 21:53:31 +02:00
|
|
|
},
|
2022-02-23 08:29:37 +01:00
|
|
|
{
|
2022-05-05 00:22:14 +02:00
|
|
|
Field::Id::MimeType,
|
2022-03-19 17:56:10 +01:00
|
|
|
Field::Type::String,
|
2022-05-05 00:22:14 +02:00
|
|
|
"mime", "mime-type",
|
2022-04-30 00:17:31 +02:00
|
|
|
"Attachment MIME-type",
|
|
|
|
"mime:image/jpeg",
|
|
|
|
'y',
|
2022-05-05 00:22:14 +02:00
|
|
|
Field::Flag::BooleanTerm
|
2022-03-19 17:41:05 +01:00
|
|
|
},
|
2022-02-23 08:29:37 +01:00
|
|
|
{
|
2022-04-30 00:17:31 +02:00
|
|
|
Field::Id::Path,
|
|
|
|
Field::Type::String,
|
2022-05-05 00:22:14 +02:00
|
|
|
"path", {},
|
2022-04-30 00:17:31 +02:00
|
|
|
"File system path to message",
|
|
|
|
"path:/a/b/Maildir/cur/msg:2,S",
|
|
|
|
'l',
|
|
|
|
Field::Flag::BooleanTerm |
|
2022-05-05 00:22:14 +02:00
|
|
|
Field::Flag::Value |
|
|
|
|
Field::Flag::IncludeInSexp
|
2022-03-19 17:41:05 +01:00
|
|
|
},
|
2022-02-23 08:29:37 +01:00
|
|
|
{
|
2022-03-19 17:56:10 +01:00
|
|
|
Field::Id::Priority,
|
|
|
|
Field::Type::Integer,
|
2022-05-05 00:22:14 +02:00
|
|
|
"priority", "prio",
|
2022-02-23 08:29:37 +01:00
|
|
|
"Priority",
|
|
|
|
"prio:high",
|
|
|
|
'p',
|
2022-04-28 21:53:31 +02:00
|
|
|
Field::Flag::BooleanTerm |
|
2022-05-05 00:22:14 +02:00
|
|
|
Field::Flag::Value |
|
|
|
|
Field::Flag::IncludeInSexp
|
2022-03-19 17:41:05 +01:00
|
|
|
},
|
2022-04-30 00:17:31 +02:00
|
|
|
{
|
|
|
|
Field::Id::References,
|
|
|
|
Field::Type::StringList,
|
2022-05-12 07:50:47 +02:00
|
|
|
"references", {},
|
2022-04-30 00:17:31 +02:00
|
|
|
"References to related messages",
|
|
|
|
{},
|
|
|
|
'r',
|
2022-05-27 20:05:15 +02:00
|
|
|
Field::Flag::Value |
|
|
|
|
Field::Flag::IncludeInSexp
|
2022-04-30 00:17:31 +02:00
|
|
|
},
|
2022-02-23 08:29:37 +01:00
|
|
|
{
|
2022-03-19 17:56:10 +01:00
|
|
|
Field::Id::Size,
|
|
|
|
Field::Type::ByteSize,
|
2022-05-05 00:22:14 +02:00
|
|
|
"size", {},
|
2022-02-23 08:29:37 +01:00
|
|
|
"Message size in bytes",
|
|
|
|
"size:1M..5M",
|
|
|
|
'z',
|
2022-03-19 17:56:10 +01:00
|
|
|
Field::Flag::Value |
|
2022-05-05 00:22:14 +02:00
|
|
|
Field::Flag::Range |
|
|
|
|
Field::Flag::IncludeInSexp
|
2022-03-19 17:41:05 +01:00
|
|
|
},
|
2022-02-23 08:29:37 +01:00
|
|
|
{
|
2022-04-30 00:17:31 +02:00
|
|
|
Field::Id::Subject,
|
2022-03-19 17:56:10 +01:00
|
|
|
Field::Type::String,
|
2022-05-05 00:22:14 +02:00
|
|
|
"subject", {},
|
2022-04-30 00:17:31 +02:00
|
|
|
"Message subject",
|
|
|
|
"subject:wombat",
|
|
|
|
's',
|
|
|
|
Field::Flag::Value |
|
2023-09-17 08:59:38 +02:00
|
|
|
Field::Flag::IncludeInSexp |
|
|
|
|
Field::Flag::NormalTerm |
|
|
|
|
Field::Flag::PhrasableTerm
|
2022-04-30 00:17:31 +02:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Field::Id::Tags,
|
|
|
|
Field::Type::StringList,
|
2022-05-05 00:22:14 +02:00
|
|
|
"tags", "tag",
|
2022-04-30 00:17:31 +02:00
|
|
|
"Message tags",
|
|
|
|
"tag:projectx",
|
|
|
|
'x',
|
2022-05-05 00:22:14 +02:00
|
|
|
Field::Flag::BooleanTerm |
|
|
|
|
Field::Flag::Value |
|
|
|
|
Field::Flag::IncludeInSexp
|
2022-03-19 17:41:05 +01:00
|
|
|
},
|
2022-02-23 08:29:37 +01:00
|
|
|
{
|
2022-03-19 17:56:10 +01:00
|
|
|
Field::Id::ThreadId,
|
|
|
|
Field::Type::String,
|
2022-05-05 00:22:14 +02:00
|
|
|
"thread", {},
|
2022-02-23 08:29:37 +01:00
|
|
|
"Thread a message belongs to",
|
|
|
|
{},
|
|
|
|
'w',
|
2022-04-28 21:53:31 +02:00
|
|
|
Field::Flag::BooleanTerm |
|
|
|
|
Field::Flag::Value
|
2022-03-19 17:41:05 +01:00
|
|
|
},
|
2022-04-30 00:17:31 +02:00
|
|
|
{
|
|
|
|
Field::Id::To,
|
|
|
|
Field::Type::ContactList,
|
2022-05-05 00:22:14 +02:00
|
|
|
"to", {},
|
2022-04-30 00:17:31 +02:00
|
|
|
"Message recipient",
|
|
|
|
"to:flimflam@example.com",
|
|
|
|
't',
|
|
|
|
Field::Flag::Contact |
|
2022-05-05 00:22:14 +02:00
|
|
|
Field::Flag::Value |
|
2022-06-08 23:02:37 +02:00
|
|
|
Field::Flag::IncludeInSexp |
|
2023-09-17 08:59:38 +02:00
|
|
|
Field::Flag::NormalTerm |
|
|
|
|
Field::Flag::PhrasableTerm,
|
2022-04-30 00:17:31 +02:00
|
|
|
},
|
2022-02-23 08:29:37 +01:00
|
|
|
}};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Convenience
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the message field for the given Id.
|
|
|
|
*
|
|
|
|
* @param id of the message field
|
|
|
|
*
|
|
|
|
* @return ref of the message field.
|
|
|
|
*/
|
2022-03-19 17:56:10 +01:00
|
|
|
constexpr const Field&
|
|
|
|
field_from_id(Field::Id id)
|
2022-02-23 08:29:37 +01:00
|
|
|
{
|
2022-03-19 17:56:10 +01:00
|
|
|
return Fields.at(static_cast<size_t>(id));
|
2022-02-23 08:29:37 +01:00
|
|
|
}
|
|
|
|
|
2022-03-03 23:02:52 +01:00
|
|
|
/**
|
|
|
|
* Invoke func for each message-field
|
|
|
|
*
|
|
|
|
* @param func some callable
|
|
|
|
*/
|
|
|
|
template <typename Func>
|
2022-04-28 21:53:31 +02:00
|
|
|
constexpr void field_for_each(Func&& func) {
|
2022-03-19 17:56:10 +01:00
|
|
|
for (const auto& field: Fields)
|
2022-03-03 23:02:52 +01:00
|
|
|
func(field);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Find a message field that satisfies some predicate
|
|
|
|
*
|
|
|
|
* @param pred the predicate (a callable)
|
|
|
|
*
|
|
|
|
* @return a message-field id, or nullopt if not found.
|
|
|
|
*/
|
|
|
|
template <typename Pred>
|
2022-04-28 21:53:31 +02:00
|
|
|
constexpr Option<Field> field_find_if(Pred&& pred) {
|
2022-03-19 17:56:10 +01:00
|
|
|
for (auto&& field: Fields)
|
2022-03-03 23:02:52 +01:00
|
|
|
if (pred(field))
|
2022-03-19 17:56:10 +01:00
|
|
|
return field;
|
2022-03-26 15:19:08 +01:00
|
|
|
return Nothing;
|
2022-03-03 23:02:52 +01:00
|
|
|
}
|
|
|
|
|
2022-02-23 08:29:37 +01:00
|
|
|
/**
|
2023-06-04 13:29:57 +02:00
|
|
|
* Get the the message-field for the given name or shortcut
|
2022-02-23 08:29:37 +01:00
|
|
|
*
|
|
|
|
* @param name_or_shortcut
|
|
|
|
*
|
2023-06-04 13:29:57 +02:00
|
|
|
* @return the message-field or Nothing
|
2022-02-23 08:29:37 +01:00
|
|
|
*/
|
2022-03-03 23:02:52 +01:00
|
|
|
static inline
|
2022-03-26 15:19:08 +01:00
|
|
|
Option<Field> field_from_shortcut(char shortcut) {
|
2022-03-19 17:56:10 +01:00
|
|
|
return field_find_if([&](auto&& field){
|
2022-03-03 23:02:52 +01:00
|
|
|
return field.shortcut == shortcut;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
static inline
|
2022-03-26 15:19:08 +01:00
|
|
|
Option<Field> field_from_name(const std::string& name) {
|
2022-05-05 00:22:14 +02:00
|
|
|
switch(name.length()) {
|
|
|
|
case 0:
|
|
|
|
return Nothing;
|
|
|
|
case 1:
|
2022-03-19 17:56:10 +01:00
|
|
|
return field_from_shortcut(name[0]);
|
2022-05-05 00:22:14 +02:00
|
|
|
default:
|
2022-03-19 17:56:10 +01:00
|
|
|
return field_find_if([&](auto&& field){
|
2022-05-05 00:22:14 +02:00
|
|
|
return name == field.name || name == field.alias;
|
|
|
|
});
|
|
|
|
}
|
2022-03-03 23:02:52 +01:00
|
|
|
}
|
|
|
|
|
2023-06-04 13:29:57 +02:00
|
|
|
/**
|
|
|
|
* Return combination-fields such
|
|
|
|
* as "contact", "recip" and "" (empty)
|
|
|
|
*
|
|
|
|
* @param name combination field name
|
|
|
|
*
|
|
|
|
* @return list of matching fields
|
|
|
|
*/
|
|
|
|
using FieldsVec = std::vector<Field>;
|
|
|
|
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";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-03-03 23:02:52 +01:00
|
|
|
/**
|
2022-03-19 17:56:10 +01:00
|
|
|
* Get the Field::Id for some number, or nullopt if it does not match
|
2022-03-03 23:02:52 +01:00
|
|
|
*
|
|
|
|
* @param id an id number
|
|
|
|
*
|
2022-03-19 17:56:10 +01:00
|
|
|
* @return Field::Id or nullopt
|
2022-03-03 23:02:52 +01:00
|
|
|
*/
|
|
|
|
static inline
|
2022-03-26 15:19:08 +01:00
|
|
|
Option<Field> field_from_number(size_t id)
|
2022-03-03 23:02:52 +01:00
|
|
|
{
|
2022-03-19 17:56:10 +01:00
|
|
|
if (id >= static_cast<size_t>(Field::Id::_count_))
|
2022-03-26 15:19:08 +01:00
|
|
|
return Nothing;
|
2022-03-03 23:02:52 +01:00
|
|
|
else
|
2022-03-19 17:56:10 +01:00
|
|
|
return field_from_id(static_cast<Field::Id>(id));
|
2022-03-03 23:02:52 +01:00
|
|
|
}
|
|
|
|
|
2022-11-07 17:22:31 +01:00
|
|
|
|
2022-02-23 08:29:37 +01:00
|
|
|
} // namespace Mu
|
2022-03-19 17:56:10 +01:00
|
|
|
#endif /* MU_FIELDS_HH__ */
|