text: /*****************************************************************************
   *
   * demo program - part of CLIPP (command line interfaces for modern C++)
   *
   * released under MIT license
   *
   * (c) 2017-2018 André Müller; foss@andremueller-online.de
   *
  *
   * This command line interface example was taken from http://docopt.org/.
   *
   * EXAMPLE
   *   We want to model this command line interface:
   *
   *     Naval Fate.
   *
   *     Usage:
   *       naval_fate ship new <name>...
   *       naval_fate ship <name> move <x> <y> [--speed=<kn>]
   *       naval_fate ship shoot <x> <y>
   *       naval_fate mine (set|remove) <x> <y> [--moored|--drifting]
   *       naval_fate -h | --help
   *       naval_fate --version
   *
   *     Options:
   *       -h --help     Show this screen.
   *       --version     Show version.
   *       --speed=<kn>  Speed in knots [default: 10].
   *       --moored      Moored (anchored) mine.
   *       --drifting    Drifting mine.
   *
   *
   *****************************************************************************/
  
  #include <iostream>
  #include <algorithm>
  #include <string>
  #include <vector>
  
  #include <clipp.h>
  
  
  int main(int argc, char* argv[])
  {
      using namespace clipp;
      using std::string;
      using std::vector;
      using std::cout;
  
      int x = 0, y = 0;
      float speed = 10.0f;
      bool drift = true;
      vector<string> names;
  
      enum class mode { none, help, shipnew, shipmove, shipshoot, mineset, minerem};
      mode selected = mode::none;
  
      auto coordinates = ( value("x", x), value("y", y) );
  
      auto shipnew  = ( command("new").set(selected,mode::shipnew),
                        values("name", names) );
  
      auto shipmove = (
          value("name", names),
          command("move").set(selected,mode::shipmove), coordinates,
          (option("--speed=") & value("kn",speed)) % "Speed in knots [default: 10]");
  
      auto shipshoot = ( command("shoot").set(selected,mode::shipshoot),
                         coordinates );
  
      auto mines = ( 
          command("mine"),
          (command("set"   ).set(selected,mode::mineset) | 
           command("remove").set(selected,mode::minerem) ),
          coordinates,
          (option("--moored"  ).set(drift,false) % "Moored (anchored) mine." | 
           option("--drifting").set(drift,true)  % "Drifting mine."          )
      );
  
      auto navalcli = (
          ( command("ship"), ( shipnew | shipmove | shipshoot ) )
          | mines
          | command("-h", "--help").set(selected,mode::help)     % "Show this screen."
          | command("--version")([]{ cout << "version 1.0\n"; }) % "Show version."
      );
  
      auto fmt = doc_formatting{}
          .first_column(2)
          .doc_column(20)
          .max_flags_per_param_in_usage(8);
  
      if(parse(argc, argv, navalcli)) {
          switch(selected) {
              default:
              case mode::none:
                  break;
              case mode::help: {
                  cout << "Naval Fate.\n\nUsage:\n"
                       << usage_lines(navalcli, "naval_fate", fmt)
                       << "\n\nOptions:\n"
                       << documentation(navalcli, fmt) << '\n';
                  }
                  break;
              case mode::shipnew:
                  if(names.empty()) {
                      cout << "No new ships were made\n";
                  } else {
                      cout << "Made new ship" << (names.size() > 1 ? "s " : " ");
                      for(const auto& n : names) cout << n << ' ';
                      cout << "\n";
                  }
                  break;
              case mode::shipmove:
                  if(names.empty()) {
                      cout << "No ship was moved.\n";
                  } else {
                      cout << "Moving ship " << names.front()
                           << " to x=" << x << " y=" << y << ".\n";
                  }
                  break;
              case mode::shipshoot:
                  cout << "Ship fired shot aimed at x=" << x << " y=" << y << ".\n";
                  break;
              case mode::mineset:
                  cout << "Laid " << (drift ? "drifting" : "& moored")
                       << " mine at x=" << x << " y=" << y << ".\n";
                  break;
              case mode::minerem:
                  cout << "Removed mine at x=" << x << " y=" << y << ".\n";
                  break;
          }
      }
      else {
          std::cerr << "Wrong command line arguments.\nUsage:"
                    << usage_lines(navalcli, "naval_fate", fmt) << '\n';
      }
  
  }
  