Line data Source code
1 : /**
2 : * Copyright Soramitsu Co., Ltd. All Rights Reserved.
3 : * SPDX-License-Identifier: Apache-2.0
4 : */
5 : #include <numeric>
6 : #include <utility>
7 :
8 : #include "common/bind.hpp"
9 : #include "interactive/interactive_common_cli.hpp"
10 : #include "parser/parser.hpp"
11 :
12 : namespace iroha_cli {
13 : namespace interactive {
14 :
15 : DescriptionMap getCommonDescriptionMap() {
16 0 : return {
17 : // commonDescriptionMap
18 0 : {SAVE_CODE, "Save as json file"},
19 0 : {SEND_CODE, "Send to Iroha peer"}
20 : // commonDescriptionMap
21 : };
22 0 : }
23 :
24 : ParamsMap getCommonParamsMap(const std::string &default_ip,
25 : int default_port) {
26 0 : return {
27 : // commonParamsMap
28 0 : {SAVE_CODE, makeParamsDescription({"Path to save json file"})},
29 0 : {SEND_CODE,
30 0 : {ParamData({"Peer address", default_ip}),
31 0 : ParamData({"Peer port", std::to_string(default_port)})}}
32 : // commonParamsMap
33 : };
34 0 : }
35 :
36 : ParamsDescription makeParamsDescription(
37 : const std::vector<std::string> ¶ms) {
38 0 : return std::accumulate(params.begin(),
39 0 : params.end(),
40 0 : ParamsDescription{},
41 : [](auto &&acc, auto &el) {
42 0 : acc.push_back(ParamData({el, {}}));
43 0 : return std::forward<decltype(acc)>(acc);
44 0 : });
45 0 : }
46 :
47 : void handleEmptyCommand() {
48 0 : std::cout << "Put not empty command" << std::endl;
49 0 : }
50 :
51 : void handleUnknownCommand(std::string &command) {
52 0 : std::cout << "Command not found: " << command << std::endl;
53 0 : }
54 :
55 : void addBackOption(MenuPoints &menu) {
56 0 : menu.push_back("0. Back (" + BACK_CODE + ")");
57 0 : }
58 :
59 : bool isBackOption(std::string line) {
60 0 : auto command = parser::parseFirstCommand(std::move(line));
61 0 : return command and (*command == "0" or *command == BACK_CODE);
62 0 : }
63 :
64 : void printCommandParameters(std::string &command,
65 : const ParamsDescription ¶meters) {
66 0 : std::cout << "Run " << command
67 0 : << " with following parameters: " << std::endl;
68 : std::for_each(parameters.begin(), parameters.end(), [](auto el) {
69 0 : std::cout << " " << el.message << std::endl;
70 0 : });
71 0 : }
72 :
73 : void printMenu(const std::string &message, MenuPoints menu_points) {
74 0 : std::cout << message << std::endl;
75 : std::for_each(menu_points.begin(), menu_points.end(), [](auto el) {
76 0 : std::cout << el << std::endl;
77 0 : });
78 0 : }
79 :
80 : boost::optional<std::string> promptString(const std::string &message) {
81 0 : std::string line;
82 0 : std::cout << message << ": ";
83 0 : if (not std::getline(std::cin, line)) {
84 : // Input is a terminating symbol
85 0 : return boost::none;
86 : }
87 0 : return line;
88 0 : }
89 :
90 : boost::optional<std::string> promptString(const ParamData ¶m) {
91 0 : std::string message = param.message;
92 0 : if (not param.cache.empty()) {
93 0 : message += " (" + param.cache + ")";
94 0 : }
95 0 : return promptString(message);
96 0 : }
97 :
98 : void printEnd() {
99 0 : std::cout << "--------------------" << std::endl;
100 0 : }
101 :
102 : boost::optional<std::pair<std::string, uint16_t>> parseIrohaPeerParams(
103 : std::vector<std::string> params,
104 : const std::string &default_ip,
105 : int default_port) {
106 0 : const auto &address = params[0].empty() ? default_ip : params[0];
107 0 : auto port = params[1].empty() ? default_port
108 0 : : parser::parseValue<uint16_t>(params[1]);
109 0 : if (not params.empty() and not port) {
110 0 : std::cout << "Port has wrong format" << std::endl;
111 : // Continue parsing
112 0 : return boost::none;
113 : }
114 0 : return std::make_pair(address, *port);
115 0 : }
116 :
117 : boost::optional<std::vector<std::string>> parseParams(
118 : std::string line, std::string command_name, ParamsMap ¶ms_map) {
119 0 : auto params_description = findInHandlerMap(command_name, params_map);
120 0 : if (not params_description) {
121 : // Report no params where found for this command
122 0 : std::cout << "Command params not found" << std::endl;
123 : // Stop parsing, something is not implemented
124 0 : return boost::none;
125 : }
126 0 : auto words = parser::split(std::move(line));
127 0 : if (words.size() == 1) {
128 : // Start interactive mode
129 0 : std::vector<std::string> params;
130 0 : std::for_each(params_description.value().begin(),
131 0 : params_description.value().end(),
132 : [¶ms](auto ¶m) {
133 : using namespace iroha;
134 : promptString(param) | [&](auto &&val) {
135 0 : if (not val.empty()) {
136 : // Update input cache
137 0 : param.cache = val;
138 0 : params.push_back(val);
139 0 : } else if (not param.cache.empty()) {
140 : // Input cache is not empty, use cached value
141 0 : params.push_back(param.cache);
142 0 : }
143 0 : };
144 0 : });
145 0 : if (params.size() != params_description.value().size()) {
146 : // Wrong params passed
147 0 : return boost::none;
148 : }
149 0 : return params;
150 0 : } else if (words.size() != params_description.value().size() + 1) {
151 : // Not enough parameters passed
152 0 : printCommandParameters(command_name, params_description.value());
153 0 : return boost::none;
154 : } else {
155 : // Remove command name, return parameters
156 0 : words.erase(words.begin());
157 0 : return words;
158 : }
159 0 : }
160 :
161 : size_t addMenuPoint(std::vector<std::string> &menu_points,
162 : const std::string &description,
163 : const std::string &command_short_name) {
164 0 : menu_points.push_back(std::to_string(menu_points.size() + 1) + ". "
165 0 : + description + " (" + command_short_name + ")");
166 0 : return menu_points.size();
167 0 : }
168 : } // namespace interactive
169 : } // namespace iroha_cli
|