/*** Olive - Non-Linear Video Editor Copyright (C) 2022 Olive Team Modifications Copyright (C) 2025 mikesolar 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 3 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, see . ***/ #include "commandlineparser.h" #include #include CommandLineParser::~CommandLineParser() { foreach (const KnownOption &o, options_) { delete o.option; } foreach (const KnownPositionalArgument &a, positional_args_) { delete a.option; } } const CommandLineParser::Option * CommandLineParser::AddOption(const QStringList &strings, const QString &description, bool takes_arg, const QString &arg_placeholder, bool hidden) { Option *o = new Option(); options_.append( { strings, description, o, takes_arg, arg_placeholder, hidden }); return o; } const CommandLineParser::PositionalArgument * CommandLineParser::AddPositionalArgument(const QString &name, const QString &description, bool required) { PositionalArgument *a = new PositionalArgument(); positional_args_.append({ name, description, a, required }); return a; } void CommandLineParser::Process(const QVector &argv) { int positional_index = 0; for (int i = 1; i < argv.size(); i++) { if (argv[i][0] == '-') { // Must be an option // Skip past first dashes QString arg_basename = argv[i].mid(1); bool matched_known = false; for (int j = 0; j < options_.size(); j++) { KnownOption &o = options_[j]; foreach (const QString &s, o.args) { if (!s.compare(arg_basename, Qt::CaseInsensitive)) { // Flag discovered! o.option->Set(); if (o.takes_arg && i + 1 < argv.size()) { o.option->SetSetting(argv[i + 1]); i++; } matched_known = true; goto found_flag; } } } found_flag: if (!matched_known) { qWarning() << "Unknown parameter:" << argv[i]; } } else { // Must be a positional flag if (positional_index < positional_args_.size()) { positional_args_[positional_index].option->SetSetting(argv[i]); positional_index++; } else { qWarning() << "Unknown parameter:" << argv[i]; } } } } void CommandLineParser::PrintHelp(const char *filename) { printf("%s %s\n", QCoreApplication::applicationName().toUtf8().constData(), QCoreApplication::applicationVersion().toUtf8().constData()); printf("Copyright (C) 2018-2022 Oak Video Editor Team\n"); QString positional_args; for (int i = 0; i < positional_args_.size(); i++) { if (i > 0) { positional_args.append(' '); } positional_args.append('['); positional_args.append(positional_args_.at(i).name); positional_args.append(']'); } const char *basename; #ifdef Q_OS_WINDOWS basename = strrchr(filename, '\\'); if (!basename) { basename = strrchr(filename, '/'); } #else basename = strrchr(filename, '/'); #endif if (basename) { // Slash found, increment pointer to avoid showing the slash itself basename++; } else { // If no slashes are found, assume string is already a basename basename = filename; } printf("Usage: %s [options] %s\n\n", basename, positional_args.toUtf8().constData()); foreach (const KnownOption &o, options_) { if (o.hidden) { continue; } QString all_args; for (int i = 0; i < o.args.size(); i++) { if (i > 0) { all_args.append(QStringLiteral(", ")); } const QString &this_arg = o.args.at(i); all_args.append('-'); all_args.append(this_arg); } if (o.arg_placeholder.isEmpty()) { printf(" %s\n", all_args.toUtf8().constData()); } else { printf(" %s <%s>\n", all_args.toUtf8().constData(), o.arg_placeholder.toUtf8().constData()); } printf(" %s\n\n", o.description.toUtf8().constData()); } printf("\n"); }