Support attaching format information to selected color variables

This commit is contained in:
Andrzej Rybczak
2016-12-22 16:31:41 +01:00
parent 9c13827b62
commit a488c2d89d
22 changed files with 492 additions and 175 deletions

View File

@@ -0,0 +1,83 @@
/***************************************************************************
* Copyright (C) 2008-2016 by Andrzej Rybczak *
* electricityispower@gmail.com *
* *
* 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 2 of the License, 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 St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include "formatted_color.h"
namespace {
void verifyFormats(const NC::FormattedColor::Formats &formats)
{
for (auto &fmt : formats)
{
if (fmt == NC::Format::NoBold
|| fmt == NC::Format::NoUnderline
|| fmt == NC::Format::NoReverse
|| fmt == NC::Format::NoAltCharset)
throw std::logic_error("FormattedColor can't hold disabling formats");
}
}
}
NC::FormattedColor::FormattedColor(Color color_, Formats formats_)
{
if (color_ == NC::Color::End)
throw std::logic_error("FormattedColor can't hold Color::End");
m_color = std::move(color_);
verifyFormats(formats_);
m_formats = std::move(formats_);
}
std::istream &NC::operator>>(std::istream &is, NC::FormattedColor &fc)
{
NC::Color c;
is >> c;
if (!is.eof() && is.peek() == ':')
{
is.get();
NC::FormattedColor::Formats formats;
while (!is.eof() && isalpha(is.peek()))
{
char flag = is.get();
switch (flag)
{
case 'b':
formats.push_back(NC::Format::Bold);
break;
case 'u':
formats.push_back(NC::Format::Underline);
break;
case 'r':
formats.push_back(NC::Format::Reverse);
break;
case 'a':
formats.push_back(NC::Format::AltCharset);
break;
default:
is.setstate(std::ios::failbit);
break;
}
}
fc = NC::FormattedColor(c, std::move(formats));
}
else
fc = NC::FormattedColor(c, {});
return is;
}

View File

@@ -0,0 +1,81 @@
/***************************************************************************
* Copyright (C) 2008-2016 by Andrzej Rybczak *
* electricityispower@gmail.com *
* *
* 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 2 of the License, 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 St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#ifndef NCMPCPP_FORMATTED_COLOR_H
#define NCMPCPP_FORMATTED_COLOR_H
#include <boost/optional.hpp>
#include <boost/range/adaptor/reversed.hpp>
#include "window.h"
namespace NC {
struct FormattedColor
{
struct End
{
End(const FormattedColor &fc)
: m_fc(fc)
{ }
const FormattedColor &base() const { return m_fc; }
private:
const FormattedColor &m_fc;
};
typedef std::vector<Format> Formats;
FormattedColor() { }
FormattedColor(Color color_, Formats formats_);
const Color &color() const { return m_color; }
const Formats &formats() const { return m_formats; }
private:
Color m_color;
Formats m_formats;
};
std::istream &operator>>(std::istream &is, FormattedColor &fc);
template <typename OutputStreamT>
OutputStreamT &operator<<(OutputStreamT &os, const FormattedColor &fc)
{
os << fc.color();
for (auto &fmt : fc.formats())
os << fmt;
return os;
}
template <typename OutputStreamT>
OutputStreamT &operator<<(OutputStreamT &os, const FormattedColor::End &rfc)
{
if (rfc.base().color() != Color::Default)
os << Color::End;
for (auto &fmt : boost::adaptors::reverse(rfc.base().formats()))
os << reverseFormat(fmt);
return os;
}
}
#endif // NCMPCPP_FORMATTED_COLOR_H

View File

@@ -259,36 +259,67 @@ std::istream &operator>>(std::istream &is, Color &c)
}
return result;
};
std::string sc;
is >> sc;
auto get_color = [](std::istream &is_) {
std::string result;
while (!is_.eof() && isalnum(is_.peek()))
result.push_back(is_.get());
return result;
};
std::string sc = get_color(is);
if (sc == "default")
c = Color::Default;
c = Color::Default;
else if (sc == "end")
c = Color::End;
else
{
short value = get_single_color(sc, false);
if (value != -1)
c = Color(value, NC::Color::transparent);
else
short fg = get_single_color(sc, false);
if (fg == -1)
is.setstate(std::ios::failbit);
// Check if there is background color
else if (!is.eof() && is.peek() == '_')
{
size_t underscore = sc.find('_');
if (underscore != std::string::npos)
{
short fg = get_single_color(sc.substr(0, underscore), false);
short bg = get_single_color(sc.substr(underscore+1), true);
if (fg != -1 && bg != -1)
c = Color(fg, bg);
else
is.setstate(std::ios::failbit);
}
else
is.get();
sc = get_color(is);
short bg = get_single_color(sc, true);
if (bg == -1)
is.setstate(std::ios::failbit);
else
c = Color(fg, bg);
}
else
c = Color(fg, NC::Color::transparent);
}
return is;
}
NC::Format reverseFormat(NC::Format fmt)
{
switch (fmt)
{
case NC::Format::Bold:
return NC::Format::NoBold;
case NC::Format::NoBold:
return NC::Format::Bold;
case NC::Format::Underline:
return NC::Format::NoUnderline;
case NC::Format::NoUnderline:
return NC::Format::Underline;
case NC::Format::Reverse:
return NC::Format::NoReverse;
case NC::Format::NoReverse:
return NC::Format::Reverse;
case NC::Format::AltCharset:
return NC::Format::NoAltCharset;
case NC::Format::NoAltCharset:
return NC::Format::AltCharset;
}
// Unreachable, silence GCC.
return fmt;
}
namespace Mouse {
namespace {

View File

@@ -149,7 +149,7 @@ struct Color
static const short transparent;
static const short previous;
Color() : m_impl(0, transparent, true, false) { }
Color() : m_impl(0, 0, true, false) { }
Color(short foreground_value, short background_value,
bool is_default = false, bool is_end = false)
: m_impl(foreground_value, background_value, is_default, is_end)
@@ -201,6 +201,8 @@ enum class Format {
AltCharset, NoAltCharset
};
NC::Format reverseFormat(NC::Format fmt);
/// This indicates how much the window has to be scrolled
enum class Scroll { Up, Down, PageUp, PageDown, Home, End };