CASM  1.1.0
A Clusters Approach to Statistical Mechanics
info.cc
Go to the documentation of this file.
1 #include "casm/app/info.hh"
2 
3 #include <cstring>
4 
11 #include "casm/casm_io/Log.hh"
13 #include "casm/clex/PrimClex.hh"
15 
16 namespace CASM {
17 
18 namespace Completer {
20 
22  bool required = false;
23  add_settings_suboption(required);
24  add_input_suboption(required);
25 
26  // Standard options: --help, --desc, --settings, --input
27  m_desc.add_options()(
28 
29  "help,h",
30  "Print help message including a list of all available methods.")(
31 
32  "desc",
33  po::value<std::vector<std::string> >(&m_desc_vec)
34  ->multitoken()
35  ->zero_tokens()
36  ->value_name(ArgHandler::infomethod()),
37  "Print extended usage description. "
38  "Use '--desc [MethodName [MethodName2...]]' for detailed method "
39  "descriptions. Partial matches of method names are acceptable.")(
40 
41  "method,m",
42  po::value<std::string>(&m_method)->value_name(ArgHandler::infomethod()),
43  "Method to use: Can use method name (including partial matches) or "
44  "index.");
45 }
46 } // namespace Completer
47 } // namespace CASM
48 
49 namespace CASM {
50 // ///////////////////////////////////////
51 // 'sym' function for casm
52 // (add an 'if-else' statement in casm.cpp to call this)
53 
54 const std::string InfoCommand::name = "info";
55 
57  : APICommand<Completer::InfoOption>(_args, _opt),
58  m_info_method_vector(nullptr) {}
59 
61  if (vm().count("method") != 1) {
62  err_log() << "Error in 'casm info'. The --method option is required."
63  << std::endl;
64  return ERR_INVALID_ARG;
65  }
66 
67  if (vm().count("settings") + vm().count("input") == 2) {
68  err_log() << "Error in 'casm info'. The options --settings or --input may "
69  "not both be chosen."
70  << std::endl;
71  return ERR_INVALID_ARG;
72  }
73 
74  return 0;
75 }
76 
77 int InfoCommand::help() const {
78  log() << opt().desc() << std::endl;
80 
81  log() << "\nFor complete options description, use 'casm info --desc "
82  "MethodName'.\n\n";
83 
84  return 0;
85 }
86 
87 int InfoCommand::desc() const {
88  if (opt().desc_vec().size()) {
89  log() << "\n";
90 
91  bool match = false;
92  for (const auto &in_name : opt().desc_vec()) {
93  for (const auto &interface_ptr : info_methods()) {
94  if (interface_ptr->name().substr(0, in_name.size()) == in_name) {
95  log() << interface_ptr->desc() << std::endl;
96  match = true;
97  break;
98  }
99  }
100  }
101 
102  if (!match) {
103  log() << "No match found. ";
105  }
106 
107  return 0;
108  } else {
109  log() << "\n";
110  log() << opt().desc() << std::endl;
111 
112  log() << "DESCRIPTION\n" << std::endl;
113 
114  log() << " casm info --settings input.json \n"
115  " casm info --input '{...JSON...}' \n"
116  " - Input settings in JSON format. \n\n";
117 
119 
120  log() << "\nFor complete options help for a particular method, \n"
121  "use 'casm info --desc MethodName'.\n\n";
122 
123  // could provide help about plugins here
124 
125  return 0;
126  }
127 }
128 
129 int InfoCommand::run() const {
130  // Select and execute an info method from this->info_methods() based on
131  // --method value
132  // - accepts partial name matches if only one partial match
133  // - if no name match, attempt to interpret --method as index into
134  // this->info_methods()
135  // - otherwise provide a useful error message
136 
137  // JSON from --input string or --settings file
138  jsonParser json_options = make_json_input(opt());
139 
140  // find how many method names match the --method input value
141  auto method_name_matches =
142  [&](notstd::cloneable_ptr<InfoInterfaceBase> const &interface_ptr) {
143  return interface_ptr->name().substr(0, opt().method().size()) ==
144  opt().method();
145  };
146  int count = std::count_if(info_methods().begin(), info_methods().end(),
147  method_name_matches);
148 
149  PrimClex const *primclex_ptr = nullptr;
150  if (args().primclex) {
151  primclex_ptr = args().primclex;
152  }
153 
154  if (count == 1) {
155  auto it = std::find_if(info_methods().begin(), info_methods().end(),
156  method_name_matches);
157  (*it)->run(json_options, primclex_ptr);
158  return 0;
159 
160  } else if (count < 1) {
161  // Attempt to understand --method input as index into method list
162  int method_index = -1;
163  try {
164  method_index = stoi(opt().method());
165  } catch (...) {
166  err_log() << "No match found for --method " << opt().method()
167  << std::endl;
169  return ERR_INVALID_ARG;
170  }
171 
172  if (method_index < 0 || method_index >= info_methods().size()) {
173  err_log() << "No match found for --method " << opt().method()
174  << std::endl;
176  return ERR_INVALID_ARG;
177  }
178 
179  auto it = info_methods().begin();
180  std::advance(it, method_index);
181 
182  (*it)->run(json_options, primclex_ptr);
183  return 0;
184  } else if (count > 1) {
185  err_log() << "Multiple matches found for --method " << opt().method()
186  << std::endl;
188  return ERR_INVALID_ARG;
189  }
190  throw std::runtime_error("Unknown error in InfoCommand::run");
191 }
192 
194  if (m_info_method_vector == nullptr) {
195  // could add plugins here...
196 
199  }
200  return *m_info_method_vector;
201 }
202 
203 void InfoCommand::print_names(std::ostream &sout,
204  InfoInterfaceVector const &info_methods) const {
205  sout << "The `casm info` methods are:\n";
206  int counter = 0;
207  for (auto const &interface_ptr : info_methods) {
208  sout << " " << counter << ") " << interface_ptr->name() << std::endl;
209  ++counter;
210  }
211 }
212 
213 } // namespace CASM
#define ERR_INVALID_ARG
Definition: errors.hh:7
const CommandArgs & args() const
Definition: APICommand.cc:11
PrimClex & primclex() const
Definition: APICommand.cc:17
const OptionType & opt() const
Definition: APICommand.hh:61
const po::variables_map & vm() const
Definition: APICommand.hh:59
static std::string infomethod()
Get value_type string for infomethod mode completion.
Definition: Handlers.cc:90
void initialize() override
Fill in the options descriptions accordingly.
Definition: info.cc:21
std::string method() const
Definition: Handlers.hh:916
std::vector< std::string > m_desc_vec
Definition: Handlers.hh:921
void add_input_suboption(bool required=true)
Definition: Handlers.cc:610
const po::options_description & desc()
Get the program options, filled with the initialized values.
Definition: Handlers.cc:321
void add_settings_suboption(bool required=true)
Definition: Handlers.cc:588
po::options_description m_desc
Definition: Handlers.hh:260
int help() const override
Definition: info.cc:77
InfoInterfaceVector m_standard_info_methods
Definition: info.hh:60
int run() const override
Definition: info.cc:129
int vm_count_check() const override
Definition: info.cc:60
static const std::string name
Definition: info.hh:40
InfoInterfaceVector const & info_methods() const
Definition: info.cc:193
int desc() const override
Definition: info.cc:87
InfoCommand(const CommandArgs &_args, Completer::InfoOption &_opt)
Definition: info.cc:56
InfoInterfaceVector const * m_info_method_vector
Definition: info.hh:61
void print_names(std::ostream &sout, InfoInterfaceVector const &info_methods) const
Definition: info.cc:203
PrimClex is the top-level data structure for a CASM project.
Definition: PrimClex.hh:55
A 'cloneable_ptr' can be used in place of 'unique_ptr'.
Main CASM namespace.
Definition: APICommand.hh:8
Log & log()
Definition: Log.hh:424
InfoInterfaceVector make_standard_info_method_interfaces()
A vector containing casm info method interfaces.
std::vector< notstd::cloneable_ptr< InfoInterfaceBase > > InfoInterfaceVector
jsonParser make_json_input(const OptionType &opt)
Definition: json_io_impl.hh:11
Log & err_log()
Definition: Log.hh:426
Data structure holding basic CASM command info.