mirror of
https://github.com/fmang/opustags.git
synced 2025-02-22 23:14:11 +01:00
move the help and some arguments checking in cli.cc
This commit is contained in:
parent
bf386899ae
commit
b5dc595855
91
src/cli.cc
91
src/cli.cc
@ -1,33 +1,66 @@
|
||||
#include <config.h>
|
||||
#include <opustags.h>
|
||||
|
||||
#include <getopt.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
static const char* version = PROJECT_NAME " version " PROJECT_VERSION "\n";
|
||||
|
||||
static const char* usage = 1 + R"raw(
|
||||
Usage: opustags --help
|
||||
opustags [OPTIONS] FILE
|
||||
opustags OPTIONS FILE -o FILE
|
||||
)raw";
|
||||
|
||||
static const char* help = 1 + R"raw(
|
||||
Options:
|
||||
-h, --help print this help
|
||||
-o, --output write the modified tags to a file
|
||||
-i, --in-place [SUFFIX] use a temporary file then replace the original file
|
||||
-y, --overwrite overwrite the output file if it already exists
|
||||
-d, --delete FIELD delete all the fields of a specified type
|
||||
-a, --add FIELD=VALUE add a field
|
||||
-s, --set FIELD=VALUE delete then add a field
|
||||
-D, --delete-all delete all the fields!
|
||||
-S, --set-all read the fields from stdin
|
||||
)raw";
|
||||
|
||||
static struct option getopt_options[] = {
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"output", required_argument, 0, 'o'},
|
||||
{"in-place", optional_argument, 0, 'i'},
|
||||
{"overwrite", no_argument, 0, 'y'},
|
||||
{"delete", required_argument, 0, 'd'},
|
||||
{"add", required_argument, 0, 'a'},
|
||||
{"set", required_argument, 0, 's'},
|
||||
{"delete-all", no_argument, 0, 'D'},
|
||||
{"set-all", no_argument, 0, 'S'},
|
||||
{NULL, 0, 0, 0}
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"output", required_argument, 0, 'o'},
|
||||
{"in-place", optional_argument, 0, 'i'},
|
||||
{"overwrite", no_argument, 0, 'y'},
|
||||
{"delete", required_argument, 0, 'd'},
|
||||
{"add", required_argument, 0, 'a'},
|
||||
{"set", required_argument, 0, 's'},
|
||||
{"delete-all", no_argument, 0, 'D'},
|
||||
{"set-all", no_argument, 0, 'S'},
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse the command-line arguments.
|
||||
*
|
||||
* Return EXIT_SUCCESS on success, meaning the parsing succeeded and the program execution may
|
||||
* continue. On error, a relevant message is printed on stderr a non-zero exit code is returned.
|
||||
* Process the command-line arguments.
|
||||
*
|
||||
* This function does not perform I/O related validations, but checks the consistency of its
|
||||
* arguments.
|
||||
*
|
||||
* It returns one of :
|
||||
* - #ot::status::ok, meaning the process may continue normally.
|
||||
* - #ot::status::exit_now, meaning there is nothing to do and process should exit successfully.
|
||||
* This happens when all the user wants is see the help or usage.
|
||||
* - #ot::status::bad_arguments, meaning the arguments were invalid and the process should exit with
|
||||
* an error.
|
||||
*
|
||||
* Help messages are written on standard output, and error messages on standard error.
|
||||
*/
|
||||
int ot::parse_options(int argc, char** argv, ot::options& opt)
|
||||
ot::status ot::process_options(int argc, char** argv, ot::options& opt)
|
||||
{
|
||||
if (argc == 1) {
|
||||
fputs(version, stdout);
|
||||
fputs(usage, stdout);
|
||||
return status::exit_now;
|
||||
}
|
||||
int c;
|
||||
while ((c = getopt_long(argc, argv, "ho:i::yd:a:s:DS", getopt_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
@ -38,14 +71,14 @@ int ot::parse_options(int argc, char** argv, ot::options& opt)
|
||||
opt.path_out = optarg;
|
||||
if (opt.path_out.empty()) {
|
||||
fputs("output's file path cannot be empty\n", stderr);
|
||||
return EXIT_FAILURE;
|
||||
return status::bad_arguments;
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
opt.inplace = optarg == nullptr ? ".otmp" : optarg;
|
||||
if (strcmp(opt.inplace, "") == 0) {
|
||||
fputs("the in-place suffix cannot be empty\n", stderr);
|
||||
return EXIT_FAILURE;
|
||||
return status::bad_arguments;
|
||||
}
|
||||
break;
|
||||
case 'y':
|
||||
@ -54,7 +87,7 @@ int ot::parse_options(int argc, char** argv, ot::options& opt)
|
||||
case 'd':
|
||||
if (strchr(optarg, '=') != nullptr) {
|
||||
fprintf(stderr, "invalid field name: '%s'\n", optarg);
|
||||
return EXIT_FAILURE;
|
||||
return status::bad_arguments;
|
||||
}
|
||||
opt.to_delete.emplace_back(optarg);
|
||||
break;
|
||||
@ -62,7 +95,7 @@ int ot::parse_options(int argc, char** argv, ot::options& opt)
|
||||
case 's':
|
||||
if (strchr(optarg, '=') == NULL) {
|
||||
fprintf(stderr, "invalid comment: '%s'\n", optarg);
|
||||
return EXIT_FAILURE;
|
||||
return status::bad_arguments;
|
||||
}
|
||||
opt.to_add.emplace_back(optarg);
|
||||
if (c == 's')
|
||||
@ -76,10 +109,26 @@ int ot::parse_options(int argc, char** argv, ot::options& opt)
|
||||
break;
|
||||
default:
|
||||
/* getopt printed a message */
|
||||
return EXIT_FAILURE;
|
||||
return status::bad_arguments;
|
||||
}
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
if (opt.print_help) {
|
||||
puts(version);
|
||||
puts(usage);
|
||||
puts(help);
|
||||
puts("See the man page for extensive documentation.");
|
||||
return status::exit_now;
|
||||
}
|
||||
if (optind != argc - 1) {
|
||||
fputs("invalid arguments\n", stderr);
|
||||
return status::bad_arguments;
|
||||
}
|
||||
opt.path_in = argv[optind];
|
||||
if (opt.path_in.empty()) {
|
||||
fputs("input's file path cannot be empty\n", stderr);
|
||||
return status::bad_arguments;
|
||||
}
|
||||
return status::ok;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -10,25 +10,6 @@
|
||||
#include <unistd.h>
|
||||
#include <ogg/ogg.h>
|
||||
|
||||
const char *version = PROJECT_NAME " version " PROJECT_VERSION "\n";
|
||||
|
||||
const char *usage =
|
||||
"Usage: opustags --help\n"
|
||||
" opustags [OPTIONS] FILE\n"
|
||||
" opustags OPTIONS FILE -o FILE\n";
|
||||
|
||||
const char *help =
|
||||
"Options:\n"
|
||||
" -h, --help print this help\n"
|
||||
" -o, --output write the modified tags to a file\n"
|
||||
" -i, --in-place [SUFFIX] use a temporary file then replace the original file\n"
|
||||
" -y, --overwrite overwrite the output file if it already exists\n"
|
||||
" -d, --delete FIELD delete all the fields of a specified type\n"
|
||||
" -a, --add FIELD=VALUE add a field\n"
|
||||
" -s, --set FIELD=VALUE delete then add a field\n"
|
||||
" -D, --delete-all delete all the fields!\n"
|
||||
" -S, --set-all read the fields from stdin\n";
|
||||
|
||||
/**
|
||||
* Display the tags on stdout.
|
||||
*
|
||||
@ -46,36 +27,12 @@ static void print_tags(ot::opus_tags &tags)
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
if(argc == 1){
|
||||
fputs(version, stdout);
|
||||
fputs(usage, stdout);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
ot::options opt;
|
||||
int exit_code = parse_options(argc, argv, opt);
|
||||
if (exit_code != EXIT_SUCCESS)
|
||||
return exit_code;
|
||||
if (opt.print_help) {
|
||||
puts(version);
|
||||
puts(usage);
|
||||
puts(help);
|
||||
puts("See the man page for extensive documentation.");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
if(optind != argc - 1){
|
||||
fputs("invalid arguments\n", stderr);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
static int run(ot::options& opt)
|
||||
{
|
||||
if (opt.inplace != nullptr && !opt.path_out.empty()) {
|
||||
fputs("cannot combine --in-place and --output\n", stderr);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
opt.path_in = argv[optind];
|
||||
if (opt.path_in.empty()) {
|
||||
fputs("input's file path cannot be empty\n", stderr);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (!opt.path_out.empty() && opt.path_in != "-" && opt.path_out != "-") {
|
||||
char canon_in[PATH_MAX+1], canon_out[PATH_MAX+1];
|
||||
if (realpath(opt.path_in.c_str(), canon_in) && realpath(opt.path_out.c_str(), canon_out)) {
|
||||
@ -247,3 +204,14 @@ int main(int argc, char **argv){
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
ot::status rc;
|
||||
ot::options opt;
|
||||
rc = process_options(argc, argv, opt);
|
||||
if (rc == ot::status::exit_now)
|
||||
return EXIT_SUCCESS;
|
||||
else if (rc != ot::status::ok)
|
||||
return EXIT_FAILURE;
|
||||
return run(opt);
|
||||
}
|
||||
|
@ -24,6 +24,8 @@ namespace ot {
|
||||
*/
|
||||
enum class status {
|
||||
ok,
|
||||
exit_now,
|
||||
bad_arguments,
|
||||
int_overflow,
|
||||
/** On standard error, errno will give more details. */
|
||||
standard_error,
|
||||
@ -204,7 +206,7 @@ struct options {
|
||||
bool print_help = false;
|
||||
};
|
||||
|
||||
int parse_options(int argc, char** argv, options& opt);
|
||||
status process_options(int argc, char** argv, options& opt);
|
||||
std::list<std::string> read_tags(FILE* file);
|
||||
|
||||
/** \} */
|
||||
|
Loading…
x
Reference in New Issue
Block a user