command-parser.cpp
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
26 #include "command-parser.hpp"
27 #include "format-helpers.hpp"
28 #include <ndn-cxx/util/logger.hpp>
29 
30 namespace nfd {
31 namespace tools {
32 namespace nfdc {
33 
34 NDN_LOG_INIT(nfdc.CommandParser);
35 
36 static_assert(std::is_same<std::underlying_type<AvailableIn>::type,
37  std::underlying_type<ParseMode>::type>::value,
38  "AvailableIn and ParseMode must be declared with same underlying type");
39 
40 std::ostream&
41 operator<<(std::ostream& os, AvailableIn modes)
42 {
43  text::Separator sep("|");
44  if ((modes & AVAILABLE_IN_ONE_SHOT) != 0) {
45  os << sep << "one-shot";
46  }
47  if ((modes & AVAILABLE_IN_BATCH) != 0) {
48  os << sep << "batch";
49  }
50 
51  if (sep.getCount() == 0) {
52  os << "none";
53  }
54  return os;
55 }
56 
57 std::ostream&
58 operator<<(std::ostream& os, ParseMode mode)
59 {
60  switch (mode) {
62  return os << "one-shot";
63  case ParseMode::BATCH:
64  return os << "batch";
65  }
66  return os << static_cast<int>(mode);
67 }
68 
69 CommandParser&
71  std::underlying_type<AvailableIn>::type modes)
72 {
73  BOOST_ASSERT(modes != AVAILABLE_IN_NONE);
74  m_commands[{def.getNoun(), def.getVerb()}].reset(
75  new Command{def, execute, static_cast<AvailableIn>(modes)});
76  return *this;
77 }
78 
80 CommandParser::addAlias(const std::string& noun, const std::string& verb, const std::string& verb2)
81 {
82  m_commands[{noun, verb2}] = m_commands.at({noun, verb});
83  return *this;
84 }
85 
86 std::tuple<std::string, std::string, CommandArguments, ExecuteCommand>
87 CommandParser::parse(const std::vector<std::string>& tokens, ParseMode mode) const
88 {
89  BOOST_ASSERT(mode == ParseMode::ONE_SHOT);
90 
91  const std::string& noun = tokens.size() > 0 ? tokens[0] : "";
92  const std::string& verb = tokens.size() > 1 ? tokens[1] : "";
93  size_t nameLen = std::min<size_t>(2, tokens.size());
94 
95  auto i = m_commands.find({noun, verb});
96  if (i == m_commands.end()) {
97  if (verb.empty()) {
98  i = m_commands.find({noun, "list"});
99  }
100  else {
101  // help, exit, quit, legacy nfdc commands
102  i = m_commands.find({noun, ""});
103  }
104  nameLen = std::min<size_t>(1, tokens.size());
105  }
106  if (i == m_commands.end() || (i->second->modes & static_cast<AvailableIn>(mode)) == 0) {
107  BOOST_THROW_EXCEPTION(Error("no such command: " + noun + " " + verb));
108  }
109 
110  const CommandDefinition& def = i->second->def;
111  NDN_LOG_TRACE("found command " << def.getNoun() << " " << def.getVerb());
112 
113  return std::make_tuple(def.getNoun(), def.getVerb(), def.parse(tokens, nameLen), i->second->execute);
114 }
115 
116 } // namespace nfdc
117 } // namespace tools
118 } // namespace nfd
declares semantics of a command
NDN_LOG_INIT(nfdc.CommandDefinition)
std::ostream & operator<<(std::ostream &os, ArgValueType vt)
Copyright (c) 2014-2015, Regents of the University of California, Arizona Board of Regents...
Definition: algorithm.hpp:32
ParseMode
indicates which mode is the parser operated in
std::function< int(ExecuteContext &ctx)> ExecuteCommand
a function to execute a command
CommandParser & addCommand(const CommandDefinition &def, const ExecuteCommand &execute, std::underlying_type< AvailableIn >::type modes=AVAILABLE_IN_ALL)
add an available command
AvailableIn
indicates which modes is a command allowed
std::tuple< std::string, std::string, CommandArguments, ExecuteCommand > parse(const std::vector< std::string > &tokens, ParseMode mode) const
parse a command line
CommandArguments parse(const std::vector< std::string > &tokens, size_t start=0) const
parse a command line
CommandParser & addAlias(const std::string &noun, const std::string &verb, const std::string &verb2)
add an alias "noun verb2" to existing command "noun verb"
print different string on first and subsequent usage