aboutsummaryrefslogtreecommitdiff
path: root/src/Cli/Cli.c
blob: 3648493c862204535f4d4e0a79ca811aa1e42ee3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include "Cli/Cli.h"

#include "Logger/Logger.h"
#include "Version/Version.h"

#include <getopt.h>
#include <stdio.h>

void cli_print_usage(const char *program_name) {
  fprintf(
      stderr,
      "Usage:\n"
      "  %s FILE [-o OUTPUT]\n"
      "  %s -d DIRECTORY [-o OUTPUT] [-f]\n\n"
      "Options:\n"
      "  -d, --directory DIRECTORY   Process a directory recursively\n"
      "  -o, --output OUTPUT         Set the output path\n"
      "  -f, --overwrite             Overwrite an existing output directory\n"
      "  -l, --log-level LEVEL       error, warning, info, debug, or silent\n"
      "  -v, --version               Show the program version\n"
      "  -h, --help                  Show this help\n",
      program_name, program_name);
}

static void cli_print_version(void) { printf("yapssg %s\n", yapssg_version); }

static const char *strip_optional_equals(const char *value) {
  return value != NULL && value[0] == '=' ? value + 1 : value;
}

CliParseResult cli_parse(int argc, char **argv, CliOptions *options) {
  static const struct option long_options[] = {
      {"directory", required_argument, NULL, 'd'},
      {"output", required_argument, NULL, 'o'},
      {"overwrite", no_argument, NULL, 'f'},
      {"force", no_argument, NULL, 'f'},
      {"log-level", required_argument, NULL, 'l'},
      {"version", no_argument, NULL, 'v'},
      {"help", no_argument, NULL, 'h'},
      {NULL, 0, NULL, 0}};
  const char *directory = NULL;
  int option;

  options->input_type = INPUT_TYPE_NONE;
  options->input_path = NULL;
  options->output_path = NULL;
  options->overwrite_output = 0;
  options->log_level = LOG_LEVEL_INFO;

  while ((option = getopt_long(argc, argv, "d:o:fl:vh", long_options, NULL)) !=
         -1) {
    switch (option) {
    case 'd':
      directory = strip_optional_equals(optarg);
      break;
    case 'o':
      options->output_path = strip_optional_equals(optarg);
      break;
    case 'f':
      options->overwrite_output = 1;
      break;
    case 'l':
      if (logger_parse_level(optarg, &options->log_level) != 0) {
        logger_error("unknown log level '%s'", optarg);
        return CLI_PARSE_ERROR;
      }
      break;
    case 'v':
      cli_print_version();
      return CLI_PARSE_VERSION;
    case 'h':
      cli_print_usage(argv[0]);
      return CLI_PARSE_HELP;
    default:
      cli_print_usage(argv[0]);
      return CLI_PARSE_ERROR;
    }
  }

  if (directory != NULL) {
    if (optind != argc || directory[0] == '\0') {
      logger_error("a directory cannot be combined with a file");
      return CLI_PARSE_ERROR;
    }
    options->input_type = INPUT_TYPE_DIRECTORY;
    options->input_path = directory;
  } else {
    if (optind + 1 != argc) {
      cli_print_usage(argv[0]);
      return CLI_PARSE_ERROR;
    }
    options->input_type = INPUT_TYPE_FILE;
    options->input_path = argv[optind];
  }

  if (options->output_path != NULL && options->output_path[0] == '\0') {
    logger_error("output path cannot be empty");
    return CLI_PARSE_ERROR;
  }

  return CLI_PARSE_OK;
}