mirror of https://github.com/KLayout/klayout.git
Enhancements on command line parser
* Advanced options * Groups * strm2gds uses the new features already.
This commit is contained in:
parent
09033d834e
commit
dede3afe1b
|
|
@ -39,13 +39,17 @@ GenericWriterOptions::GenericWriterOptions ()
|
|||
void
|
||||
GenericWriterOptions::add_options (tl::CommandLineOptions &cmd, const std::string &format)
|
||||
{
|
||||
cmd << tl::arg ("-os|--scale-factor=factor", &scale_factor, "Scales the layout upon writing",
|
||||
std::string group ("[Output options - General]");
|
||||
|
||||
cmd << tl::arg (group +
|
||||
"-os|--scale-factor=factor", &scale_factor, "Scales the layout upon writing",
|
||||
"Specifies layout scaling. If given, the saved layout will be scaled by the "
|
||||
"given factor."
|
||||
);
|
||||
|
||||
if (format == "GDS2" || format == "GDS2Text" || format == "OASIS") {
|
||||
cmd << tl::arg ("-ou|--dbu=dbu", &dbu, "Uses the specified database unit",
|
||||
cmd << tl::arg (group +
|
||||
"-ou|--dbu=dbu", &dbu, "Uses the specified database unit",
|
||||
"Specifies the database unit to save the layout in. The database unit is given "
|
||||
"in micron units. By default, the original unit is used. The layout will not "
|
||||
"change physically because internally, the coordinates are scaled to match the "
|
||||
|
|
@ -53,35 +57,43 @@ GenericWriterOptions::add_options (tl::CommandLineOptions &cmd, const std::strin
|
|||
);
|
||||
}
|
||||
|
||||
cmd << tl::arg ("-ox|--drop-empty-cells", &dont_write_empty_cells, "Drops empty cells",
|
||||
cmd << tl::arg (group +
|
||||
"#-ox|--drop-empty-cells", &dont_write_empty_cells, "Drops empty cells",
|
||||
"If given, empty cells won't be written. See --keep-instances for more options."
|
||||
);
|
||||
|
||||
if (format == "GDS2" || format == "GDS2Text") {
|
||||
cmd << tl::arg ("-ok|--keep-instances", &keep_instances, "Keeps instances of dropped cells",
|
||||
cmd << tl::arg (group +
|
||||
"#-ok|--keep-instances", &keep_instances, "Keeps instances of dropped cells",
|
||||
"If given, instances of dropped cell's won't be removed. Hence, ghost cells are "
|
||||
"produced. The resulting layout may not be readable by consumers that require "
|
||||
"all instantiated cells to be present as actual cells."
|
||||
"all instantiated cells to be present as actual cells.\n"
|
||||
"Dropped cells are those which are removed by a negative cell selection (see "
|
||||
"--write-cells) "
|
||||
);
|
||||
}
|
||||
|
||||
if (format == "GDS2" || format == "GDS2Text" || format == "OASIS") {
|
||||
cmd << tl::arg ("-oc|--write-context-info", &write_context_info, "Writes context information",
|
||||
cmd << tl::arg (group +
|
||||
"#-oc|--write-context-info", &write_context_info, "Writes context information",
|
||||
"Include context information for PCell instances and other information in a format-specific "
|
||||
"way. The resulting layout may show unexpected features for other consumers."
|
||||
);
|
||||
}
|
||||
|
||||
cmd << tl::arg ("-ow|--write-cells=sel", &cell_selection, "Specifies cells to write",
|
||||
cmd << tl::arg (group +
|
||||
"#-ow|--write-cells=sel", &cell_selection, "Specifies cells to write",
|
||||
"This option specifies the cells to write. The value of this option is a sequence of "
|
||||
"select/unselect operations. A select operation is an optional plus sign (+), followed by "
|
||||
"a cell filter. An unselect operation is a minus sign (-) followed by a cell filter. "
|
||||
"A cell filter is a plain cell name, a glob pattern (using '*' and '?' for placeholders). "
|
||||
"If a cell filter is enclosed in round brackets, only this cell is specified. Otherwise "
|
||||
"the cell and it's children are specified.\n"
|
||||
"positive and negative cell select operations. "
|
||||
"A select operation is an optional plus (+) or minus sign (-), followed by "
|
||||
"a cell filter. By default a select operation is positive, with a minus sign, the "
|
||||
"select operation is negative and will unselect the matching cells."
|
||||
"A cell filter is a plain cell name or a glob pattern (using '*' and '?' for placeholders). "
|
||||
"If a cell filter is enclosed in round brackets, it will apply only to the matching cells. "
|
||||
"Otherwise it will apply to these cells plus their children.\n"
|
||||
"\n"
|
||||
"Multiple operations can be specified by adding them with a comma separator. "
|
||||
"Cell selection and unselection happens in the order given. Hence it's possible "
|
||||
"Multiple operations can be specified by combining them with a comma. "
|
||||
"Positive and negative selection happens in the order given. Hence it's possible "
|
||||
"to select a cell with it's children and then unselect some children of this cell.\n"
|
||||
"\n"
|
||||
"Examples:\n\n"
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
#include "tlCommandLineParser.h"
|
||||
|
||||
int
|
||||
main (int argc, char *argv [])
|
||||
main_func (int argc, char *argv [])
|
||||
{
|
||||
bd::init ();
|
||||
|
||||
|
|
@ -38,39 +38,50 @@ main (int argc, char *argv [])
|
|||
|
||||
tl::CommandLineOptions cmd;
|
||||
|
||||
cmd << tl::arg ("-ov|--max-vertex-count=count", &gds2_options.max_vertex_count, "Specifies the maximum number of points per polygon",
|
||||
std::string group = "[Output options - GDS2 specific]";
|
||||
|
||||
cmd << tl::arg (group +
|
||||
"-ov|--max-vertex-count=count", &gds2_options.max_vertex_count, "Specifies the maximum number of points per polygon",
|
||||
"If this number is given, polygons are cut into smaller parts if they have more "
|
||||
"than the specified number of points. If not given, the maximum number of points will be used. "
|
||||
"This is 8190 unless --multi-xy-records is given."
|
||||
)
|
||||
<< tl::arg ("-om|--multi-xy-records", &gds2_options.multi_xy_records, "Allows unlimited number of points",
|
||||
<< tl::arg (group +
|
||||
"#-om|--multi-xy-records", &gds2_options.multi_xy_records, "Allows unlimited number of points",
|
||||
"If this option is given, multiple XY records will be written to accomodate an unlimited number "
|
||||
"of points per polygon or path. However, such files may not be compatible with some consumers."
|
||||
)
|
||||
<< tl::arg ("-oz|--no-zero-length-paths", &gds2_options.no_zero_length_paths, "Converts zero-length paths to polygons",
|
||||
<< tl::arg (group +
|
||||
"#-oz|--no-zero-length-paths", &gds2_options.no_zero_length_paths, "Converts zero-length paths to polygons",
|
||||
"If this option is given, zero-length paths (such with one point) are not written as paths "
|
||||
"but converted to polygons. This avoids compatibility issues with consumers of this layout file."
|
||||
)
|
||||
<< tl::arg ("-on|--cellname-length=length", &gds2_options.max_cellname_length, "Limits cell names to the given length",
|
||||
<< tl::arg (group +
|
||||
"-on|--cellname-length=length", &gds2_options.max_cellname_length, "Limits cell names to the given length",
|
||||
"If this option is given, long cell names will truncated if their length exceeds the given length."
|
||||
)
|
||||
<< tl::arg ("-ol|--libname=libname", &gds2_options.libname, "Uses the given library name",
|
||||
<< tl::arg (group +
|
||||
"-ol|--libname=libname", &gds2_options.libname, "Uses the given library name",
|
||||
"This option can specify the GDS2 LIBNAME for the output file. By default, the original LIBNAME is "
|
||||
"written."
|
||||
)
|
||||
<< tl::arg ("-or|--user-units=unit", &gds2_options.user_units, "Specifies the user unit to use",
|
||||
<< tl::arg (group +
|
||||
"#-or|--user-units=unit", &gds2_options.user_units, "Specifies the user unit to use",
|
||||
"Specifies the GDS2 user unit. By default micrometers are used for the user unit."
|
||||
)
|
||||
<< tl::arg ("!-ot|--no-timestamps", &gds2_options.write_timestamps, "Don't write timestamps",
|
||||
<< tl::arg (group +
|
||||
"#!-ot|--no-timestamps", &gds2_options.write_timestamps, "Don't write timestamps",
|
||||
"Writes a dummy time stamp instead of the actual time. With this option, GDS2 files become "
|
||||
"bytewise indentical even if written at different times. This option is useful if binary "
|
||||
"identity is important (i.e. in regression scenarios)."
|
||||
)
|
||||
<< tl::arg ("-op|--write-cell-properties", &gds2_options.write_cell_properties, "Write cell properties",
|
||||
<< tl::arg (group +
|
||||
"#-op|--write-cell-properties", &gds2_options.write_cell_properties, "Write cell properties",
|
||||
"This option enables a GDS2 extension that allows writing of cell properties to GDS2 files. "
|
||||
"Consumers that don't support this feature, may not be able to read such a GDS2 files."
|
||||
)
|
||||
<< tl::arg ("-oq|--write-file-properties", &gds2_options.write_file_properties, "Write file properties",
|
||||
<< tl::arg (group +
|
||||
"#-oq|--write-file-properties", &gds2_options.write_file_properties, "Write file properties",
|
||||
"This option enables a GDS2 extension that allows writing of file properties to GDS2 files. "
|
||||
"Consumers that don't support this feature, may not be able to read such a GDS2 files."
|
||||
)
|
||||
|
|
@ -82,31 +93,37 @@ main (int argc, char *argv [])
|
|||
|
||||
cmd.brief ("This program will convert the given file to a GDS2 file");
|
||||
|
||||
cmd.parse (argc, argv);
|
||||
|
||||
db::Manager m;
|
||||
db::Layout layout (&m);
|
||||
db::LayerMap map;
|
||||
|
||||
{
|
||||
tl::InputStream stream (infile);
|
||||
db::Reader reader (stream);
|
||||
map = reader.read (layout);
|
||||
}
|
||||
|
||||
{
|
||||
db::SaveLayoutOptions save_options;
|
||||
save_options.set_options (gds2_options);
|
||||
generic_writer_options.configure (save_options, layout);
|
||||
|
||||
tl::OutputStream stream (outfile);
|
||||
db::GDS2Writer writer;
|
||||
writer.write (layout, stream, save_options);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv [])
|
||||
{
|
||||
try {
|
||||
|
||||
cmd.parse (argc, argv);
|
||||
|
||||
db::Manager m;
|
||||
db::Layout layout (&m);
|
||||
db::LayerMap map;
|
||||
|
||||
{
|
||||
tl::InputStream stream (infile);
|
||||
db::Reader reader (stream);
|
||||
map = reader.read (layout);
|
||||
}
|
||||
|
||||
{
|
||||
db::SaveLayoutOptions save_options;
|
||||
save_options.set_options (gds2_options);
|
||||
generic_writer_options.configure (save_options, layout);
|
||||
|
||||
tl::OutputStream stream (outfile);
|
||||
db::GDS2Writer writer;
|
||||
writer.write (layout, stream, save_options);
|
||||
}
|
||||
|
||||
} catch (tl::CancelException &ex) {
|
||||
return main_func (argc, argv);
|
||||
} catch (tl::CancelException & /*ex*/) {
|
||||
return 1;
|
||||
} catch (std::exception &ex) {
|
||||
tl::error << ex.what ();
|
||||
|
|
@ -117,6 +134,4 @@ main (int argc, char *argv [])
|
|||
} catch (...) {
|
||||
tl::error << "ERROR: unspecific error";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,10 +32,29 @@ namespace tl
|
|||
// ArgBase implementation
|
||||
|
||||
ArgBase::ParsedOption::ParsedOption (const std::string &option)
|
||||
: optional (false), inverted (false)
|
||||
: optional (false), inverted (false), advanced (false), non_advanced (false)
|
||||
{
|
||||
tl::Extractor ex (option.c_str ());
|
||||
|
||||
while (! ex.at_end ()) {
|
||||
|
||||
if (ex.test ("#")) {
|
||||
advanced = true;
|
||||
} else if (ex.test ("/")) {
|
||||
non_advanced = true;
|
||||
} else if (ex.test ("[")) {
|
||||
const char *t = ex.get ();
|
||||
while (! ex.at_end () && *ex != ']') {
|
||||
++ex;
|
||||
}
|
||||
group += std::string (t, 0, ex.get () - t);
|
||||
ex.test ("]");
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (ex.test ("!")) {
|
||||
inverted = true;
|
||||
}
|
||||
|
|
@ -61,7 +80,7 @@ ArgBase::ParsedOption::ParsedOption (const std::string &option)
|
|||
}
|
||||
}
|
||||
|
||||
ArgBase::ArgBase (const char *option, const char *brief_doc, const char *long_doc)
|
||||
ArgBase::ArgBase (const std::string &option, const std::string &brief_doc, const std::string &long_doc)
|
||||
: m_option (option), m_brief_doc (brief_doc), m_long_doc (long_doc)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
|
|
@ -98,7 +117,29 @@ public:
|
|||
|
||||
void action (CommandLineOptions *options) const
|
||||
{
|
||||
options->produce_help (options->program_name ());
|
||||
options->produce_help (options->program_name (), false);
|
||||
throw tl::CancelException ();
|
||||
}
|
||||
};
|
||||
|
||||
class AdvancedHelpArg
|
||||
: public ArgBase
|
||||
{
|
||||
public:
|
||||
AdvancedHelpArg ()
|
||||
: ArgBase ("/--help-all", "Shows all options (including advanced) and exits", "")
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
ArgBase *clone () const
|
||||
{
|
||||
return new AdvancedHelpArg ();
|
||||
}
|
||||
|
||||
void action (CommandLineOptions *options) const
|
||||
{
|
||||
options->produce_help (options->program_name (), true);
|
||||
throw tl::CancelException ();
|
||||
}
|
||||
};
|
||||
|
|
@ -130,7 +171,7 @@ class VersionArg
|
|||
{
|
||||
public:
|
||||
VersionArg ()
|
||||
: ArgBase ("--version", "Produces the version and exits", "")
|
||||
: ArgBase ("--version", "Shows the version and exits", "")
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
|
@ -147,6 +188,42 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class VerbosityArg
|
||||
: public ArgBase
|
||||
{
|
||||
public:
|
||||
VerbosityArg ()
|
||||
: ArgBase ("-d|--debug-level", "Sets the verbosity level",
|
||||
"The verbosity level is an integer. Typical values are:\n"
|
||||
"* 0: silent\n"
|
||||
"* 10: somewhat verbose\n"
|
||||
"* 11: somewhat verbose plus timing information\n"
|
||||
"* 20: verbose\n"
|
||||
"* 21: verbose plus timing information\n"
|
||||
"..."
|
||||
)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
ArgBase *clone () const
|
||||
{
|
||||
return new VerbosityArg ();
|
||||
}
|
||||
|
||||
bool wants_value () const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void take_value (tl::Extractor &ex)
|
||||
{
|
||||
int d = 0;
|
||||
ex.read (d);
|
||||
tl::verbosity (d);
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// CommandLineOptions implementation
|
||||
|
||||
|
|
@ -156,7 +233,7 @@ std::string CommandLineOptions::m_license;
|
|||
CommandLineOptions::CommandLineOptions ()
|
||||
{
|
||||
// Populate with the built-in options
|
||||
*this << HelpArg () << VersionArg () << LicenseArg ();
|
||||
*this << HelpArg () << AdvancedHelpArg () << VersionArg () << LicenseArg () << VerbosityArg ();
|
||||
}
|
||||
|
||||
CommandLineOptions::~CommandLineOptions ()
|
||||
|
|
@ -242,6 +319,9 @@ struct NameCompare
|
|||
if (! a->is_option ()) {
|
||||
return false;
|
||||
}
|
||||
if (a->option ().group != b->option ().group) {
|
||||
return a->option ().group < b->option ().group;
|
||||
}
|
||||
if (a->option ().short_option.empty () != b->option ().short_option.empty ()) {
|
||||
return a->option ().short_option.empty () < b->option ().short_option.empty ();
|
||||
}
|
||||
|
|
@ -253,7 +333,7 @@ struct NameCompare
|
|||
};
|
||||
|
||||
void
|
||||
CommandLineOptions::produce_help (const std::string &program_name)
|
||||
CommandLineOptions::produce_help (const std::string &program_name, bool advanced)
|
||||
{
|
||||
int columns = 80;
|
||||
|
||||
|
|
@ -314,17 +394,34 @@ CommandLineOptions::produce_help (const std::string &program_name)
|
|||
"(with two dashes). If a value is required, it can be specified either "
|
||||
"as the following argument or added to the option with an equal sign (=).");
|
||||
|
||||
tl::info << " List of options:" << tl::endl;
|
||||
tl::info << tl::endl << " List of options:" << tl::endl;
|
||||
|
||||
tl::info << " "
|
||||
<< pad_string (short_option_width + 5, "Short") << " "
|
||||
<< pad_string (long_option_width + 5, "Long") << " "
|
||||
<< pad_string (name_width + 3, "Value") << " " << "Description" << tl::endl;
|
||||
std::string header = pad_string (short_option_width + 5, "Short") + " "
|
||||
+ pad_string (long_option_width + 5, "Long") + " "
|
||||
+ pad_string (name_width + 3, "Value") + " " + "Description";
|
||||
|
||||
tl::info << " " << header << tl::endl;
|
||||
|
||||
std::string prev_group;
|
||||
bool hidden = false;
|
||||
|
||||
for (std::vector<ArgBase *>::const_iterator a = sorted_args.begin (); a != sorted_args.end (); ++a) {
|
||||
|
||||
if (! (*a)->is_option ()) {
|
||||
continue;
|
||||
} else if ((*a)->option ().advanced && !advanced) {
|
||||
hidden = true;
|
||||
continue;
|
||||
} else if ((*a)->option ().non_advanced && advanced) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((*a)->option ().group != prev_group) {
|
||||
prev_group = (*a)->option ().group;
|
||||
tl::info << tl::endl << " " << prev_group << ":" << tl::endl;
|
||||
tl::info << " " << header << tl::endl;
|
||||
}
|
||||
|
||||
std::string name;
|
||||
if ((*a)->wants_value ()) {
|
||||
name = (*a)->option ().name;
|
||||
|
|
@ -332,6 +429,7 @@ CommandLineOptions::produce_help (const std::string &program_name)
|
|||
name = "value";
|
||||
}
|
||||
}
|
||||
|
||||
tl::info << " "
|
||||
<< pad_string (short_option_width + 5, (*a)->option ().short_option.empty () ? "" : "-" + (*a)->option ().short_option) << " "
|
||||
<< pad_string (long_option_width + 5, (*a)->option ().long_option.empty () ? "" : "--" + (*a)->option ().long_option) << " "
|
||||
|
|
@ -343,6 +441,11 @@ CommandLineOptions::produce_help (const std::string &program_name)
|
|||
print_string_formatted (" ", columns, (*a)->long_doc ());
|
||||
tl::info << "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (hidden) {
|
||||
tl::info << tl::endl << " See --help-all for more options." << tl::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -363,11 +466,24 @@ CommandLineOptions::parse (int argc, char *argv[])
|
|||
{
|
||||
m_program_name = tl::to_string (QFileInfo (QString::fromLocal8Bit (argv [0])).fileName ());
|
||||
|
||||
std::vector<ArgBase *>::const_iterator next_plain_arg = m_args.begin ();
|
||||
while (next_plain_arg != m_args.end () && (*next_plain_arg)->is_option ()) {
|
||||
++next_plain_arg;
|
||||
std::vector<ArgBase *> plain_args;
|
||||
std::map<std::string, ArgBase *> arg_by_short_option, arg_by_long_option;
|
||||
|
||||
for (std::vector<ArgBase *>::const_iterator i = m_args.begin (); i != m_args.end (); ++i) {
|
||||
if ((*i)->is_option ()) {
|
||||
if (! (*i)->option ().short_option.empty ()) {
|
||||
arg_by_short_option.insert (std::make_pair ((*i)->option ().short_option, *i));
|
||||
}
|
||||
if (! (*i)->option ().long_option.empty ()) {
|
||||
arg_by_long_option.insert (std::make_pair ((*i)->option ().long_option, *i));
|
||||
}
|
||||
} else {
|
||||
plain_args.push_back (*i);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<ArgBase *>::const_iterator next_plain_arg = plain_args.begin ();
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
|
||||
ArgBase *arg = 0;
|
||||
|
|
@ -378,43 +494,31 @@ CommandLineOptions::parse (int argc, char *argv[])
|
|||
if (ex.test ("--")) {
|
||||
|
||||
std::string n;
|
||||
ex.read_word (n);
|
||||
for (std::vector<ArgBase *>::const_iterator a = m_args.begin (); a != m_args.end () && !arg; ++a) {
|
||||
if ((*a)->option ().long_option == n) {
|
||||
arg = *a;
|
||||
}
|
||||
}
|
||||
|
||||
if (!arg) {
|
||||
ex.read_word (n, "_-");
|
||||
std::map<std::string, ArgBase *>::const_iterator a = arg_by_long_option.find (n);
|
||||
if (a == arg_by_long_option.end ()) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Unknown command line option --%1 (use -h for help)").arg (tl::to_qstring (n))));
|
||||
}
|
||||
arg = a->second;
|
||||
|
||||
} else if (ex.test ("-")) {
|
||||
|
||||
std::string n;
|
||||
ex.read_word (n);
|
||||
for (std::vector<ArgBase *>::const_iterator a = m_args.begin (); a != m_args.end () && !arg; ++a) {
|
||||
if ((*a)->option ().short_option == n) {
|
||||
arg = *a;
|
||||
}
|
||||
}
|
||||
|
||||
if (!arg) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Unknown command line option -%1 (use -h for help)").arg (tl::to_qstring (n))));
|
||||
std::map<std::string, ArgBase *>::const_iterator a = arg_by_short_option.find (n);
|
||||
if (a == arg_by_short_option.end ()) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Unknown command line option --%1 (use -h for help)").arg (tl::to_qstring (n))));
|
||||
}
|
||||
arg = a->second;
|
||||
|
||||
} else {
|
||||
|
||||
if (next_plain_arg == m_args.end ()) {
|
||||
if (next_plain_arg == plain_args.end ()) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Unknown command line component %1 - no further plain argument expected (use -h for help)").arg (tl::to_qstring (arg_as_utf8))));
|
||||
}
|
||||
|
||||
arg = *next_plain_arg++;
|
||||
|
||||
while (next_plain_arg != m_args.end () && (*next_plain_arg)->is_option ()) {
|
||||
++next_plain_arg;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (arg->wants_value ()) {
|
||||
|
|
@ -438,11 +542,13 @@ CommandLineOptions::parse (int argc, char *argv[])
|
|||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (ex.test ("=")) {
|
||||
arg->take_value (ex);
|
||||
} else {
|
||||
arg->mark_present (arg->option ().inverted);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Exection the action if there is one
|
||||
|
|
@ -450,7 +556,7 @@ CommandLineOptions::parse (int argc, char *argv[])
|
|||
|
||||
}
|
||||
|
||||
if (next_plain_arg != m_args.end () && !(*next_plain_arg)->option ().optional) {
|
||||
if (next_plain_arg != plain_args.end () && !(*next_plain_arg)->option ().optional) {
|
||||
throw tl::Exception (tl::to_string (QObject::tr ("Additional arguments required (use -h for help)")));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,8 +56,9 @@ public:
|
|||
*/
|
||||
ParsedOption (const std::string &option);
|
||||
|
||||
bool optional, inverted;
|
||||
bool optional, inverted, advanced, non_advanced;
|
||||
std::string long_option, short_option, name;
|
||||
std::string group;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -77,8 +78,11 @@ public:
|
|||
* "--long-option=value" - A long option with a value
|
||||
* "-o|--long-option" - A short/long option
|
||||
* "-o|--long-option=value" - A short/long option with a value
|
||||
* "[group]..." - List the option under this group (group = group title)
|
||||
* "#..." - Advanced option - listed with --help-all only
|
||||
* "/..." - Non-ddvanced option - listed with -h|--help only
|
||||
*/
|
||||
ArgBase (const char *option, const char *brief_doc, const char *long_doc);
|
||||
ArgBase (const std::string &option, const std::string &brief_doc, const std::string &long_doc);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
|
|
@ -264,7 +268,7 @@ class arg_direct_setter
|
|||
: public ArgBase
|
||||
{
|
||||
public:
|
||||
arg_direct_setter (const char *option, T *value, const char *brief_doc, const char *long_doc)
|
||||
arg_direct_setter (const std::string &option, T *value, const std::string &brief_doc, const std::string &long_doc)
|
||||
: ArgBase (option, brief_doc, long_doc), mp_value (value)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
|
|
@ -302,7 +306,7 @@ class arg_method_setter
|
|||
: public ArgBase
|
||||
{
|
||||
public:
|
||||
arg_method_setter (const char *option, C *object, void (C::*setter)(T), const char *brief_doc, const char *long_doc)
|
||||
arg_method_setter (const std::string &option, C *object, void (C::*setter)(T), const std::string &brief_doc, const std::string &long_doc)
|
||||
: ArgBase (option, brief_doc, long_doc), mp_object (object), mp_setter (setter)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
|
|
@ -340,13 +344,13 @@ private:
|
|||
* @brief Polymorphic production methods for the argument getters
|
||||
*/
|
||||
template <class C, class T>
|
||||
arg_method_setter<C, T> arg (const char *option, C *object, void (C::*setter)(T), const char *brief_doc, const char *long_doc = "")
|
||||
arg_method_setter<C, T> arg (const std::string &option, C *object, void (C::*setter)(T), const std::string &brief_doc, const std::string &long_doc = "")
|
||||
{
|
||||
return arg_method_setter<C, T> (option, object, setter, brief_doc, long_doc);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
arg_direct_setter<T> arg (const char *option, T *value, const char *brief_doc, const char *long_doc = "")
|
||||
arg_direct_setter<T> arg (const std::string &option, T *value, const std::string &brief_doc, const std::string &long_doc = "")
|
||||
{
|
||||
return arg_direct_setter<T> (option, value, brief_doc, long_doc);
|
||||
}
|
||||
|
|
@ -423,7 +427,7 @@ public:
|
|||
/**
|
||||
* @brief Produces the help text
|
||||
*/
|
||||
void produce_help (const std::string &program_name);
|
||||
void produce_help (const std::string &program_name, bool advanced);
|
||||
|
||||
/**
|
||||
* @brief Produces the version text
|
||||
|
|
|
|||
Loading…
Reference in New Issue