E-MailRelay
goptions.h
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2021 Graeme Walker <graeme_walker@users.sourceforge.net>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16// ===
17///
18/// \file goptions.h
19///
20
21#ifndef G_OPTIONS_H
22#define G_OPTIONS_H
23
24#include "gdef.h"
25#include "gstrings.h"
26#include "gexception.h"
27#include <string>
28#include <map>
29
30namespace G
31{
32 class Options ;
33 struct OptionsLayout ;
34}
35
36//| \class G::OptionsLayout
37/// Describes the layout for G::Options output.
38///
40{
41 std::string separator ; ///< separator between syntax and description
42 std::size_t column ; ///< left hand column width if no separator (includes margin)
43 std::size_t width ; ///< overall width for wrapping, or zero for none
44 std::size_t width2 ; ///< width after the first line, or zero for 'width'
45 std::size_t margin ; ///< spaces to the left of the syntax part
46 unsigned int level ; ///< show options at-or-below this level
47 bool level_exact ; ///< .. or exactly at that level
48 bool extra ; ///< include descriptions' extra text
49 bool alt_usage ; ///< use alternate "usage:" string
51 explicit OptionsLayout( std::size_t column ) ;
52 OptionsLayout( std::size_t column , std::size_t width ) ;
53 OptionsLayout & set_column( std::size_t ) ;
54 OptionsLayout & set_extra( bool = true ) ;
55 OptionsLayout & set_level( unsigned int ) ;
56 OptionsLayout & set_level_if( bool , unsigned int ) ;
57 OptionsLayout & set_level_exact( bool = true ) ;
58 OptionsLayout & set_alt_usage( bool = true ) ;
59} ;
60
61//| \class G::Options
62/// A class to represent allowed command-line options and to provide command-line
63/// usage text.
64///
66{
67public:
68 using Layout = OptionsLayout ;
69 G_EXCEPTION( InvalidSpecification , "invalid options specification string" ) ;
70
71 explicit Options( const std::string & spec , char sep_major = '|' , char sep_minor = '!' , char escape = '^' ) ;
72 ///< Constructor taking a specification string.
73 ///<
74 ///< Uses specifications like "p!port!defines the port number!!1!port!1|v!verbose!shows more logging!!0!!1"
75 ///< made up of (1) an optional single-character-option-letter, (2) a multi-character-option-name
76 ///< (3) an option-description, (4) optional option-description-extra text, (5) a value-type
77 ///< (with '0' for unvalued, '1' for a single value, '2' for a comma-separated list (possibly
78 ///< multiple times), or '01' for a defaultable single value) or (6) a value-description
79 ///< (unless unvalued), and (7) a level enumeration.
80 ///<
81 ///< By convention mainstream options should have a level of 1, and obscure ones level 2 and above.
82 ///< If the option-description field is empty or if the level is zero then the option is hidden.
83
85 ///< Default constructor for no options.
86
87 void add( StringArray ) ;
88 ///< Adds one component of the specification, broken down into its seven
89 ///< separate parts.
90
91 void add( StringArray , char sep , char escape = '\\' ) ;
92 ///< Adds one component of the specification broken down into six separate
93 ///< parts with fields 3 and 4 joined by the given separator character.
94
95 const StringArray & names() const ;
96 ///< Returns the sorted list of long-form option names.
97
98 std::string lookup( char c ) const ;
99 ///< Converts from short-form option character to the corresponding
100 ///< long-form name. Returns the empty string if none.
101
102 bool valid( const std::string & ) const ;
103 ///< Returns true if the long-form option name is valid.
104
105 bool visible( const std::string & name , unsigned int level , bool level_exact = false ) const ;
106 ///< Returns true if the option is visible at the given level.
107 ///< Deliberately hidden options at level zero are never
108 ///< visible(). Returns false if not a valid() name .
109
110 bool visible( const std::string & name ) const ;
111 ///< Returns true if the option is visible. Returns false if
112 ///< the option is hidden or the name is not valid().
113
114 bool valued( char ) const ;
115 ///< Returns true if the given short-form option takes a value,
116 ///< Returns true if the short-form option character is valued,
117 ///< including multivalued() and defaulting().
118 ///< Returns false if not valid().
119
120 bool valued( const std::string & ) const ;
121 ///< Returns true if the given long-form option takes a value,
122 ///< including multivalued() and defaulting(). Returns false
123 ///< if not valid().
124
125 bool multivalued( char ) const ;
126 ///< Returns true if the short-form option can have multiple values.
127 ///< Returns false if not valid().
128
129 bool multivalued( const std::string & ) const ;
130 ///< Returns true if the long-form option can have multiple values.
131 ///< Returns false if not valid().
132
133 bool unvalued( const std::string & ) const ;
134 ///< Returns true if the given option name is valid and
135 ///< takes no value. Returns false if not valid().
136
137 bool defaulting( const std::string & ) const ;
138 ///< Returns true if the given long-form single-valued() option
139 ///< can optionally have no explicit value, so "--foo=" and "--foo"
140 ///< are equivalent, having an empty value, and "--foo=bar" has
141 ///< a value of 'bar' but "--foo bar" is interpreted as 'foo'
142 ///< taking its default (empty) value followed by a separate
143 ///< argument 'bar'.
144
145 std::string usageSummary( const Layout & ,
146 const std::string & exe , const std::string & args = std::string() ) const ;
147 ///< Returns a one-line (or line-wrapped) usage summary, as
148 ///< "usage: <exe> <options> <args>". The 'args' parameter
149 ///< should represent the non-option arguments (with a
150 ///< leading space), like " <foo> [<bar>]".
151 ///<
152 ///< Eg:
153 ///< \code
154 ///< std::cout << options.usageSummary(
155 ///< OptionsLayout().set_level_if(!verbose,1U).set_extra(verbose) ,
156 ///< getopt.args().prefix() , " <arg> [<arg> ...]" ) << std::endl ;
157 ///< \endcode
158
159 std::string usageHelp( const Layout & ) const ;
160 ///< Returns a multi-line string giving help on each option.
161
162 void showUsage( const Layout & , std::ostream & stream ,
163 const std::string & exe , const std::string & args = std::string() ) const ;
164 ///< Streams out multi-line usage text using usageSummary() and
165 ///< usageHelp().
166
167private:
168 struct Option
169 {
170 enum class Multiplicity { zero , zero_or_one , one , many } ;
171 char c ;
172 std::string name ;
173 std::string description ;
174 std::string description_extra ;
175 Multiplicity value_multiplicity ;
176 bool hidden ;
177 std::string value_description ;
178 unsigned int level ;
179
180 Option( char c_ , const std::string & name_ , const std::string & description_ ,
181 const std::string & description_extra_ , const std::string & multiplicity_ ,
182 const std::string & vd_ , unsigned int level_ ) ;
183 static Multiplicity decode( const std::string & ) ;
184 } ;
185 using Map = std::map<std::string,Option> ;
186
187private:
188 void parseSpec( const std::string & spec , char , char , char ) ;
189 void addImp( const std::string & , char c , const std::string & , const std::string & ,
190 const std::string & , const std::string & , unsigned int ) ;
191 std::string usageSummaryPartOne( const Layout & ) const ;
192 std::string usageSummaryPartTwo( const Layout & ) const ;
193 std::string usageHelpSyntax( Map::const_iterator ) const ;
194 std::string usageHelpDescription( Map::const_iterator , const Layout & ) const ;
195 std::string usageHelpSeparator( const Layout & , std::size_t syntax_length ) const ;
196 std::string usageHelpWrap( const Layout & , const std::string & line_in ,
197 const std::string & ) const ;
198 std::string usageHelpImp( const Layout & ) const ;
199 static std::size_t longestSubLine( const std::string & ) ;
200
201private:
202 StringArray m_names ; // sorted
203 Map m_map ;
204} ;
205
206inline G::OptionsLayout & G::OptionsLayout::set_column( std::size_t c ) { column = c ; return *this ; }
207inline G::OptionsLayout & G::OptionsLayout::set_extra( bool e ) { extra = e ; return *this ; }
208inline G::OptionsLayout & G::OptionsLayout::set_level( unsigned int l ) { level = l ; return *this ; }
209inline G::OptionsLayout & G::OptionsLayout::set_level_if( bool b , unsigned int l ) { if(b) level = l ; return *this ; }
210inline G::OptionsLayout & G::OptionsLayout::set_level_exact( bool le ) { level_exact = le ; return *this ; }
211inline G::OptionsLayout & G::OptionsLayout::set_alt_usage( bool au ) { alt_usage = au ; return *this ; }
212
213#endif
A class to represent allowed command-line options and to provide command-line usage text.
Definition: goptions.h:66
std::string lookup(char c) const
Converts from short-form option character to the corresponding long-form name.
Definition: goptions.cpp:159
bool unvalued(const std::string &) const
Returns true if the given option name is valid and takes no value.
Definition: goptions.cpp:123
const StringArray & names() const
Returns the sorted list of long-form option names.
Definition: goptions.cpp:169
bool visible(const std::string &name, unsigned int level, bool level_exact=false) const
Returns true if the option is visible at the given level.
Definition: goptions.cpp:139
bool defaulting(const std::string &) const
Returns true if the given long-form single-valued() option can optionally have no explicit value,...
Definition: goptions.cpp:106
bool valid(const std::string &) const
Returns true if the long-form option name is valid.
Definition: goptions.cpp:154
void add(StringArray)
Adds one component of the specification, broken down into its seven separate parts.
Definition: goptions.cpp:65
bool multivalued(char) const
Returns true if the short-form option can have multiple values.
Definition: goptions.cpp:128
std::string usageSummary(const Layout &, const std::string &exe, const std::string &args=std::string()) const
Returns a one-line (or line-wrapped) usage summary, as "usage: <exe> <options> <args>".
Definition: goptions.cpp:444
bool valued(char) const
Returns true if the given short-form option takes a value, Returns true if the short-form option char...
Definition: goptions.cpp:112
void showUsage(const Layout &, std::ostream &stream, const std::string &exe, const std::string &args=std::string()) const
Streams out multi-line usage text using usageSummary() and usageHelp().
Definition: goptions.cpp:435
Options()
Default constructor for no options.
std::string usageHelp(const Layout &) const
Returns a multi-line string giving help on each option.
Definition: goptions.cpp:385
Low-level classes.
Definition: galign.h:28
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstrings.h:31
Describes the layout for G::Options output.
Definition: goptions.h:40
std::size_t column
left hand column width if no separator (includes margin)
Definition: goptions.h:42
std::size_t margin
spaces to the left of the syntax part
Definition: goptions.h:45
std::size_t width
overall width for wrapping, or zero for none
Definition: goptions.h:43
std::string separator
separator between syntax and description
Definition: goptions.h:41
bool extra
include descriptions' extra text
Definition: goptions.h:48
std::size_t width2
width after the first line, or zero for 'width'
Definition: goptions.h:44
unsigned int level
show options at-or-below this level
Definition: goptions.h:46
bool level_exact
.. or exactly at that level
Definition: goptions.h:47
bool alt_usage
use alternate "usage:" string
Definition: goptions.h:49