#include "colormanager.h" #include "config.h" #include "confighandlerexception.h" #include "configparser.h" #include "feedlistformaction.h" #include "filebrowserformaction.h" #include "helpformaction.h" #include "itemlistformaction.h" #include "itemviewformaction.h" #include "logger.h" #include "matcherexception.h" #include "pbview.h" #include "selectformaction.h" #include "strprintf.h" #include "urlviewformaction.h" #include "utils.h" using namespace podboat; namespace newsboat { ColorManager::ColorManager() { } ColorManager::~ColorManager() {} void ColorManager::register_commands(ConfigParser& cfgparser) { cfgparser.register_handler("color", *this); } void ColorManager::handle_action(const std::string& action, const std::vector& params) { LOG(Level::DEBUG, "ColorManager::handle_action(%s,...) was called", action); if (action == "color") { if (params.size() < 3) { throw ConfigHandlerException(ActionHandlerStatus::TOO_FEW_PARAMS); } /* * the command syntax is: * color [ ...] */ const std::string element = params[0]; const std::string fgcolor = params[1]; const std::string bgcolor = params[2]; if (!utils::is_valid_color(fgcolor)) { throw ConfigHandlerException(strprintf::fmt( _("`%s' is not a valid color"), fgcolor)); } if (!utils::is_valid_color(bgcolor)) { throw ConfigHandlerException(strprintf::fmt( _("`%s' is not a valid color"), bgcolor)); } const std::vector attribs( std::next(params.cbegin(), 3), params.cend()); for (const auto& attr : attribs) { if (!utils::is_valid_attribute(attr)) { throw ConfigHandlerException(strprintf::fmt( _("`%s' is not a valid attribute"), attr)); } } /* we only allow certain elements to be configured, also to * indicate the user possible mis-spellings */ const std::vector supported_elements({ "listnormal", "listfocus", "listnormal_unread", "listfocus_unread", "info", "background", "article", "end-of-text-marker", "title", "hint-key", "hint-keys-delimiter", "hint-separator", "hint-description" }); const auto element_is_supported = std::find(supported_elements.cbegin(), supported_elements.cend(), element) != supported_elements.cend(); if (element_is_supported) { element_styles[element] = {fgcolor, bgcolor, attribs}; } else { throw ConfigHandlerException(strprintf::fmt( _("`%s' is not a valid configuration element"), element)); } } else { throw ConfigHandlerException(ActionHandlerStatus::INVALID_COMMAND); } } void ColorManager::dump_config(std::vector& config_output) const { for (const auto& element_style : element_styles) { const std::string& element = element_style.first; const TextStyle& style = element_style.second; std::string configline = strprintf::fmt("color %s %s %s", element, style.fg_color, style.bg_color); for (const auto& attrib : style.attributes) { configline.append(" "); configline.append(attrib); } config_output.push_back(configline); } } std::string format_style(const TextStyle& style) { std::string result; if (style.fg_color != "default") { result.append("fg="); result.append(style.fg_color); } if (style.bg_color != "default") { if (!result.empty()) { result.append(","); } result.append("bg="); result.append(style.bg_color); } for (const auto& attr : style.attributes) { if (!result.empty()) { result.append(","); } result.append("attr="); result.append(attr); } return result; } void ColorManager::emit_fallback_from_to(const std::string& from_element, const std::string& to_element, const std::function& stfl_value_setter) const { const auto from_style = element_styles.find(from_element); const auto to_style = element_styles.find(to_element); if (from_style == element_styles.cend() && to_style != element_styles.cend()) { const auto style = format_style(to_style->second); LOG(Level::DEBUG, "ColorManager::apply_colors: %s inherited from %s %s\n", from_element, to_element, style); stfl_value_setter(from_element, style); } } void ColorManager::apply_colors( std::function stfl_value_setter) const { for (const auto& element_style : element_styles) { const std::string& element = element_style.first; const TextStyle& style = element_style.second; const auto colorattr = format_style(style); LOG(Level::DEBUG, "ColorManager::apply_colors: %s %s\n", element, colorattr); stfl_value_setter(element, colorattr); if (element == "article") { std::string bold = colorattr; std::string underline = colorattr; if (!bold.empty()) { bold.append(","); } if (!underline.empty()) { underline.append(","); } bold.append("attr=bold"); underline.append("attr=underline"); // STFL will just ignore those in forms which don't have the // `color_bold` and `color_underline` variables. LOG(Level::DEBUG, "ColorManager::apply_colors: color_bold %s\n", bold); stfl_value_setter("color_bold", bold); LOG(Level::DEBUG, "ColorManager::apply_colors: color_underline %s\n", underline); stfl_value_setter("color_underline", underline); } } emit_fallback_from_to("title", "info", stfl_value_setter); emit_fallback_from_to("hint-key", "info", stfl_value_setter); emit_fallback_from_to("hint-keys-delimiter", "info", stfl_value_setter); emit_fallback_from_to("hint-separator", "info", stfl_value_setter); emit_fallback_from_to("hint-description", "info", stfl_value_setter); } } // namespace newsboat