ericw-tools/common/settings.cc

196 lines
5.6 KiB
C++

/* Copyright (C) 2016 Eric Wasylishen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
See file, 'COPYING', for details.
*/
#include "common/settings.hh"
#include "common/threads.hh"
#include "common/fs.hh"
namespace settings
{
setting_base::setting_base(
setting_container *dictionary, const nameset &names, const setting_group *group, const char *description)
: _names(names), _group(group), _description(description)
{
Q_assert(_names.size() > 0);
if (dictionary) {
dictionary->registerSetting(this);
}
}
bool setting_base::parseString(const std::string &string, source source)
{
parser_t p{string};
return parse("", p, source);
}
setting_group performance_group{"Performance", 10};
setting_group logging_group{"Logging", 5};
setting_group game_group{"Game", 15};
setting_container::~setting_container() = default;
void setting_container::reset()
{
for (auto setting : _settings) {
setting->reset();
}
}
void setting_container::copyFrom(const setting_container &other)
{
for (auto setting : _settings) {
const std::string &pri_name = setting->primaryName();
const auto *other_setting = other.findSetting(pri_name);
if (other_setting) {
setting->copyFrom(*other_setting);
}
}
}
void setting_container::printHelp()
{
fmt::print("{}usage: {} [-help/-h/-?] [-options] {}\n\n", programDescription, programName, remainderName);
for (auto grouped : grouped()) {
if (grouped.first) {
fmt::print("{}:\n", grouped.first->name);
}
for (auto setting : grouped.second) {
size_t numPadding = max(static_cast<size_t>(0), 28 - (setting->primaryName().size() + 4));
fmt::print(" -{} {:{}} {}\n", setting->primaryName(), setting->format(), numPadding,
setting->getDescription());
for (int i = 1; i < setting->names().size(); i++) {
fmt::print(" \\{}\n", setting->names()[i]);
}
}
printf("\n");
}
throw quit_after_help_exception();
}
void setting_container::printSummary()
{
logging::print("\n--- Options Summary ---\n");
for (auto setting : _settings) {
if (setting->isChanged()) {
logging::print(" \"{}\" was set to \"{}\" (from {})\n", setting->primaryName(), setting->stringValue(),
setting->sourceString());
}
}
logging::print("\n");
}
std::vector<std::string> setting_container::parse(parser_base_t &parser)
{
// the settings parser loop will continuously eat tokens as long as
// it begins with a -; once we have no more settings to consume, we
// break out of this loop and return the remainder.
while (true) {
// end of cmd line
if (!parser.parse_token(PARSE_PEEK)) {
break;
}
// end of options
if (parser.token[0] != '-') {
break;
}
// actually eat the token since we peeked above
parser.parse_token();
// remove leading hyphens. we support any number of them.
while (parser.token.front() == '-') {
parser.token.erase(parser.token.begin());
}
if (parser.token.empty()) {
throw parse_exception("stray \"-\" in command line; please check your parameters");
}
if (parser.token == "help" || parser.token == "h" || parser.token == "?") {
printHelp();
}
auto setting = findSetting(parser.token);
if (!setting) {
throw parse_exception(fmt::format("unknown option \"{}\"", parser.token));
}
// pass off to setting to parse; store
// name for error message below
std::string token = std::move(parser.token);
if (!setting->parse(token, parser, source::COMMANDLINE)) {
throw parse_exception(
fmt::format("invalid value for option \"{}\"; should be in format {}", token, setting->format()));
}
}
// return remainder
std::vector<std::string> remainder;
while (true) {
if (parser.at_end() || !parser.parse_token()) {
break;
}
remainder.emplace_back(std::move(parser.token));
}
return remainder;
}
void common_settings::setParameters(int argc, const char **argv)
{
programName = fs::path(argv[0]).stem().string();
fmt::print("---- {} / ericw-tools {} ----\n", programName, ERICWTOOLS_VERSION);
}
void common_settings::postinitialize(int argc, const char **argv)
{
printSummary();
configureTBB(threads.value(), lowpriority.value());
if (verbose.value()) {
logging::mask |= logging::flag::VERBOSE;
}
if (nopercent.value()) {
logging::mask &= ~bitflags<logging::flag>(logging::flag::PERCENT);
}
if (nostat.value()) {
logging::mask &= ~bitflags<logging::flag>(logging::flag::STAT);
}
if (noprogress.value()) {
logging::mask &= ~bitflags<logging::flag>(logging::flag::PROGRESS);
}
}
} // namespace settings