Mercurial > irccd
changeset 675:168ea30142d9
Irccd: add color support in irccd output, closes #792 @1h
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 11 Apr 2018 22:21:21 +0200 |
parents | 5d0ed41be10c |
children | 747665d5062b |
files | doc/src/irccd.conf.md doc/src/irccd.md libcommon/irccd/string_util.cpp libcommon/irccd/string_util.hpp libirccd/irccd/daemon/irccd.cpp |
diffstat | 5 files changed, 123 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- a/doc/src/irccd.conf.md Wed Apr 11 21:01:10 2018 +0200 +++ b/doc/src/irccd.conf.md Wed Apr 11 22:21:21 2018 +0200 @@ -127,7 +127,7 @@ Only one keyword is defined, `message` which contains the message that irccd wants to output. -**Note:** colors and attributes are not supported. +**Note:** colors and attributes are not supported on Windows. The available options:
--- a/doc/src/irccd.md Wed Apr 11 21:01:10 2018 +0200 +++ b/doc/src/irccd.md Wed Apr 11 22:21:21 2018 +0200 @@ -96,7 +96,7 @@ If supported, you can use environment variables like **${HOME}**. Please note that braces are mandatory. -## Attributes +## IRC attributes The attribute format is composed of three parts, foreground, background and modifiers, each separated by a comma. @@ -135,6 +135,34 @@ - underline2, - reverse. +## Shell attributes + +Like IRC attributes, it's possible to specify colors and attributes in some +places such as logger configuration. + +Warning: colors are not supported on all platforms. + +### Available colors + + - black, + - red, + - green, + - orange, + - blue, + - purple, + - cyan, + - white, + - default. + +### Available attributes + + - bold, + - dim, + - underline, + - blink, + - reverse, + - hidden. + ## Keywords Keywords are arbitrary names that are replaced depending on the context. They
--- a/libcommon/irccd/string_util.cpp Wed Apr 11 21:01:10 2018 +0200 +++ b/libcommon/irccd/string_util.cpp Wed Apr 11 22:21:21 2018 +0200 @@ -38,7 +38,7 @@ namespace { -const std::unordered_map<std::string, int> colors{ +const std::unordered_map<std::string, int> irc_colors{ { "white", 0 }, { "black", 1 }, { "blue", 2 }, @@ -57,7 +57,7 @@ { "lightgrey", 15 } }; -const std::unordered_map<std::string, char> attributes{ +const std::unordered_map<std::string, char> irc_attributes{ { "bold", '\x02' }, { "italic", '\x09' }, { "strike", '\x13' }, @@ -67,6 +67,27 @@ { "reverse", '\x16' } }; +const std::unordered_map<std::string, unsigned> shell_colors{ + { "black", 30 }, + { "red", 31 }, + { "green", 32 }, + { "orange", 33 }, + { "blue", 34 }, + { "purple", 35 }, + { "cyan", 36 }, + { "white", 37 }, + { "default", 39 }, +}; + +const std::unordered_map<std::string, unsigned> shell_attributes{ + { "bold", 1 }, + { "dim", 2 }, + { "underline", 4 }, + { "blink", 5 }, + { "reverse", 7 }, + { "hidden", 8 } +}; + inline bool is_reserved(char token) noexcept { return token == '#' || token == '@' || token == '$' || token == '!'; @@ -113,14 +134,15 @@ return ""; } -std::string subst_attrs(const std::string& content) +std::string subst_irc_attrs(const std::string& content) { - std::stringstream oss; - std::vector<std::string> list = split(content, ","); + auto list = split(content, ","); // @{} means reset. if (list.empty()) - return std::string(1, attributes.at("reset")); + return std::string(1, irc_attributes.at("reset")); + + std::ostringstream oss; // Remove useless spaces. std::transform(list.begin(), list.end(), list.begin(), strip); @@ -136,19 +158,19 @@ oss << '\x03'; // Foreground. - auto it = colors.find(foreground); - if (it != colors.end()) + auto it = irc_colors.find(foreground); + if (it != irc_colors.end()) oss << it->second; // Background. - if (list.size() >= 2 && (it = colors.find(list[1])) != colors.end()) + if (list.size() >= 2 && (it = irc_colors.find(list[1])) != irc_colors.end()) oss << "," << it->second; // Attributes. for (std::size_t i = 2; i < list.size(); ++i) { - auto attribute = attributes.find(list[i]); + auto attribute = irc_attributes.find(list[i]); - if (attribute != attributes.end()) + if (attribute != irc_attributes.end()) oss << attribute->second; } } @@ -156,6 +178,60 @@ return oss.str(); } +std::string subst_shell_attrs(const std::string& content) +{ +#if !defined(IRCCD_SYSTEM_WINDOWS) + auto list = split(content, ","); + + if (list.empty()) + return "[0m"; + if (list.size() > 3) + return ""; + + std::vector<std::string> seq; + + /* + * Shell sequence looks like this: + * + * [attributes;foreground;backgroundm + */ + if (list.size() >= 3) { + const auto it = shell_attributes.find(list[2]); + + if (it != shell_attributes.end()) + seq.push_back(std::to_string(it->second)); + else + return ""; + } + if (list.size() >= 1) { + const auto it = shell_colors.find(list[0]); + + if (it != shell_colors.end()) + seq.push_back(std::to_string(it->second)); + else + return ""; + } + if (list.size() >= 2) { + const auto it = shell_colors.find(list[1]); + + if (it != shell_colors.end()) + seq.push_back(std::to_string(it->second + 10)); + else + return ""; + } + + std::ostringstream oss; + + oss << "["; + oss << string_util::join(seq, ';'); + oss << "m"; + + return oss.str(); +#else + return ""; +#endif +} + std::string subst_shell(const std::string& command) { #if defined(HAVE_POPEN) @@ -218,7 +294,9 @@ break; case '@': if ((params.flags & subst_flags::irc_attrs) == subst_flags::irc_attrs) - value = subst_attrs(content); + value = subst_irc_attrs(content); + else if ((params.flags & subst_flags::shell_attrs) == subst_flags::shell_attrs) + value = subst_shell_attrs(content); break; case '!': if ((params.flags & subst_flags::shell) == subst_flags::shell)
--- a/libcommon/irccd/string_util.hpp Wed Apr 11 21:01:10 2018 +0200 +++ b/libcommon/irccd/string_util.hpp Wed Apr 11 22:21:21 2018 +0200 @@ -52,7 +52,8 @@ keywords = (1 << 1), //!< keywords env = (1 << 2), //!< environment variables shell = (1 << 3), //!< command line command - irc_attrs = (1 << 4) //!< IRC escape codes + irc_attrs = (1 << 4), //!< IRC escape codes + shell_attrs = (1 << 5) //!< shell attributes }; /**
--- a/libirccd/irccd/daemon/irccd.cpp Wed Apr 11 21:01:10 2018 +0200 +++ b/libirccd/irccd/daemon/irccd.cpp Wed Apr 11 22:21:21 2018 +0200 @@ -45,6 +45,7 @@ string_util::subst params; params.flags &= ~(string_util::subst_flags::irc_attrs); + params.flags |= string_util::subst_flags::shell_attrs; params.keywords.emplace("message", std::move(input)); return string_util::format(tmpl, params);