summaryrefslogtreecommitdiff
path: root/examples/joinargs.cpp
blob: efe19e3cec78022a5c6584b1d2d37d7529ea21aa (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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include <argagg/argagg.hpp>

#include <cstdlib>
#include <fstream>
#include <iostream>
#include <sstream>

static std::ofstream g_dev_null;

int main(
  int argc,
  const char** argv)
{
  using argagg::parser_results;
  using argagg::parser;
  using std::cerr;
  using std::cout;
  using std::endl;
  using std::ofstream;
  using std::ostream;
  using std::ostringstream;
  using std::string;

  // Use an initializer list to define the argument parser. The first brace
  // starts the initializer list, the second brace starts the initializer list
  // for the definitions vector in the argagg::parser struct.
  parser argparser {{

      // Each entry here is an initializer list for an `argagg::definition`
      // struct.
      {
        // Name of the option. This is the key used to retrieve the flag parser
        // results.
        "help",

        // The strings ("flags") that must be matched to activate this option.
        {"-h", "--help"},

        // The help string that is streamed out when the argagg::parser object
        // itself is streamed out.
        "displays help information",

        // Number of arguments needed by this option. Should be 0 or 1.
        0},
      {
        "verbose", {"-v", "--verbose"},
        "increases verbosity", 0},
      {
        "lorem-ipsum", {"--lorem-ipsum"},
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
        "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim "
        "ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut "
        "aliquip ex ea commodo consequat. Duis aute irure dolor in "
        "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla "
        "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in "
        "culpa qui officia deserunt mollit anim id est laborum.", 0},
      {
        "sep", {"-s", "--sep"},
        "separator (default ',')", 1},
      {
        "output", {"-o", "--output"},
        "output filename (stdout if not specified)", 1},
    }};

  // Define our usage text.
  ostringstream usage;
  usage
    << "Joins all positional arguments together with a separator" << endl
    << endl
    << "Usage: " << argv[0] << " [options] ARG [ARG...]" << endl
    << endl;

  // Use our argument parser to... parse the command line arguments. If there
  // are any problems then just spit out the usage and help text and exit.
  argagg::parser_results args;
  try {
    args = argparser.parse(argc, argv);
  } catch (const std::exception& e) {
    argagg::fmt_ostream help(cerr);
    help << usage.str() << argparser << endl
         << "Encountered exception while parsing arguments: " << e.what()
         << endl;
    return EXIT_FAILURE;
  }

  // If the help flag was specified then spit out the usage and help text and
  // exit.
  if (args["help"]) {
    argagg::fmt_ostream help(cerr);
    help << usage.str() << argparser;
    return EXIT_SUCCESS;
  }

  // Respect verbosity. Okay, the logging here is a little ludicrous. The point
  // I want to show here is that you can quickly get the number of times an
  // option shows up.
  int verbose_level = args["verbose"].count();

  // Set up our verbose log output stream selector that selects stderr if the
  // requested log level is lower than or equal to the currently set verbose
  // level.
  g_dev_null.open("/dev/null"); // portable? eh... simple? yes!
  auto vlog = [&](int level) -> ostream& {
      return verbose_level >= level ? cerr : g_dev_null;
    };

  vlog(1) << "verbose log level: " << verbose_level << endl;

  // Use comma as the separator unless one was specified.
  auto sep = args["sep"].as<string>(",");
  vlog(1) << "set separator to '" << sep << "'" << endl;

  // Determine output stream.
  ofstream output_file;
  ostream* output = &std::cout;
  if (args["output"]) {
    string filename = args["output"];
    output_file.open(filename);
    output = &output_file;
    vlog(1) << "outputting to file at '" << filename << "'" << endl;
  } else {
    vlog(1) << "outputting to stdout" << endl;
  }

  // Join the arguments.
  if (args.count() < 1) {
    vlog(0) << usage.str() << argparser << endl
            << "Not enough arguments" << endl;
    return EXIT_FAILURE;
  }
  for (auto& arg : args.pos) {
    vlog(2) << "writing argument" << endl;
    vlog(4) << "argument is '" << arg << "'" << endl;
    *output << arg;
    if (arg != args.pos.back()) {
      vlog(3) << "writing separator" << endl;
      *output << sep;
    }
  }
  vlog(4) << "writing endl" << endl;
  *output << endl;

  vlog(4) << "everything a-okay" << endl;
  return EXIT_SUCCESS;  
}