<commit_before>#include "formaction.h"

#include <cassert>
#include <cinttypes>

#include "config.h"
#include "configexception.h"
#include "logger.h"
#include "matcherexception.h"
#include "strprintf.h"
#include "utils.h"
#include "view.h"

namespace newsboat {

History FormAction::searchhistory;
History FormAction::cmdlinehistory;

FormAction::FormAction(View* vv, std::string formstr, ConfigContainer* cfg)
	: v(vv)
	, cfg(cfg)
	, f(new Stfl::Form(formstr))
	, do_redraw(true)
	, finish_operation(OP_NIL)
	, qna_history(nullptr)
{
	if (v) {
		if (cfg->get_configvalue_as_bool("show-keymap-hint") == false) {
			f->set("showhint", "0");
		}
		if (cfg->get_configvalue_as_bool("show-title-bar") == false) {
			f->set("showtitle", "0");
		}
		if (cfg->get_configvalue_as_bool("swap-title-and-hints") ==
			true) {
			std::string hints = f->dump("hints", "", 0);
			std::string title = f->dump("title", "", 0);
			f->modify("title", "replace", "label[swap-title]");
			f->modify("hints", "replace", "label[swap-hints]");
			f->modify("swap-title", "replace", hints);
			f->modify("swap-hints", "replace", title);
		}
	}
	valid_cmds.push_back("set");
	valid_cmds.push_back("quit");
	valid_cmds.push_back("source");
	valid_cmds.push_back("dumpconfig");
	valid_cmds.push_back("dumpform");
}

void FormAction::set_keymap_hints()
{
	f->set("help", prepare_keymap_hint(this->get_keymap_hint()));
}

void FormAction::recalculate_form()
{
	f->run(-3);
}

FormAction::~FormAction() {}

std::shared_ptr<Stfl::Form> FormAction::get_form()
{
	return f;
}

std::string FormAction::prepare_keymap_hint(KeyMapHintEntry* hints)
{
	/*
	 * This function generates the "keymap hint" line by putting
	 * together the elements of a structure, and looking up the
	 * currently set keybinding so that the "keymap hint" line always
	 * reflects the current configuration.
	 */
	std::string keymap_hint;
	for (int i = 0; hints[i].op != OP_NIL; ++i) {
		std::string bound_keys = utils::join(v->get_keymap()->get_keys(hints[i].op,
					this->id()), ",");
		if (bound_keys.empty()) {
			bound_keys = "<none>";
		}
		keymap_hint.append(bound_keys);
		keymap_hint.append(":");
		keymap_hint.append(hints[i].text);
		keymap_hint.append(" ");
	}
	return keymap_hint;
}

std::string FormAction::get_value(const std::string& value)
{
	return f->get(value);
}

void FormAction::start_cmdline(std::string default_value)
{
	std::vector<QnaPair> qna;
	qna.push_back(QnaPair(":", default_value));
	v->inside_cmdline(true);
	this->start_qna(qna, OP_INT_END_CMDLINE, &FormAction::cmdlinehistory);
}

bool FormAction::process_op(Operation op,
	bool automatic,
	std::vector<std::string>* args)
{
	switch (op) {
	case OP_REDRAW:
		LOG(Level::DEBUG, "FormAction::process_op: redrawing screen");
		Stfl::reset();
		break;
	case OP_CMDLINE:
		start_cmdline();
		break;
	case OP_INT_SET:
		if (automatic) {
			std::string cmdline = "set ";
			if (args) {
				for (const auto& arg : *args) {
					cmdline.append(strprintf::fmt(
							"%s ", Stfl::quote(arg)));
				}
			}
			LOG(Level::DEBUG,
				"FormAction::process_op: running commandline "
				"`%s'",
				cmdline);
			this->handle_cmdline(cmdline);
		} else {
			LOG(Level::WARN,
				"FormAction::process_op: got OP_INT_SET, but "
				"not "
				"automatic");
		}
		break;
	case OP_INT_CANCEL_QNA:
		f->modify("lastline",
			"replace",
			"{hbox[lastline] .expand:0 {label[msglabel] .expand:h "
			"text[msg]:\"\"}}");
		v->inside_qna(false);
		v->inside_cmdline(false);
		break;
	case OP_INT_QNA_NEXTHIST:
		if (qna_history) {
			std::string entry = qna_history->next();
			f->set("qna_value", entry);
			f->set("qna_value_pos", std::to_string(entry.length()));
		}
		break;
	case OP_INT_QNA_PREVHIST:
		if (qna_history) {
			std::string entry = qna_history->prev();
			f->set("qna_value", entry);
			f->set("qna_value_pos", std::to_string(entry.length()));
		}
		break;
	case OP_INT_END_QUESTION:
		/*
		 * An answer has been entered, we save the value, and ask the
		 * next question.
		 */
		qna_responses.push_back(f->get("qna_value"));
		start_next_question();
		break;
	case OP_VIEWDIALOGS:
		v->view_dialogs();
		break;
	case OP_NEXTDIALOG:
		v->goto_next_dialog();
		break;
	case OP_PREVDIALOG:
		v->goto_prev_dialog();
		break;
	default:
		return this->process_operation(op, automatic, args);
	}
	return true;
}<commit_msg>Pass up,down,pageup,pagedown,home,end to STFL<commit_after>#include "formaction.h"

#include <cassert>
#include <cinttypes>
#include <ncurses.h>

#include "config.h"
#include "configexception.h"
#include "logger.h"
#include "matcherexception.h"
#include "strprintf.h"
#include "utils.h"
#include "view.h"

namespace newsboat {

History FormAction::searchhistory;
History FormAction::cmdlinehistory;

FormAction::FormAction(View* vv, std::string formstr, ConfigContainer* cfg)
	: v(vv)
	, cfg(cfg)
	, f(new Stfl::Form(formstr))
	, do_redraw(true)
	, finish_operation(OP_NIL)
	, qna_history(nullptr)
{
	if (v) {
		if (cfg->get_configvalue_as_bool("show-keymap-hint") == false) {
			f->set("showhint", "0");
		}
		if (cfg->get_configvalue_as_bool("show-title-bar") == false) {
			f->set("showtitle", "0");
		}
		if (cfg->get_configvalue_as_bool("swap-title-and-hints") ==
			true) {
			std::string hints = f->dump("hints", "", 0);
			std::string title = f->dump("title", "", 0);
			f->modify("title", "replace", "label[swap-title]");
			f->modify("hints", "replace", "label[swap-hints]");
			f->modify("swap-title", "replace", hints);
			f->modify("swap-hints", "replace", title);
		}
	}
	valid_cmds.push_back("set");
	valid_cmds.push_back("quit");
	valid_cmds.push_back("source");
	valid_cmds.push_back("dumpconfig");
	valid_cmds.push_back("dumpform");
}

void FormAction::set_keymap_hints()
{
	f->set("help", prepare_keymap_hint(this->get_keymap_hint()));
}

void FormAction::recalculate_form()
{
	f->run(-3);
}

FormAction::~FormAction() {}

std::shared_ptr<Stfl::Form> FormAction::get_form()
{
	return f;
}

std::string FormAction::prepare_keymap_hint(KeyMapHintEntry* hints)
{
	/*
	 * This function generates the "keymap hint" line by putting
	 * together the elements of a structure, and looking up the
	 * currently set keybinding so that the "keymap hint" line always
	 * reflects the current configuration.
	 */
	std::string keymap_hint;
	for (int i = 0; hints[i].op != OP_NIL; ++i) {
		std::string bound_keys = utils::join(v->get_keymap()->get_keys(hints[i].op,
					this->id()), ",");
		if (bound_keys.empty()) {
			bound_keys = "<none>";
		}
		keymap_hint.append(bound_keys);
		keymap_hint.append(":");
		keymap_hint.append(hints[i].text);
		keymap_hint.append(" ");
	}
	return keymap_hint;
}

std::string FormAction::get_value(const std::string& value)
{
	return f->get(value);
}

void FormAction::start_cmdline(std::string default_value)
{
	std::vector<QnaPair> qna;
	qna.push_back(QnaPair(":", default_value));
	v->inside_cmdline(true);
	this->start_qna(qna, OP_INT_END_CMDLINE, &FormAction::cmdlinehistory);
}

bool FormAction::process_op(Operation op,
	bool automatic,
	std::vector<std::string>* args)
{
	switch (op) {
	case OP_REDRAW:
		LOG(Level::DEBUG, "FormAction::process_op: redrawing screen");
		Stfl::reset();
		break;
	case OP_CMDLINE:
		start_cmdline();
		break;
	case OP_INT_SET:
		if (automatic) {
			std::string cmdline = "set ";
			if (args) {
				for (const auto& arg : *args) {
					cmdline.append(strprintf::fmt(
							"%s ", Stfl::quote(arg)));
				}
			}
			LOG(Level::DEBUG,
				"FormAction::process_op: running commandline "
				"`%s'",
				cmdline);
			this->handle_cmdline(cmdline);
		} else {
			LOG(Level::WARN,
				"FormAction::process_op: got OP_INT_SET, but "
				"not "
				"automatic");
		}
		break;
	case OP_INT_CANCEL_QNA:
		f->modify("lastline",
			"replace",
			"{hbox[lastline] .expand:0 {label[msglabel] .expand:h "
			"text[msg]:\"\"}}");
		v->inside_qna(false);
		v->inside_cmdline(false);
		break;
	case OP_INT_QNA_NEXTHIST:
		if (qna_history) {
			std::string entry = qna_history->next();
			f->set("qna_value", entry);
			f->set("qna_value_pos", std::to_string(entry.length()));
		}
		break;
	case OP_INT_QNA_PREVHIST:
		if (qna_history) {
			std::string entry = qna_history->prev();
			f->set("qna_value", entry);
			f->set("qna_value_pos", std::to_string(entry.length()));
		}
		break;
	case OP_INT_END_QUESTION:
		/*
		 * An answer has been entered, we save the value, and ask the
		 * next question.
		 */
		qna_responses.push_back(f->get("qna_value"));
		start_next_question();
		break;
	case OP_VIEWDIALOGS:
		v->view_dialogs();
		break;
	case OP_NEXTDIALOG:
		v->goto_next_dialog();
		break;
	case OP_PREVDIALOG:
		v->goto_prev_dialog();
		break;
	case OP_SK_UP:
		if (ungetch(KEY_UP) == OK) {
			get_form()->run(0);
		}
		break;
	case OP_SK_DOWN:
		if (ungetch(KEY_DOWN) == OK) {
			get_form()->run(0);
		}
		break;
	case OP_SK_PGUP:
		if (ungetch(KEY_PPAGE) == OK) {
			get_form()->run(0);
		}
		break;
	case OP_SK_PGDOWN:
		if (ungetch(KEY_NPAGE) == OK) {
			get_form()->run(0);
		}
		break;
	case OP_SK_HOME:
		if (ungetch(KEY_HOME) == OK) {
			get_form()->run(0);
		}
		break;
	case OP_SK_END:
		if (ungetch(KEY_END) == OK) {
			get_form()->run(0);
		}
		break;
	default:
		return this->process_operation(op, automatic, args);
	}
	return true;
}
{'fraction_non_alphanumeric': 0.178428617745596, 'fraction_numerical': 0.0021614611477358695, 'mean_word_length': 4.708821714990746, 'pattern_counts': {'":': 4, '<': 16, '<?xml version=': 0, '>': 92, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4468377', 'n_tokens_mistral': 3994, 'n_tokens_neox': 3664, 'n_words': 637}