metaforce/hecl/driver/ToolBase.hpp

236 lines
5.9 KiB
C++
Raw Normal View History

2018-10-07 03:38:44 +00:00
#pragma once
2015-05-20 05:22:32 +00:00
#include <string>
#include <vector>
#include <list>
2017-12-29 07:56:31 +00:00
#include <cstdio>
#include <cstring>
2015-05-20 05:22:32 +00:00
2015-07-22 19:14:50 +00:00
#ifndef _WIN32
#include <unistd.h>
2017-10-25 07:46:32 +00:00
#include <termios.h>
2017-10-30 07:29:07 +00:00
#else
#include <conio.h>
2015-07-22 19:14:50 +00:00
#endif
2016-03-04 23:02:44 +00:00
#include "hecl/Database.hpp"
#include "logvisor/logvisor.hpp"
2015-07-05 06:27:24 +00:00
2016-03-04 23:02:44 +00:00
extern logvisor::Module LogModule;
2018-12-08 05:18:42 +00:00
struct ToolPassInfo {
hecl::SystemString pname;
hecl::SystemString cwd;
std::vector<hecl::SystemString> args;
std::vector<hecl::SystemChar> flags;
hecl::SystemString output;
hecl::Database::Project* project = nullptr;
unsigned verbosityLevel = 0;
bool force = false;
bool yes = false;
bool gui = false;
2015-05-20 05:22:32 +00:00
};
2017-10-25 07:46:32 +00:00
#define RED "\033[0;31m"
#define GREEN "\033[0;32m"
#define YELLOW "\033[0;33m"
#define BLUE "\033[0;34m"
#define MAGENTA "\033[0;35m"
#define CYAN "\033[0;36m"
#define BOLD "\033[1m"
#define NORMAL "\033[0m"
#define HIDE_CURSOR "\033[?25l"
#define SHOW_CURSOR "\033[?25h"
#define WRAP_INDENT 4
extern bool XTERM_COLOR;
2018-12-08 05:18:42 +00:00
class ToolBase {
protected:
2018-12-08 05:18:42 +00:00
const ToolPassInfo& m_info;
bool m_good = false;
bool continuePrompt() {
if (!m_info.yes) {
if (XTERM_COLOR)
2020-04-11 22:48:11 +00:00
fmt::print(FMT_STRING(_SYS_STR("\n" BLUE BOLD "Continue?" NORMAL " (Y/n) ")));
2018-12-08 05:18:42 +00:00
else
2020-04-11 22:48:11 +00:00
fmt::print(FMT_STRING(_SYS_STR("\nContinue? (Y/n) ")));
2018-12-08 05:18:42 +00:00
fflush(stdout);
int ch;
2017-10-25 07:46:32 +00:00
#ifndef _WIN32
2018-12-08 05:18:42 +00:00
struct termios tioOld, tioNew;
tcgetattr(0, &tioOld);
tioNew = tioOld;
tioNew.c_lflag &= ~ICANON;
tcsetattr(0, TCSANOW, &tioNew);
while ((ch = getchar()))
2017-10-25 07:46:32 +00:00
#else
2018-12-08 05:18:42 +00:00
while ((ch = getch()))
2017-10-25 07:46:32 +00:00
#endif
2018-12-08 05:18:42 +00:00
{
if (ch == 'n' || ch == 'N') {
2020-04-11 22:48:11 +00:00
fmt::print(FMT_STRING(_SYS_STR("\n")));
2018-12-08 05:18:42 +00:00
return false;
}
if (ch == 'y' || ch == 'Y' || ch == '\r' || ch == '\n')
break;
}
2017-10-25 07:46:32 +00:00
#ifndef _WIN32
2018-12-08 05:18:42 +00:00
tcsetattr(0, TCSANOW, &tioOld);
2017-10-25 07:46:32 +00:00
#endif
}
2020-04-11 22:48:11 +00:00
fmt::print(FMT_STRING(_SYS_STR("\n")));
2018-12-08 05:18:42 +00:00
return true;
}
2017-10-25 07:46:32 +00:00
public:
explicit ToolBase(const ToolPassInfo& info) : m_info(info) {
2018-12-08 05:18:42 +00:00
hecl::VerbosityLevel = info.verbosityLevel;
hecl::GuiMode = info.gui;
}
virtual ~ToolBase() = default;
2020-04-10 03:19:33 +00:00
virtual hecl::SystemStringView toolName() const = 0;
2018-12-08 05:18:42 +00:00
virtual int run() = 0;
virtual void cancel() {}
explicit operator bool() const { return m_good; }
};
2018-12-08 05:18:42 +00:00
class HelpOutput {
2015-05-26 04:42:20 +00:00
public:
using HelpFunc = void (*)(HelpOutput&);
2015-05-26 04:42:20 +00:00
2018-12-08 05:18:42 +00:00
private:
FILE* m_sout = nullptr;
2018-12-08 05:18:42 +00:00
HelpFunc m_helpFunc;
int m_lineWidth;
hecl::SystemString m_wrapBuffer;
void _wrapBuf(hecl::SystemString& string) {
int counter;
hecl::SystemString::iterator it = string.begin();
while (it != string.end()) {
std::ptrdiff_t v = it - string.begin();
/* copy string until the end of the line is reached */
for (counter = WRAP_INDENT; counter < m_lineWidth; ++counter) {
if (it >= string.end())
return;
if (*it == _SYS_STR('\n')) {
counter = WRAP_INDENT;
++it;
}
if (counter == WRAP_INDENT) {
for (int i = 0; i < WRAP_INDENT; ++i)
it = string.insert(it, _SYS_STR(' ')) + 1;
}
if (it >= string.end())
return;
if (*it != _SYS_STR('\n'))
++it;
}
/* check for whitespace */
if (isspace(*it)) {
*it = _SYS_STR('\n');
counter = WRAP_INDENT;
++it;
} else {
/* check for nearest whitespace back in string */
for (hecl::SystemString::iterator k = it; k != string.begin(); --k) {
if (isspace(*k)) {
counter = WRAP_INDENT;
if (k - string.begin() < v)
k = string.insert(it, _SYS_STR('\n'));
2015-05-26 04:42:20 +00:00
else
2018-12-08 05:18:42 +00:00
*k = _SYS_STR('\n');
it = k + 1;
break;
}
2015-05-26 04:42:20 +00:00
}
2018-12-08 05:18:42 +00:00
}
2015-05-26 04:42:20 +00:00
}
2018-12-08 05:18:42 +00:00
}
2015-05-26 04:42:20 +00:00
public:
explicit HelpOutput(HelpFunc helpFunc)
: m_helpFunc(helpFunc), m_lineWidth(hecl::GuiMode ? 120 : hecl::ConsoleWidth()) {}
2015-05-26 04:42:20 +00:00
2018-12-08 05:18:42 +00:00
void go() {
2015-06-10 02:40:03 +00:00
#if _WIN32
2018-12-08 05:18:42 +00:00
m_sout = stdout;
m_helpFunc(*this);
2015-06-10 02:40:03 +00:00
#else
2018-12-08 05:18:42 +00:00
m_sout = popen("less -R", "w");
if (m_sout) {
m_helpFunc(*this);
pclose(m_sout);
} else {
m_sout = stdout;
m_helpFunc(*this);
2015-05-26 04:42:20 +00:00
}
2018-12-08 05:18:42 +00:00
#endif
}
2020-04-11 22:48:11 +00:00
void print(const hecl::SystemChar* str) { fmt::print(m_sout, FMT_STRING(_SYS_STR("{}")), str); }
2018-12-08 05:18:42 +00:00
void printBold(const hecl::SystemChar* str) {
if (XTERM_COLOR)
2020-04-11 22:48:11 +00:00
fmt::print(m_sout, FMT_STRING(_SYS_STR("" BOLD "{}" NORMAL "")), str);
2018-12-08 05:18:42 +00:00
else
2020-04-11 22:48:11 +00:00
fmt::print(m_sout, FMT_STRING(_SYS_STR("{}")), str);
2018-12-08 05:18:42 +00:00
}
void secHead(const hecl::SystemChar* headName) {
if (XTERM_COLOR)
2020-04-11 22:48:11 +00:00
fmt::print(m_sout, FMT_STRING(_SYS_STR("" BOLD "{}" NORMAL "\n")), headName);
2018-12-08 05:18:42 +00:00
else
2020-04-11 22:48:11 +00:00
fmt::print(m_sout, FMT_STRING(_SYS_STR("{}\n")), headName);
2018-12-08 05:18:42 +00:00
}
void optionHead(const hecl::SystemChar* flag, const hecl::SystemChar* synopsis) {
if (XTERM_COLOR)
2020-04-11 22:48:11 +00:00
fmt::print(m_sout, FMT_STRING(_SYS_STR("" BOLD "{}" NORMAL " ({})\n")), flag, synopsis);
2018-12-08 05:18:42 +00:00
else
2020-04-11 22:48:11 +00:00
fmt::print(m_sout, FMT_STRING(_SYS_STR("{} ({})\n")), flag, synopsis);
2018-12-08 05:18:42 +00:00
}
void beginWrap() { m_wrapBuffer.clear(); }
void wrap(const hecl::SystemChar* str) { m_wrapBuffer += str; }
void wrapBold(const hecl::SystemChar* str) {
if (XTERM_COLOR)
m_wrapBuffer += _SYS_STR("" BOLD "");
m_wrapBuffer += str;
if (XTERM_COLOR)
m_wrapBuffer += _SYS_STR("" NORMAL "");
}
void endWrap() {
_wrapBuf(m_wrapBuffer);
m_wrapBuffer += _SYS_STR('\n');
2020-04-11 22:48:11 +00:00
fmt::print(m_sout, FMT_STRING(_SYS_STR("{}")), m_wrapBuffer);
2018-12-08 05:18:42 +00:00
m_wrapBuffer.clear();
}
2015-05-26 04:42:20 +00:00
};
2018-12-08 05:18:42 +00:00
static hecl::SystemString MakePathArgAbsolute(const hecl::SystemString& arg, const hecl::SystemString& cwd) {
2015-10-02 04:06:45 +00:00
#if _WIN32
2018-12-08 05:18:42 +00:00
if (arg.size() >= 2 && iswalpha(arg[0]) && arg[1] == _SYS_STR(':'))
return arg;
if (arg[0] == _SYS_STR('\\') || arg[0] == _SYS_STR('/'))
return arg;
return cwd + _SYS_STR('\\') + arg;
2015-10-02 04:06:45 +00:00
#else
2018-12-08 05:18:42 +00:00
if (arg[0] == _SYS_STR('/') || arg[0] == _SYS_STR('\\'))
return arg;
if (cwd.back() == _SYS_STR('/') || cwd.back() == _SYS_STR('\\'))
return cwd + arg;
return cwd + _SYS_STR('/') + arg;
2015-10-02 04:06:45 +00:00
#endif
}