format: add flags to refine parsing and printing of the AST
This commit is contained in:
70
src/format.h
70
src/format.h
@@ -31,6 +31,15 @@
|
||||
|
||||
namespace Format {
|
||||
|
||||
namespace Flags {
|
||||
const unsigned None = 0;
|
||||
const unsigned Color = 1;
|
||||
const unsigned Format = 2;
|
||||
const unsigned OutputSwitch = 4;
|
||||
const unsigned Tag = 8;
|
||||
const unsigned All = Color | Format | OutputSwitch | Tag;
|
||||
}
|
||||
|
||||
enum class ListType { All, Any, AST };
|
||||
|
||||
template <ListType, typename> struct List;
|
||||
@@ -38,7 +47,7 @@ template <typename CharT> using All = List<ListType::All, CharT>;
|
||||
template <typename CharT> using Any = List<ListType::Any, CharT>;
|
||||
template <typename CharT> using AST = List<ListType::AST, CharT>;
|
||||
|
||||
struct AlignRight { };
|
||||
struct OutputSwitch { };
|
||||
|
||||
struct SongTag
|
||||
{
|
||||
@@ -59,7 +68,7 @@ using Expression = boost::variant<
|
||||
std::basic_string<CharT>,
|
||||
NC::Color,
|
||||
NC::Format,
|
||||
AlignRight,
|
||||
OutputSwitch,
|
||||
SongTag,
|
||||
boost::recursive_wrapper<Any<CharT>>,
|
||||
boost::recursive_wrapper<All<CharT>>
|
||||
@@ -82,17 +91,18 @@ private:
|
||||
Base m_base;
|
||||
};
|
||||
|
||||
template <typename CharT, typename OutputT, typename OutputAfterAlignmentT = OutputT>
|
||||
template <typename CharT, typename OutputT, typename SecondOutputT = OutputT>
|
||||
struct Printer: boost::static_visitor<bool>
|
||||
{
|
||||
typedef std::basic_string<CharT> StringT;
|
||||
|
||||
Printer(OutputT &os, const MPD::Song *song, OutputAfterAlignmentT *os_after_alignment)
|
||||
Printer(OutputT &os, const MPD::Song *song, SecondOutputT *second_os, const unsigned flags)
|
||||
: m_output(os)
|
||||
, m_song(song)
|
||||
, m_after_alignment(false)
|
||||
, m_output_after_alignment(os_after_alignment)
|
||||
, m_output_switched(false)
|
||||
, m_second_os(second_os)
|
||||
, m_no_output(0)
|
||||
, m_flags(flags)
|
||||
{ }
|
||||
|
||||
bool operator()(const StringT &s)
|
||||
@@ -103,27 +113,29 @@ struct Printer: boost::static_visitor<bool>
|
||||
|
||||
bool operator()(const NC::Color &c)
|
||||
{
|
||||
output(c);
|
||||
if (m_flags & Flags::Color)
|
||||
output(c);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator()(NC::Format fmt)
|
||||
{
|
||||
output(fmt);
|
||||
if (m_flags & Flags::Format)
|
||||
output(fmt);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator()(AlignRight)
|
||||
bool operator()(OutputSwitch)
|
||||
{
|
||||
if (!m_no_output)
|
||||
m_after_alignment = true;
|
||||
m_output_switched = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator()(const SongTag &st)
|
||||
{
|
||||
StringT tags;
|
||||
if (m_song != nullptr)
|
||||
if (m_flags & Flags::Tag && m_song != nullptr)
|
||||
{
|
||||
tags = convertString<CharT, char>::apply(
|
||||
m_song->getTags(st.function())
|
||||
@@ -198,11 +210,13 @@ private:
|
||||
result += s;
|
||||
}
|
||||
};
|
||||
// when writing to a string, ignore all properties
|
||||
// when writing to a string, we should ignore all other
|
||||
// properties. if this code is reached, throw an exception.
|
||||
template <typename ValueT, typename SomeCharT>
|
||||
struct output_<ValueT, std::basic_string<SomeCharT>>
|
||||
{
|
||||
static void exec(std::basic_string<CharT> &, const ValueT &) { }
|
||||
struct output_<ValueT, std::basic_string<SomeCharT>> {
|
||||
static void exec(std::basic_string<CharT> &, const ValueT &) {
|
||||
throw std::logic_error("non-string property can't be appended to the string");
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ValueT>
|
||||
@@ -210,8 +224,8 @@ private:
|
||||
{
|
||||
if (!m_no_output)
|
||||
{
|
||||
if (m_after_alignment && m_output_after_alignment != nullptr)
|
||||
output_<ValueT, OutputAfterAlignmentT>::exec(*m_output_after_alignment, value);
|
||||
if (m_output_switched && m_second_os != nullptr)
|
||||
output_<ValueT, SecondOutputT>::exec(*m_second_os, value);
|
||||
else
|
||||
output_<ValueT, OutputT>::exec(m_output, value);
|
||||
}
|
||||
@@ -220,10 +234,11 @@ private:
|
||||
OutputT &m_output;
|
||||
const MPD::Song *m_song;
|
||||
|
||||
bool m_after_alignment;
|
||||
OutputAfterAlignmentT *m_output_after_alignment;
|
||||
bool m_output_switched;
|
||||
SecondOutputT *m_second_os;
|
||||
|
||||
unsigned m_no_output;
|
||||
const unsigned m_flags;
|
||||
};
|
||||
|
||||
template <typename CharT, typename VisitorT>
|
||||
@@ -234,17 +249,18 @@ void visit(VisitorT &visitor, const AST<CharT> &ast)
|
||||
}
|
||||
|
||||
template <typename CharT, typename ItemT>
|
||||
void print(const AST<CharT> &ast, NC::Menu<ItemT> &menu,
|
||||
const MPD::Song *song, NC::BasicBuffer<CharT> *buffer)
|
||||
void print(const AST<CharT> &ast, NC::Menu<ItemT> &menu, const MPD::Song *song,
|
||||
NC::BasicBuffer<CharT> *buffer, const unsigned flags = Flags::All)
|
||||
{
|
||||
Printer<CharT, NC::Menu<ItemT>, NC::Buffer> printer(menu, song, buffer);
|
||||
Printer<CharT, NC::Menu<ItemT>, NC::Buffer> printer(menu, song, buffer, flags);
|
||||
visit(printer, ast);
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
void print(const AST<CharT> &ast, NC::BasicBuffer<CharT> &buffer, const MPD::Song *song)
|
||||
void print(const AST<CharT> &ast, NC::BasicBuffer<CharT> &buffer,
|
||||
const MPD::Song *song, const unsigned flags = Flags::All)
|
||||
{
|
||||
Printer<CharT, NC::BasicBuffer<CharT>> printer(buffer, song, &buffer);
|
||||
Printer<CharT, NC::BasicBuffer<CharT>> printer(buffer, song, &buffer, flags);
|
||||
visit(printer, ast);
|
||||
}
|
||||
|
||||
@@ -252,13 +268,13 @@ template <typename CharT>
|
||||
std::basic_string<CharT> stringify(const AST<CharT> &ast, const MPD::Song *song)
|
||||
{
|
||||
std::basic_string<CharT> result;
|
||||
Printer<CharT, std::basic_string<CharT>> printer(result, song, &result);
|
||||
Printer<CharT, std::basic_string<CharT>> printer(result, song, &result, Flags::Tag);
|
||||
visit(printer, ast);
|
||||
return result;
|
||||
}
|
||||
|
||||
AST<char> parse(const std::string &s);
|
||||
AST<wchar_t> wparse(const std::wstring &ws);
|
||||
AST<char> parse(const std::string &s, const unsigned flags = Flags::All);
|
||||
AST<wchar_t> parse(const std::wstring &ws, const unsigned flags = Flags::All);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user