]>
git.proxmox.com Git - ceph.git/blob - ceph/src/tools/rbd/OptionPrinter.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "tools/rbd/OptionPrinter.h"
5 #include "tools/rbd/IndentStream.h"
6 #include "include/ceph_assert.h"
10 namespace po
= boost::program_options
;
12 const std::string
OptionPrinter::POSITIONAL_ARGUMENTS("Positional arguments");
13 const std::string
OptionPrinter::OPTIONAL_ARGUMENTS("Optional arguments");
15 const size_t OptionPrinter::MAX_DESCRIPTION_OFFSET
;
17 OptionPrinter::OptionPrinter(const OptionsDescription
&positional
,
18 const OptionsDescription
&optional
)
19 : m_positional(positional
), m_optional(optional
) {
22 void OptionPrinter::print_short(std::ostream
&os
, size_t initial_offset
) {
23 size_t max_option_width
= 0;
24 std::vector
<std::string
> optionals
;
25 for (size_t i
= 0; i
< m_optional
.options().size(); ++i
) {
26 std::stringstream option
;
28 bool required
= m_optional
.options()[i
]->semantic()->is_required();
32 option
<< "--" << m_optional
.options()[i
]->long_name();
33 if (m_optional
.options()[i
]->semantic()->max_tokens() != 0) {
34 option
<< " <" << m_optional
.options()[i
]->long_name() << ">";
39 max_option_width
= std::max(max_option_width
, option
.str().size());
40 optionals
.emplace_back(option
.str());
43 std::vector
<std::string
> positionals
;
44 for (size_t i
= 0; i
< m_positional
.options().size(); ++i
) {
45 std::stringstream option
;
47 // we overload po::value<std::string>()->default_value("") to signify
48 // an optional positional argument (purely for help printing purposes)
50 bool required
= !m_positional
.options()[i
]->semantic()->apply_default(v
);
52 auto ptr
= boost::any_cast
<std::string
>(&v
);
53 ceph_assert(ptr
&& ptr
->empty());
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() << "> ...]";
64 max_option_width
= std::max(max_option_width
, option
.str().size());
65 positionals
.emplace_back(option
.str());
67 if (m_positional
.options()[i
]->semantic()->max_tokens() > 1) {
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;
78 IndentStream
indent_stream(indent
, initial_offset
, LINE_WIDTH
, os
);
79 indent_stream
.set_delimiter("[");
80 for (auto& option
: optionals
) {
81 indent_stream
<< option
<< " ";
84 if (optionals
.size() > 0 || positionals
.size() == 0) {
85 indent_stream
<< std::endl
;
88 if (positionals
.size() > 0) {
89 indent_stream
.set_delimiter(" ");
90 for (auto& option
: positionals
) {
91 indent_stream
<< option
<< " ";
93 indent_stream
<< std::endl
;
97 void OptionPrinter::print_optional(const OptionsDescription
&global_opts
,
98 size_t &name_width
, std::ostream
&os
) {
99 std::string
indent2(2, ' ');
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()) {
107 std::stringstream ss
;
109 << global_opts
.options()[i
]->format_name() << " "
110 << global_opts
.options()[i
]->format_parameter();
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
;
119 void OptionPrinter::print_detailed(std::ostream
&os
) {
120 std::string
indent_prefix(2, ' ');
121 size_t name_width
= compute_name_width(indent_prefix
.size());
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()
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
;
134 std::cout
<< std::endl
;
137 if (m_optional
.options().size() > 0) {
138 std::cout
<< OPTIONAL_ARGUMENTS
<< std::endl
;
139 print_optional(m_optional
, name_width
, os
);
140 std::cout
<< std::endl
;
144 size_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()
153 width
= std::max(width
, name_width
);
157 width
= std::min(width
, MAX_DESCRIPTION_OFFSET
) + 1;