<commit_before>#include <filebrowser_formaction.h>
#include <formatstring.h>
#include <logger.h>
#include <config.h>
#include <view.h>
#include <utils.h>
#include <strprintf.h>

#include <iostream>
#include <iomanip>
#include <sstream>
#include <cstring>

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <pwd.h>
#include <grp.h>


namespace newsboat {

filebrowser_formaction::filebrowser_formaction(view * vv, std::string formstr)
	: formaction(vv,formstr), quit(false)
{
	// In filebrowser, keyboard focus is at the input field, so user can't
	// possibly use 'q' key to exit the dialog
	keymap *keys = vv->get_keys();
	keys->set_key(OP_QUIT, "ESC", id());
	vv->set_keymap(keys);
}

filebrowser_formaction::~filebrowser_formaction() { }

void filebrowser_formaction::process_operation(operation op, bool /* automatic */, std::vector<std::string> * /* args */) {
	switch (op) {
	case OP_OPEN: {
		/*
		 * whenever "ENTER" is hit, we need to distinguish two different cases:
		 *   - the focus is in the list of files, then we need to set the filename field to the currently selected entry
		 *   - the focus is in the filename field, then the filename needs to be returned.
		 */
		LOG(level::DEBUG,"filebrowser_formaction: 'opening' item");
		std::string focus = f->get_focus();
		if (focus.length() > 0) {
			if (focus == "files") {
				std::string selection = f->get("listposname");
				char filetype = selection[0];
				selection.erase(0,1);
				std::string filename(selection);
				switch (filetype) {
				case 'd': {
					std::string fileswidth = f->get("files:w");
					unsigned int width = utils::to_u(fileswidth);

					fmtstr_formatter fmt;
					fmt.register_fmt('N', PROGRAM_NAME);
					fmt.register_fmt('V', PROGRAM_VERSION);
					fmt.register_fmt('f', filename);
					f->set("head", fmt.do_format(v->get_cfg()->get_configvalue("filebrowser-title-format"), width));
					int status = ::chdir(filename.c_str());
					LOG(level::DEBUG,
							"filebrowser_formaction:OP_OPEN: chdir(%s) = %i",
							filename, status);
					f->set("listpos","0");
					std::string fn = utils::getcwd();
					fn.append(NEWSBEUTER_PATH_SEP);
					std::string fnstr = f->get("filenametext");
					std::string::size_type base = fnstr.find_first_of('/');
					if (base == std::string::npos) {
						fn.append(fnstr);
					} else {
						fn.append(fnstr, base, std::string::npos);
					}
					f->set("filenametext",fn);
					do_redraw = true;
				}
				break;
				case '-': {
					std::string fn = utils::getcwd();
					fn.append(NEWSBEUTER_PATH_SEP);
					fn.append(filename);
					f->set("filenametext",fn);
					f->set_focus("filename");
				}
				break;
				default:
					// TODO: show error message
					break;
				}
			} else {
				bool do_pop = true;
				std::string fn = f->get("filenametext");
				struct stat sbuf;
				/*
				 * this check is very important, as people will kill us if they accidentaly overwrote their files
				 * with no further warning...
				 */
				if (::stat(fn.c_str(), &sbuf)!=-1) {
					f->set_focus("files");
					if (v->confirm(strprintf::fmt(_("Do you really want to overwrite `%s' (y:Yes n:No)? "), fn), _("yn")) == *_("n")) {
						do_pop = false;
					}
					f->set_focus("filenametext");
				}
				if (do_pop)
					v->pop_current_formaction();
			}
		}
	}
	break;
	case OP_QUIT:
		LOG(level::DEBUG,"view::filebrowser: quitting");
		v->pop_current_formaction();
		f->set("filenametext", "");
		break;
	case OP_HARDQUIT:
		LOG(level::DEBUG,"view::filebrowser: hard quitting");
		while (v->formaction_stack_size() >0) {
			v->pop_current_formaction();
		}
		f->set("filenametext", "");
		break;
	default:
		break;
	}
}

void filebrowser_formaction::prepare() {
	/*
	 * prepare is always called before an operation is processed,
	 * and if a redraw is necessary, it updates the list of files
	 * in the current directory.
	 */
	if (do_redraw) {
		auto cwdtmp = utils::getcwd();
		std::string code = "{list";

		DIR * dirp = ::opendir(cwdtmp.c_str());
		if (dirp) {
			struct dirent * de = ::readdir(dirp);
			while (de) {
				if (strcmp(de->d_name,".")!=0)
					code.append(add_file(de->d_name));
				de = ::readdir(dirp);
			}
			::closedir(dirp);
		}

		code.append("}");

		f->modify("files", "replace_inner", code);
		do_redraw = false;
	}<commit_msg>Show cursor in the filebrowser<commit_after>#include <filebrowser_formaction.h>
#include <formatstring.h>
#include <logger.h>
#include <config.h>
#include <view.h>
#include <utils.h>
#include <strprintf.h>

#include <iostream>
#include <iomanip>
#include <sstream>
#include <cstring>

#include <curses.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <pwd.h>
#include <grp.h>


namespace newsboat {

filebrowser_formaction::filebrowser_formaction(view * vv, std::string formstr)
	: formaction(vv,formstr), quit(false)
{
	// In filebrowser, keyboard focus is at the input field, so user can't
	// possibly use 'q' key to exit the dialog
	keymap *keys = vv->get_keys();
	keys->set_key(OP_QUIT, "ESC", id());
	vv->set_keymap(keys);
}

filebrowser_formaction::~filebrowser_formaction() { }

void filebrowser_formaction::process_operation(operation op, bool /* automatic */, std::vector<std::string> * /* args */) {
	switch (op) {
	case OP_OPEN: {
		/*
		 * whenever "ENTER" is hit, we need to distinguish two different cases:
		 *   - the focus is in the list of files, then we need to set the filename field to the currently selected entry
		 *   - the focus is in the filename field, then the filename needs to be returned.
		 */
		LOG(level::DEBUG,"filebrowser_formaction: 'opening' item");
		std::string focus = f->get_focus();
		if (focus.length() > 0) {
			if (focus == "files") {
				std::string selection = f->get("listposname");
				char filetype = selection[0];
				selection.erase(0,1);
				std::string filename(selection);
				switch (filetype) {
				case 'd': {
					std::string fileswidth = f->get("files:w");
					unsigned int width = utils::to_u(fileswidth);

					fmtstr_formatter fmt;
					fmt.register_fmt('N', PROGRAM_NAME);
					fmt.register_fmt('V', PROGRAM_VERSION);
					fmt.register_fmt('f', filename);
					f->set("head", fmt.do_format(v->get_cfg()->get_configvalue("filebrowser-title-format"), width));
					int status = ::chdir(filename.c_str());
					LOG(level::DEBUG,
							"filebrowser_formaction:OP_OPEN: chdir(%s) = %i",
							filename, status);
					f->set("listpos","0");
					std::string fn = utils::getcwd();
					fn.append(NEWSBEUTER_PATH_SEP);
					std::string fnstr = f->get("filenametext");
					std::string::size_type base = fnstr.find_first_of('/');
					if (base == std::string::npos) {
						fn.append(fnstr);
					} else {
						fn.append(fnstr, base, std::string::npos);
					}
					f->set("filenametext",fn);
					do_redraw = true;
				}
				break;
				case '-': {
					std::string fn = utils::getcwd();
					fn.append(NEWSBEUTER_PATH_SEP);
					fn.append(filename);
					f->set("filenametext",fn);
					f->set_focus("filename");
				}
				break;
				default:
					// TODO: show error message
					break;
				}
			} else {
				bool do_pop = true;
				std::string fn = f->get("filenametext");
				struct stat sbuf;
				/*
				 * this check is very important, as people will kill us if they accidentaly overwrote their files
				 * with no further warning...
				 */
				if (::stat(fn.c_str(), &sbuf)!=-1) {
					f->set_focus("files");
					if (v->confirm(strprintf::fmt(_("Do you really want to overwrite `%s' (y:Yes n:No)? "), fn), _("yn")) == *_("n")) {
						do_pop = false;
					}
					f->set_focus("filenametext");
				}
				if (do_pop) {
					curs_set(0);
					v->pop_current_formaction();
				}
			}
		}
	}
	break;
	case OP_QUIT:
		LOG(level::DEBUG,"view::filebrowser: quitting");
		curs_set(0);
		v->pop_current_formaction();
		f->set("filenametext", "");
		break;
	case OP_HARDQUIT:
		LOG(level::DEBUG,"view::filebrowser: hard quitting");
		while (v->formaction_stack_size() >0) {
			v->pop_current_formaction();
		}
		f->set("filenametext", "");
		break;
	default:
		break;
	}
}

void filebrowser_formaction::prepare() {
	/*
	 * prepare is always called before an operation is processed,
	 * and if a redraw is necessary, it updates the list of files
	 * in the current directory.
	 */
	if (do_redraw) {
		auto cwdtmp = utils::getcwd();
		std::string code = "{list";

		DIR * dirp = ::opendir(cwdtmp.c_str());
		if (dirp) {
			struct dirent * de = ::readdir(dirp);
			while (de) {
				if (strcmp(de->d_name,".")!=0)
					code.append(add_file(de->d_name));
				de = ::readdir(dirp);
			}
			::closedir(dirp);
		}

		code.append("}");

		f->modify("files", "replace_inner", code);
		do_redraw = false;
	}

	std::string focus = f->get_focus();
	if (focus == "files") {
		curs_set(0);
	} else {
		curs_set(1);
	}
{'fraction_non_alphanumeric': 0.16926906539941164, 'fraction_numerical': 0.0022629554197782305, 'mean_word_length': 3.5281762295081966, 'pattern_counts': {'":': 0, '<': 40, '<?xml version=': 0, '>': 99, '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': '4914433', 'n_tokens_mistral': 3743, 'n_tokens_neox': 3156, 'n_words': 715}