You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
4.3 KiB

2 years ago
  1. /*****************************************************************************
  2. *
  3. * demo program - part of CLIPP (command line interfaces for modern C++)
  4. *
  5. * released under MIT license
  6. *
  7. * (c) 2017-2018 André Müller; foss@andremueller-online.de
  8. *
  9. *
  10. * This command line interface example was taken from http://docopt.org/.
  11. *
  12. * EXAMPLE
  13. * We want to model this command line interface:
  14. *
  15. * Naval Fate.
  16. *
  17. * Usage:
  18. * naval_fate ship new <name>...
  19. * naval_fate ship <name> move <x> <y> [--speed=<kn>]
  20. * naval_fate ship shoot <x> <y>
  21. * naval_fate mine (set|remove) <x> <y> [--moored|--drifting]
  22. * naval_fate -h | --help
  23. * naval_fate --version
  24. *
  25. * Options:
  26. * -h --help Show this screen.
  27. * --version Show version.
  28. * --speed=<kn> Speed in knots [default: 10].
  29. * --moored Moored (anchored) mine.
  30. * --drifting Drifting mine.
  31. *
  32. *
  33. *****************************************************************************/
  34. #include <iostream>
  35. #include <algorithm>
  36. #include <string>
  37. #include <vector>
  38. #include <clipp.h>
  39. int main(int argc, char* argv[])
  40. {
  41. using namespace clipp;
  42. using std::string;
  43. using std::vector;
  44. using std::cout;
  45. int x = 0, y = 0;
  46. float speed = 10.0f;
  47. bool drift = true;
  48. vector<string> names;
  49. enum class mode { none, help, shipnew, shipmove, shipshoot, mineset, minerem};
  50. mode selected = mode::none;
  51. auto coordinates = ( value("x", x), value("y", y) );
  52. auto shipnew = ( command("new").set(selected,mode::shipnew),
  53. values("name", names) );
  54. auto shipmove = (
  55. value("name", names),
  56. command("move").set(selected,mode::shipmove), coordinates,
  57. (option("--speed=") & value("kn",speed)) % "Speed in knots [default: 10]");
  58. auto shipshoot = ( command("shoot").set(selected,mode::shipshoot),
  59. coordinates );
  60. auto mines = (
  61. command("mine"),
  62. (command("set" ).set(selected,mode::mineset) |
  63. command("remove").set(selected,mode::minerem) ),
  64. coordinates,
  65. (option("--moored" ).set(drift,false) % "Moored (anchored) mine." |
  66. option("--drifting").set(drift,true) % "Drifting mine." )
  67. );
  68. auto navalcli = (
  69. ( command("ship"), ( shipnew | shipmove | shipshoot ) )
  70. | mines
  71. | command("-h", "--help").set(selected,mode::help) % "Show this screen."
  72. | command("--version")([]{ cout << "version 1.0\n"; }) % "Show version."
  73. );
  74. auto fmt = doc_formatting{}
  75. .first_column(2)
  76. .doc_column(20)
  77. .max_flags_per_param_in_usage(8);
  78. if(parse(argc, argv, navalcli)) {
  79. switch(selected) {
  80. default:
  81. case mode::none:
  82. break;
  83. case mode::help: {
  84. cout << "Naval Fate.\n\nUsage:\n"
  85. << usage_lines(navalcli, "naval_fate", fmt)
  86. << "\n\nOptions:\n"
  87. << documentation(navalcli, fmt) << '\n';
  88. }
  89. break;
  90. case mode::shipnew:
  91. if(names.empty()) {
  92. cout << "No new ships were made\n";
  93. } else {
  94. cout << "Made new ship" << (names.size() > 1 ? "s " : " ");
  95. for(const auto& n : names) cout << n << ' ';
  96. cout << "\n";
  97. }
  98. break;
  99. case mode::shipmove:
  100. if(names.empty()) {
  101. cout << "No ship was moved.\n";
  102. } else {
  103. cout << "Moving ship " << names.front()
  104. << " to x=" << x << " y=" << y << ".\n";
  105. }
  106. break;
  107. case mode::shipshoot:
  108. cout << "Ship fired shot aimed at x=" << x << " y=" << y << ".\n";
  109. break;
  110. case mode::mineset:
  111. cout << "Laid " << (drift ? "drifting" : "& moored")
  112. << " mine at x=" << x << " y=" << y << ".\n";
  113. break;
  114. case mode::minerem:
  115. cout << "Removed mine at x=" << x << " y=" << y << ".\n";
  116. break;
  117. }
  118. }
  119. else {
  120. std::cerr << "Wrong command line arguments.\nUsage:"
  121. << usage_lines(navalcli, "naval_fate", fmt) << '\n';
  122. }
  123. }