1 /**
2 * @file bindings/cli/print_help.cpp
3 * @author Matthew Amidon
4 * @author Ryan Curtin
5 *
6 * Print help for a given function.
7 *
8 * mlpack is free software; you may redistribute it and/or modify it under the
9 * terms of the 3-clause BSD license. You should have received a copy of the
10 * 3-clause BSD license along with mlpack. If not, see
11 * http://www.opensource.org/licenses/BSD-3-Clause for more information.
12 */
13 #include "print_help.hpp"
14
15 #include <mlpack/core.hpp>
16 #include <mlpack/core/util/hyphenate_string.hpp>
17
18 namespace mlpack {
19 namespace bindings {
20 namespace cli {
21
22 /* Prints the descriptions of the current hierarchy. */
PrintHelp(const std::string & param)23 void PrintHelp(const std::string& param)
24 {
25 std::string usedParam = param;
26 std::map<std::string, util::ParamData>& parameters = IO::Parameters();
27 const std::map<char, std::string>& aliases = IO::Aliases();
28 util::BindingDetails& bindingDetails = IO::GetSingleton().doc;
29 // If we pass a single param, alias it if necessary.
30 if (usedParam.length() == 1 && aliases.count(usedParam[0]))
31 usedParam = aliases.at(usedParam[0]);
32
33 // Do we only want to print out one value?
34 if (usedParam != "" && parameters.count(usedParam))
35 {
36 util::ParamData& data = parameters.at(usedParam);
37 std::string alias = (data.alias != '\0') ? " (-"
38 + std::string(1, data.alias) + ")" : "";
39
40 // Figure out the name of the type.
41 std::string printableType;
42 IO::GetSingleton().functionMap[data.tname]["StringTypeParam"](data, NULL,
43 (void*) &printableType);
44 std::string type = " [" + printableType + "]";
45
46 // Now, print the descriptions.
47 std::string fullDesc = " --" + usedParam + alias + type + " ";
48
49 if (fullDesc.length() <= 32) // It all fits on one line.
50 std::cout << fullDesc << std::string(32 - fullDesc.length(), ' ');
51 else // We need multiple lines.
52 std::cout << fullDesc << std::endl << std::string(32, ' ');
53
54 std::cout << util::HyphenateString(data.desc, 32) << std::endl;
55 return;
56 }
57 else if (usedParam != "")
58 {
59 // User passed a single variable, but it doesn't exist.
60 std::cerr << "Parameter --" << usedParam << " does not exist."
61 << std::endl;
62 exit(1); // Nothing left to do.
63 }
64
65 // Print out the descriptions.
66 if (bindingDetails.programName != "")
67 {
68 std::cout << bindingDetails.programName << std::endl << std::endl;
69 std::cout << " " << util::HyphenateString(bindingDetails.longDescription(),
70 2) << std::endl << std::endl;
71 for (size_t j = 0; j < bindingDetails.example.size(); ++j)
72 {
73 std::cout << " " << util::HyphenateString(bindingDetails.example[j](), 2)
74 << std::endl << std::endl;
75 }
76 }
77 else
78 std::cout << "[undocumented program]" << std::endl << std::endl;
79
80 for (size_t pass = 0; pass < 3; ++pass)
81 {
82 bool printedHeader = false;
83 // Print out the descriptions of everything else.
84 for (auto& iter : parameters)
85 {
86 util::ParamData& data = iter.second;
87 const std::string key;
88 IO::GetSingleton().functionMap[data.tname]["MapParameterName"](data,
89 NULL, (void*) &key);
90
91 std::string desc = data.desc;
92 std::string alias = (iter.second.alias != '\0') ?
93 std::string(1, iter.second.alias) : "";
94 alias = alias.length() ? " (-" + alias + ")" : alias;
95
96 // Filter un-printed options.
97 if ((pass == 0) && !(data.required && data.input)) // Required input.
98 continue;
99 if ((pass == 1) && !(!data.required && data.input)) // Optional input.
100 continue;
101 if ((pass == 2) && data.input) // Output options only (always optional).
102 continue;
103
104 // For reverse compatibility: this can be removed when these options are
105 // gone in mlpack 3.0.0. We don't want to print the deprecated options.
106 if (data.name == "inputFile")
107 continue;
108
109 if (!printedHeader)
110 {
111 printedHeader = true;
112 if (pass == 0)
113 std::cout << "Required input options:" << std::endl << std::endl;
114 else if (pass == 1)
115 std::cout << "Optional input options: " << std::endl << std::endl;
116 else if (pass == 2)
117 std::cout << "Optional output options: " << std::endl << std::endl;
118 }
119
120 // Append default value to description.
121 if (pass >= 1 && (data.cppType == "int" || data.cppType == "double" ||
122 data.cppType == "std::string" ||
123 data.cppType == "std::vector<int>" ||
124 data.cppType == "std::vector<double>" ||
125 data.cppType == "std::vector<std::string>"))
126 {
127 std::string defaultValue;
128 IO::GetSingleton().functionMap[data.tname]["DefaultParam"](data,
129 NULL, (void*) &defaultValue);
130 desc += " Default value " + defaultValue + ".";
131 }
132
133 // Now, print the descriptions.
134 std::string printableType;
135 IO::GetSingleton().functionMap[data.tname]["StringTypeParam"](data,
136 NULL, (void*) &printableType);
137 std::string type = " [" + printableType + "]";
138 std::string fullDesc = " --" + key + alias + type + " ";
139
140 if (fullDesc.length() <= 32) // It all fits on one line.
141 std::cout << fullDesc << std::string(32 - fullDesc.length(), ' ');
142 else // We need multiple lines.
143 std::cout << fullDesc << std::endl << std::string(32, ' ');
144
145 std::cout << util::HyphenateString(desc, 32) << std::endl;
146 }
147
148 if (printedHeader)
149 std::cout << std::endl;
150 }
151
152 // Helpful information at the bottom of the help output, to point the user to
153 // citations and better documentation (if necessary). See ticket #195.
154 std::cout << util::HyphenateString("For further information, including "
155 "relevant papers, citations, and theory, consult the documentation found "
156 "at http://www.mlpack.org or included with your distribution of mlpack.",
157 0) << std::endl;
158 }
159
160
161 } // namespace cli
162 } // namespace bindings
163 } // namespace mlpack
164