<commit_before>#include "itemviewformaction.h"

#include <algorithm>
#include <cstring>
#include <sstream>

#include "config.h"
#include "exceptions.h"
#include "formatstring.h"
#include "logger.h"
#include "strprintf.h"
#include "textformatter.h"
#include "utils.h"
#include "view.h"

namespace newsboat {

ItemViewFormAction::ItemViewFormAction(View* vv,
	std::shared_ptr<ItemListFormAction> il,
	std::string formstr,
	Cache* cc,
	ConfigContainer* cfg)
	: FormAction(vv, formstr, cfg)
	, show_source(false)
	, quit(false)
	, rxman(0)
	, num_lines(0)
	, itemlist(il)
	, in_search(false)
	, rsscache(cc)
	, cfg(cfg)
{
	valid_cmds.push_back("save");
	std::sort(valid_cmds.begin(), valid_cmds.end());
}

ItemViewFormAction::~ItemViewFormAction() {}

void ItemViewFormAction::init()
{
	f->set("msg", "");
	do_redraw = true;
	quit = false;
	links.clear();
	num_lines = 0;
	if (!cfg->get_configvalue_as_bool("display-article-progress")) {
		f->set("percentwidth", "0");
	} else {
		f->set("percentwidth",
			std::to_string(Utils::max(6,
				Utils::max(strlen(_("Top")),
					strlen(_("Bottom"))))));
		update_percent();
	}
	set_keymap_hints();
}

void ItemViewFormAction::prepare()
{
	/*
	 * whenever necessary, the item view is regenerated. This is done
	 * by putting together the feed name, title, link, author, optional
	 * flags and podcast download URL (enclosures) and then render the
	 * HTML. The links extracted by the renderer are then appended, too.
	 */
	if (do_redraw) {
		{
			ScopeMeasure("itemview::prepare: rendering");
			f->run(-3); // XXX HACK: render once so that we get a
				    // proper widget width
		}

		std::shared_ptr<RssItem> item = feed->get_item_by_guid(guid);
		TextFormatter textfmt;

		std::shared_ptr<RssFeed> feedptr = item->get_feedptr();

		std::string feedtitle, feedheader;
		if (feedptr.get() != nullptr) {
			if (feedptr->title().length() > 0) {
				feedtitle = feedptr->title();
				Utils::remove_soft_hyphens(feedtitle);
			} else if (feedptr->link().length() > 0) {
				feedtitle = feedptr->link();
			} else if (feedptr->rssurl().length() > 0) {
				feedtitle = feedptr->rssurl();
			}
		}
		if (feedtitle.length() > 0) {
			feedheader =
				StrPrintf::fmt("%s%s", _("Feed: "), feedtitle);
			textfmt.add_line(LineType::wrappable, feedheader);
		}

		if (item->title().length() > 0) {
			std::string title = StrPrintf::fmt(
				"%s%s", _("Title: "), item->title());
			Utils::remove_soft_hyphens(title);
			textfmt.add_line(LineType::wrappable, title);
		}

		if (item->author().length() > 0) {
			std::string author = StrPrintf::fmt(
				"%s%s", _("Author: "), item->author());
			Utils::remove_soft_hyphens(author);
			textfmt.add_line(LineType::wrappable, author);
		}

		if (item->link().length() > 0) {
			std::string link = StrPrintf::fmt("%s%s",
				_("Link: "),
				Utils::censor_url(item->link()));
			textfmt.add_line(LineType::softwrappable, link);
		}

		std::string date =
			StrPrintf::fmt("%s%s", _("Date: "), item->pubDate());
		textfmt.add_line(LineType::wrappable, date);

		if (item->flags().length() > 0) {
			std::string flags = StrPrintf::fmt(
				"%s%s", _("Flags: "), item->flags());
			textfmt.add_line(LineType::wrappable, flags);
		}

		if (item->enclosure_url().length() > 0) {
			std::string enc_url = StrPrintf::fmt("%s%s",
				_("Podcast Download URL: "),
				Utils::censor_url(item->enclosure_url()));
			if (item->enclosure_type() != "") {
				enc_url.append(StrPrintf::fmt(" (%s%s)",
					_("type: "),
					item->enclosure_type()));
			}
			textfmt.add_line(LineType::softwrappable, enc_url);
		}

		textfmt.add_line(LineType::wrappable, std::string());

		unsigned int unread_item_count = feed->unread_item_count();
		// we need to subtract because the current item isn't yet marked
		// as read
		if (item->unread())
			unread_item_count--;
		set_head(item->title(),
			feedtitle,
			unread_item_count,
			feed->total_item_count());

		std::vector<std::pair<LineType, std::string>> lines;
		if (show_source) {
			render_source(lines,
				Utils::quote_for_stfl(item->description()));
		} else {
			std::string baseurl = item->get_base() != ""
				? item->get_base()
				: item->feedurl();
			lines = render_html(
				item->description(), links, baseurl);
		}

		textfmt.add_lines(lines);

		std::string widthstr = f->get("article:w");
		unsigned int window_width = Utils::to_u(widthstr, 0);

		unsigned int textwidth =
			cfg->get_configvalue_as_int("text-width");
		if (textwidth == 0 || textwidth > window_width) {
			textwidth = window_width;
			if (textwidth - 5 > 0) {
				textwidth -= 5;
			}
		}

		std::string formatted_text;
		std::tie(formatted_text, num_lines) =
			textfmt.format_text_to_list(
				rxman, "article", textwidth, window_width);
		f->modify("article", "replace_inner", formatted_text);
		f->set("articleoffset", "0");

		if (in_search) {
			rxman->remove_last_regex("article");
			in_search = false;
		}

		do_redraw = false;
	}
}

void ItemViewFormAction::process_operation(Operation op,
	bool automatic,
	std::vector<std::string>* args)
{
	std::shared_ptr<RssItem> item = feed->get_item_by_guid(guid);<commit_msg>Prettify itemview_formaction::prepare()<commit_after>#include "itemviewformaction.h"

#include <algorithm>
#include <cstring>
#include <sstream>

#include "config.h"
#include "exceptions.h"
#include "formatstring.h"
#include "logger.h"
#include "strprintf.h"
#include "textformatter.h"
#include "utils.h"
#include "view.h"

namespace newsboat {

ItemViewFormAction::ItemViewFormAction(View* vv,
	std::shared_ptr<ItemListFormAction> il,
	std::string formstr,
	Cache* cc,
	ConfigContainer* cfg)
	: FormAction(vv, formstr, cfg)
	, show_source(false)
	, quit(false)
	, rxman(0)
	, num_lines(0)
	, itemlist(il)
	, in_search(false)
	, rsscache(cc)
	, cfg(cfg)
{
	valid_cmds.push_back("save");
	std::sort(valid_cmds.begin(), valid_cmds.end());
}

ItemViewFormAction::~ItemViewFormAction() {}

void ItemViewFormAction::init()
{
	f->set("msg", "");
	do_redraw = true;
	quit = false;
	links.clear();
	num_lines = 0;
	if (!cfg->get_configvalue_as_bool("display-article-progress")) {
		f->set("percentwidth", "0");
	} else {
		f->set("percentwidth",
			std::to_string(Utils::max(6,
				Utils::max(strlen(_("Top")),
					strlen(_("Bottom"))))));
		update_percent();
	}
	set_keymap_hints();
}

void ItemViewFormAction::prepare()
{
	/*
	 * whenever necessary, the item view is regenerated. This is done
	 * by putting together the feed name, title, link, author, optional
	 * flags and podcast download URL (enclosures) and then render the
	 * HTML. The links extracted by the renderer are then appended, too.
	 */
	if (do_redraw) {
		{
			ScopeMeasure("itemview::prepare: rendering");
			f->run(-3); // XXX HACK: render once so that we get a
				    // proper widget width
		}

		std::shared_ptr<RssItem> item = feed->get_item_by_guid(guid);
		TextFormatter textfmt;

		std::shared_ptr<RssFeed> feedptr = item->get_feedptr();

		std::string feedtitle;
		if (feedptr) {
			if (!feedptr->title().empty()) {
				feedtitle = feedptr->title();
				Utils::remove_soft_hyphens(feedtitle);
			} else if (!feedptr->link().empty()) {
				feedtitle = feedptr->link();
			} else if (!feedptr->rssurl().empty()) {
				feedtitle = feedptr->rssurl();
			}
		}
		if (!feedtitle.empty()) {
			const auto feedheader =
				StrPrintf::fmt("%s%s", _("Feed: "), feedtitle);
			textfmt.add_line(LineType::wrappable, feedheader);
		}

		if (!item->title().empty()) {
			auto title = StrPrintf::fmt(
				"%s%s", _("Title: "), item->title());
			Utils::remove_soft_hyphens(title);
			textfmt.add_line(LineType::wrappable, title);
		}

		if (!item->author().empty()) {
			auto author = StrPrintf::fmt(
				"%s%s", _("Author: "), item->author());
			Utils::remove_soft_hyphens(author);
			textfmt.add_line(LineType::wrappable, author);
		}

		if (!item->link().empty()) {
			const auto link = StrPrintf::fmt("%s%s",
				_("Link: "),
				Utils::censor_url(item->link()));
			textfmt.add_line(LineType::softwrappable, link);
		}

		const auto date =
			StrPrintf::fmt("%s%s", _("Date: "), item->pubDate());
		textfmt.add_line(LineType::wrappable, date);

		if (!item->flags().empty()) {
			const auto flags = StrPrintf::fmt(
				"%s%s", _("Flags: "), item->flags());
			textfmt.add_line(LineType::wrappable, flags);
		}

		if (!item->enclosure_url().empty()) {
			std::string enc_url = StrPrintf::fmt("%s%s",
				_("Podcast Download URL: "),
				Utils::censor_url(item->enclosure_url()));
			if (!item->enclosure_type().empty()) {
				enc_url.append(StrPrintf::fmt(" (%s%s)",
					_("type: "),
					item->enclosure_type()));
			}
			textfmt.add_line(LineType::softwrappable, enc_url);
		}

		textfmt.add_line(LineType::wrappable, std::string());

		unsigned int unread_item_count = feed->unread_item_count();
		// we need to subtract because the current item isn't yet marked
		// as read
		if (item->unread()) {
			unread_item_count--;
		}
		set_head(item->title(),
			feedtitle,
			unread_item_count,
			feed->total_item_count());

		std::vector<std::pair<LineType, std::string>> lines;
		if (show_source) {
			render_source(lines,
				Utils::quote_for_stfl(item->description()));
		} else {
			std::string baseurl;
			if (!item->get_base().empty()) {
				baseurl = item->get_base();
			} else {
				baseurl = item->feedurl();
			}

			lines = render_html(item->description(), links, baseurl);
		}

		textfmt.add_lines(lines);

		std::string widthstr = f->get("article:w");
		const unsigned int window_width = Utils::to_u(widthstr, 0);

		unsigned int textwidth =
			cfg->get_configvalue_as_int("text-width");
		if (textwidth == 0 || textwidth > window_width) {
			textwidth = window_width;
			if (textwidth - 5 > 0) {
				textwidth -= 5;
			}
		}

		std::string formatted_text;
		std::tie(formatted_text, num_lines) =
			textfmt.format_text_to_list(
				rxman, "article", textwidth, window_width);
		f->modify("article", "replace_inner", formatted_text);
		f->set("articleoffset", "0");

		if (in_search) {
			rxman->remove_last_regex("article");
			in_search = false;
		}

		do_redraw = false;
	}
}

void ItemViewFormAction::process_operation(Operation op,
	bool automatic,
	std::vector<std::string>* args)
{
	std::shared_ptr<RssItem> item = feed->get_item_by_guid(guid);
{'fraction_non_alphanumeric': 0.17902439024390243, 'fraction_numerical': 0.003219512195121951, 'mean_word_length': 4.435312831389184, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 118, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5870346', 'n_tokens_mistral': 4153, 'n_tokens_neox': 3710, 'n_words': 686}