params.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /**
  2. * params.cpp for jsonstroller
  3. *
  4. * Author: isundil <isundill@gmail.com>
  5. **/
  6. #include <fstream>
  7. #include <iostream>
  8. #include <sstream>
  9. #include <curses.h>
  10. #include <unistd.h>
  11. #include "diffCmd.hh"
  12. #include "params.hh"
  13. #include "config.h"
  14. Params::Params(char **av): progName(*av), strict(true), diffMode(false), diffCmd(nullptr)
  15. {
  16. av++;
  17. while (*av)
  18. {
  19. params.push_back(*av);
  20. av++;
  21. }
  22. }
  23. Params::~Params()
  24. {
  25. for (std::pair<std::string, std::basic_istream<char>*> in : inputs)
  26. delete in.second;
  27. if (diffCmd)
  28. delete diffCmd;
  29. }
  30. bool Params::read()
  31. {
  32. bool written = false,
  33. inDiff = false;
  34. std::stringstream *input = nullptr;
  35. ignoreUnicode = false;
  36. colorMode = sorted = true;
  37. compressMode = false;
  38. for (std::list<std::string>::const_iterator i = params.cbegin(); i != params.cend(); i++)
  39. {
  40. std::string tmp(*i);
  41. if (!input && !inDiff)
  42. {
  43. if (tmp == "--")
  44. inputs["ARGS"] = input = new std::stringstream();
  45. else if (tmp == "-W")
  46. strict = false;
  47. else if (tmp == "--ascii")
  48. ignoreUnicode = true;
  49. else if (tmp == "--color")
  50. colorMode = true;
  51. else if (tmp == "--diff")
  52. diffMode = true;
  53. else if (tmp == "--compress")
  54. compressMode = true;
  55. else if (tmp == "--help" || tmp == "-h")
  56. {
  57. usage();
  58. return false;
  59. }
  60. else if (tmp == "--version" || tmp == "-v")
  61. {
  62. version();
  63. return false;
  64. }
  65. else if (tmp == "--keep-order")
  66. sorted = false;
  67. else if (tmp == "--diff-cmd")
  68. {
  69. if (diffCmd)
  70. throw std::runtime_error("Invalid double usage of --diff-cmd");
  71. inDiff = true;
  72. diffCmd = new DiffCmd();
  73. }
  74. else if (tmp.find("--color=") == 0)
  75. {
  76. std::string mode = tmp.substr(8);
  77. if (mode == "always")
  78. colorMode = true;
  79. else if (mode == "never")
  80. colorMode = false;
  81. else
  82. throw std::runtime_error("Invalid option for --color: " +mode);
  83. }
  84. else if (tmp.find("-") == 0)
  85. throw std::runtime_error("Invalid argument: " +tmp);
  86. else
  87. {
  88. std::ifstream *in = new std::ifstream(tmp);
  89. if (!in->is_open())
  90. {
  91. delete in;
  92. throw std::runtime_error("Cannot open " +tmp +" for reading");
  93. }
  94. if (inputs.contains(tmp))
  95. {
  96. delete in;
  97. throw std::runtime_error("Cannot compare " +tmp +" and " +tmp +" files (path are identical)");
  98. }
  99. else
  100. inputs[tmp] = in;
  101. }
  102. }
  103. else if (inDiff)
  104. {
  105. if (tmp == ";")
  106. inDiff = false;
  107. else
  108. diffCmd->add(tmp);
  109. }
  110. else
  111. {
  112. if (written)
  113. input->write(" ", sizeof(char));
  114. else
  115. written = true;
  116. input->write(tmp.c_str(), sizeof(char) * tmp.size());
  117. }
  118. }
  119. if (diffMode)
  120. {
  121. if (inputs.size() > 3)
  122. {
  123. std::cerr << progName << ": more than 3 files to compare" << std::endl;
  124. usage();
  125. return false;
  126. }
  127. if (inputs.size() < 2)
  128. {
  129. std::cerr << progName << ": not enough files to compare" << std::endl;
  130. usage();
  131. return false;
  132. }
  133. }
  134. return true;
  135. }
  136. IndexedDeque Params::getInputs() const
  137. {
  138. if (!inputs.empty())
  139. return inputs;
  140. IndexedDeque result;
  141. result["STDIN"] = &std::cin;
  142. return result;
  143. }
  144. void Params::usage() const noexcept
  145. {
  146. std::cout << "Usage: "
  147. << progName << " [OPTIONS]" << std::endl
  148. << "or: " << progName << " [OPTIONS] FILENAME" << std::endl
  149. << "or: " << progName << " [OPTIONS] -- INPUT" << std::endl
  150. << "or: " << progName << " --diff [OPTIONS] FILENAME FILENAME [FILENAME]" << std::endl
  151. << "Read json input and print it using ncurse" << std::endl << std::endl
  152. << "if not INPUT nor FILENAME, use standard input" << std::endl << std::endl
  153. << "When output is redirected to a file or another command, output will be prettyfied unless --compress" << std::endl << std::endl
  154. << " FILENAME\t\tread input from filename instead of stdin" << std::endl
  155. << " INPUT\t\t\tuse this as input instead of stdin" << std::endl
  156. << " -W \t\t\tconsider continuing on non-blocking errors" << std::endl
  157. << " --ascii\t\tignore unicode values" << std::endl
  158. << " --keep-order\t\tdo not sort objects by key" << std::endl
  159. << " --color[=MODE]\tcolorize output, MODE can be never or always (default when ommited)" << std::endl
  160. << " --compress\tif output is redirected, strip unnecessaries characters" << std::endl
  161. << " --diff-cmd COMMAND ;\tExecute command as external diff. All following argument will be passed as parameter to COMMAND until ';' is encountered. The '{}' argument will be replaced by the file path of the prettified input" << std::endl
  162. << " -v, -version\t\tdisplay version information" << std::endl
  163. << " -h, --helph\t\tshow this message and exit" << std::endl << std::endl
  164. << "Examples:" << std::endl
  165. << STROLL_PROGNAME << " f.json\tOutput f.json's content" << std::endl << std::endl
  166. << STROLL_PROGNAME << " --diff fileA.json fileB.json\tcompare fileA.json and fileB.json" << std::endl << std::endl
  167. << STROLL_PROGNAME << " --diff-cmd vimdiff {} ';' fileA.json fileB.json\tcompare fileA.json and fileB.json" << std::endl << std::endl
  168. << "Report bugs to <isundill@gmail.com>" << std::endl;
  169. }
  170. void Params::version() const noexcept
  171. {
  172. std::cout << STROLL_PROGNAME << " (jsonstroller suite) " << VERSION << " generated on " << VERSIONDATE << std::endl << std::endl
  173. << "Copyright (C) 2016 Free Software Foundation, Inc." << std::endl
  174. << "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>." << std::endl
  175. << "This is free software: you are free to change and redistribute it." << std::endl
  176. << "There is NO WARRANTY, to the extent permitted by law." << std::endl << std::endl
  177. << "Written by isundil <isundill@gmail.com>." << std::endl;
  178. }
  179. bool Params::isStrict() const
  180. { return strict; }
  181. bool Params::colorEnabled() const
  182. { return colorMode; }
  183. bool Params::sortObjects() const
  184. { return sorted; }
  185. bool Params::isIgnoringUnicode() const
  186. { return ignoreUnicode; }
  187. const std::string &Params::getProgName() const
  188. { return progName; }
  189. bool Params::compressed() const
  190. { return compressMode; }
  191. bool Params::isDiff() const
  192. { return diffMode; }
  193. DiffCmd *Params::getExternalDiff() const
  194. { return diffCmd; }