]> git.proxmox.com Git - ceph.git/blame - ceph/src/tools/rbd/OptionPrinter.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / tools / rbd / OptionPrinter.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#include "tools/rbd/OptionPrinter.h"
5#include "tools/rbd/IndentStream.h"
20effc67 6#include "include/ceph_assert.h"
7c673cae
FG
7
8namespace rbd {
9
10namespace po = boost::program_options;
11
12const std::string OptionPrinter::POSITIONAL_ARGUMENTS("Positional arguments");
13const std::string OptionPrinter::OPTIONAL_ARGUMENTS("Optional arguments");
14
15const size_t OptionPrinter::MAX_DESCRIPTION_OFFSET;
16
17OptionPrinter::OptionPrinter(const OptionsDescription &positional,
18 const OptionsDescription &optional)
19 : m_positional(positional), m_optional(optional) {
20}
21
22void OptionPrinter::print_short(std::ostream &os, size_t initial_offset) {
f67539c2
TL
23 size_t max_option_width = 0;
24 std::vector<std::string> optionals;
7c673cae 25 for (size_t i = 0; i < m_optional.options().size(); ++i) {
f67539c2
TL
26 std::stringstream option;
27
7c673cae
FG
28 bool required = m_optional.options()[i]->semantic()->is_required();
29 if (!required) {
f67539c2 30 option << "[";
7c673cae 31 }
f67539c2 32 option << "--" << m_optional.options()[i]->long_name();
7c673cae 33 if (m_optional.options()[i]->semantic()->max_tokens() != 0) {
f67539c2 34 option << " <" << m_optional.options()[i]->long_name() << ">";
7c673cae
FG
35 }
36 if (!required) {
f67539c2
TL
37 option << "]";
38 }
39 max_option_width = std::max(max_option_width, option.str().size());
40 optionals.emplace_back(option.str());
41 }
42
43 std::vector<std::string> positionals;
44 for (size_t i = 0; i < m_positional.options().size(); ++i) {
45 std::stringstream option;
46
20effc67
TL
47 // we overload po::value<std::string>()->default_value("") to signify
48 // an optional positional argument (purely for help printing purposes)
49 boost::any v;
50 bool required = !m_positional.options()[i]->semantic()->apply_default(v);
51 if (!required) {
52 auto ptr = boost::any_cast<std::string>(&v);
53 ceph_assert(ptr && ptr->empty());
54 option << "[";
55 }
f67539c2
TL
56 option << "<" << m_positional.options()[i]->long_name() << ">";
57 if (m_positional.options()[i]->semantic()->max_tokens() > 1) {
58 option << " [<" << m_positional.options()[i]->long_name() << "> ...]";
7c673cae 59 }
20effc67
TL
60 if (!required) {
61 option << "]";
62 }
f67539c2
TL
63
64 max_option_width = std::max(max_option_width, option.str().size());
65 positionals.emplace_back(option.str());
66
67 if (m_positional.options()[i]->semantic()->max_tokens() > 1) {
68 break;
69 }
70 }
71
72 size_t indent = std::min(initial_offset, MAX_DESCRIPTION_OFFSET) + 1;
73 if (indent + max_option_width + 2 > LINE_WIDTH) {
74 // decrease the indent so that we don't wrap past the end of the line
75 indent = LINE_WIDTH - max_option_width - 2;
76 }
77
78 IndentStream indent_stream(indent, initial_offset, LINE_WIDTH, os);
79 indent_stream.set_delimiter("[");
80 for (auto& option : optionals) {
81 indent_stream << option << " ";
7c673cae 82 }
11fdf7f2 83
f67539c2 84 if (optionals.size() > 0 || positionals.size() == 0) {
11fdf7f2
TL
85 indent_stream << std::endl;
86 }
7c673cae 87
f67539c2 88 if (positionals.size() > 0) {
7c673cae 89 indent_stream.set_delimiter(" ");
f67539c2
TL
90 for (auto& option : positionals) {
91 indent_stream << option << " ";
7c673cae
FG
92 }
93 indent_stream << std::endl;
94 }
95}
96
f67539c2
TL
97void OptionPrinter::print_optional(const OptionsDescription &global_opts,
98 size_t &name_width, std::ostream &os) {
99 std::string indent2(2, ' ');
100
101 for (size_t i = 0; i < global_opts.options().size(); ++i) {
102 std::string description = global_opts.options()[i]->description();
103 auto result = boost::find_first(description, "deprecated");
104 if (!result.empty()) {
105 continue;
106 }
107 std::stringstream ss;
108 ss << indent2
109 << global_opts.options()[i]->format_name() << " "
110 << global_opts.options()[i]->format_parameter();
111
112 std::cout << ss.str();
113 IndentStream indent_stream(name_width, ss.str().size(), LINE_WIDTH, std::cout);
114 indent_stream << global_opts.options()[i]->description() << std::endl;
115 }
116
117}
118
7c673cae
FG
119void OptionPrinter::print_detailed(std::ostream &os) {
120 std::string indent_prefix(2, ' ');
121 size_t name_width = compute_name_width(indent_prefix.size());
122
123 if (m_positional.options().size() > 0) {
124 std::cout << POSITIONAL_ARGUMENTS << std::endl;
125 for (size_t i = 0; i < m_positional.options().size(); ++i) {
126 std::stringstream ss;
127 ss << indent_prefix << "<" << m_positional.options()[i]->long_name()
128 << ">";
129
130 std::cout << ss.str();
131 IndentStream indent_stream(name_width, ss.str().size(), LINE_WIDTH, os);
132 indent_stream << m_positional.options()[i]->description() << std::endl;
133 }
134 std::cout << std::endl;
135 }
136
137 if (m_optional.options().size() > 0) {
138 std::cout << OPTIONAL_ARGUMENTS << std::endl;
f67539c2 139 print_optional(m_optional, name_width, os);
7c673cae
FG
140 std::cout << std::endl;
141 }
142}
143
144size_t OptionPrinter::compute_name_width(size_t indent) {
145 size_t width = MIN_NAME_WIDTH;
146 std::vector<OptionsDescription> descs = {m_positional, m_optional};
147 for (size_t desc_idx = 0; desc_idx < descs.size(); ++desc_idx) {
148 const OptionsDescription &desc = descs[desc_idx];
149 for (size_t opt_idx = 0; opt_idx < desc.options().size(); ++opt_idx) {
150 size_t name_width = desc.options()[opt_idx]->format_name().size() +
151 desc.options()[opt_idx]->format_parameter().size()
152 + 1;
153 width = std::max(width, name_width);
154 }
155 }
156 width += indent;
157 width = std::min(width, MAX_DESCRIPTION_OFFSET) + 1;
158 return width;
159}
160
161} // namespace rbd