Sharg 1.1.0
The argument parser for bio-c++ tools.
 
Loading...
Searching...
No Matches
The Sharg Cookbook

This document provides example recipes on how to carry out particular tasks using the Sharg functionalities in C++. Please note that these recipes are not ordered. You can use the links in the table of contents or the search function of your browser to navigate them.

It will take some time, but we hope to expand this document into containing numerous great examples. If you have suggestions for how to improve the Cookbook and/or examples you would like included, please feel free to contact us.

Constructing a basic parser

#include <sharg/all.hpp>
void run_program(std::filesystem::path const & reference_path, std::filesystem::path const & index_path)
{
std::cerr << "reference_file_path: " << reference_path << '\n';
std::cerr << "index_path " << index_path << '\n';
}
struct cmd_arguments
{
std::filesystem::path reference_path{};
std::filesystem::path index_path{"out.index"};
};
void initialise_parser(sharg::parser & parser, cmd_arguments & args)
{
parser.info.author = "E. coli";
parser.info.short_description = "Creates an index over a reference.";
parser.info.version = "1.0.0";
parser.add_option(args.reference_path,
sharg::config{.short_id = 'r',
.long_id = "reference",
.description = "The path to the reference.",
.required = true,
.validator = sharg::input_file_validator{{"fa", "fasta"}}});
parser.add_option(
args.index_path,
sharg::config{.short_id = 'o',
.long_id = "output",
.description = "The output index file path.",
.validator =
sharg::output_file_validator{sharg::output_file_open_options::create_new, {"index"}}});
}
int main(int argc, char const ** argv)
{
sharg::parser parser("Indexer", argc, argv);
cmd_arguments args{};
initialise_parser(parser, args);
try
{
parser.parse();
}
catch (sharg::parser_error const & ext)
{
std::cerr << "[PARSER ERROR] " << ext.what() << '\n';
return -1;
}
run_program(args.reference_path, args.index_path);
return 0;
}
Meta-header for the Parser module .
Parser exception that is thrown whenever there is an error while parsing the command line arguments.
Definition: exceptions.hpp:43
The Sharg command line parser.
Definition: parser.hpp:157
void add_option(option_type &value, config< validator_type > const &config)
Adds an option to the sharg::parser.
Definition: parser.hpp:246
parser_meta_data info
Aggregates all parser related meta data (see sharg::parser_meta_data struct).
Definition: parser.hpp:674
Option struct that is passed to the sharg::parser::add_option() function.
Definition: config.hpp:46
std::string short_description
A short description of the application (e.g. "A tool for mapping reads to the genome").
Definition: auxiliary.hpp:60
std::string version
The version information MAJOR.MINOR.PATH (e.g. 3.1.3)
Definition: auxiliary.hpp:57
std::string author
Your name ;-)
Definition: auxiliary.hpp:63
T what(T... args)

Constructing a subcommand parser

#include <sharg/all.hpp>
// =====================================================================================================================
// pull
// =====================================================================================================================
struct pull_arguments
{
std::string repository{};
std::string branch{};
bool progress{false};
};
int run_git_pull(sharg::parser & parser)
{
pull_arguments args{};
parser.add_positional_option(args.repository, sharg::config{.description = "The repository name to pull from."});
parser.add_positional_option(args.branch, sharg::config{.description = "The branch name to pull from."});
try
{
parser.parse();
}
catch (sharg::parser_error const & ext)
{
std::cerr << "[Error git pull] " << ext.what() << "\n";
return -1;
}
std::cerr << "Git pull with repository " << args.repository << " and branch " << args.branch << '\n';
return 0;
}
// =====================================================================================================================
// push
// =====================================================================================================================
struct push_arguments
{
std::string repository{};
bool push_all{false};
};
int run_git_push(sharg::parser & parser)
{
push_arguments args{};
parser.add_positional_option(args.repository, sharg::config{.description = "The repository name to push to."});
parser.add_positional_option(args.branches, sharg::config{.description = "The branch names to push."});
try
{
parser.parse();
}
catch (sharg::parser_error const & ext)
{
std::cerr << "[Error git push] " << ext.what() << "\n";
return -1;
}
std::cerr << "Git push with repository " << args.repository << " and branches ";
for (auto && branch : args.branches)
std::cerr << branch << ' ';
std::cerr << '\n';
return 0;
}
// =====================================================================================================================
// main
// =====================================================================================================================
int main(int argc, char const ** argv)
{
sharg::parser top_level_parser{"mygit", argc, argv, sharg::update_notifications::on, {"push", "pull"}};
// Add information and flags, but no (positional) options to your top-level parser.
// Because of ambiguity, we do not allow any (positional) options for the top-level parser.
top_level_parser.info.description.push_back("You can push or pull from a remote repository.");
bool flag{false};
top_level_parser.add_flag(flag, sharg::config{.short_id = 'f', .long_id = "flag", .description = "some flag"});
try
{
top_level_parser.parse(); // trigger command line parsing
}
catch (sharg::parser_error const & ext) // catch user errors
{
std::cerr << "[Error] " << ext.what() << "\n"; // customise your error message
return -1;
}
sharg::parser & sub_parser = top_level_parser.get_sub_parser(); // hold a reference to the sub_parser
std::cout << "Proceed to sub parser.\n";
if (sub_parser.info.app_name == std::string_view{"mygit-pull"})
return run_git_pull(sub_parser);
else if (sub_parser.info.app_name == std::string_view{"mygit-push"})
return run_git_push(sub_parser);
else
std::cout << "Unhandled subparser named " << sub_parser.info.app_name << '\n';
// Note: Arriving in this else branch means you did not handle all sub_parsers in the if branches above.
return 0;
}
void add_positional_option(option_type &value, config< validator_type > const &config)
Adds a positional option to the sharg::parser.
Definition: parser.hpp:314
void parse()
Initiates the actual command line parsing.
Definition: parser.hpp:399
parser & get_sub_parser()
Returns a reference to the sub-parser instance if subcommand parsing was enabled.
Definition: parser.hpp:462
@ on
Automatic update notifications should be enabled.
char short_id
The short identifier for the option (e.g. 'a', making the option callable via -a).
Definition: config.hpp:56
std::string app_name
The application name that will be displayed on the help page.
Definition: auxiliary.hpp:54

Write a custom validator

This recipe implements a validator that checks whether a numeric argument is an integral square (i.e. 0, 1, 4, 9...). Invalid values throw a sharg::validation_error.

#include <cmath>
struct custom_validator
{
using option_value_type = double; // used for all arithmetic types
void operator()(option_value_type const & val) const
{
if ((std::round(val) != val) || // not an integer
(std::pow(std::round(std::sqrt(val)), 2) != val)) // not a square
{
throw sharg::validation_error{"The provided number is not an arithmetic square."};
}
}
std::string get_help_page_message() const
{
return "Value must be the square of an integral number.";
}
};
Parser exception thrown when an argument could not be casted to the according type.
Definition: exceptions.hpp:183

All Sharg documentation snippets

The following lists all snippets that appear in our documentation. Search for keywords with Strg + F.

#include <sharg/all.hpp>
int main(int argc, char const ** argv)
{
sharg::parser myparser{"Test", argc, argv};
std::string myvar{"Example"};
myparser.add_option(myvar, sharg::config{.short_id = 's', .long_id = "special-op", .advanced = true});
}
#include <sharg/all.hpp>
namespace foo
{
enum class bar
{
one,
two,
three
};
// Specialise a mapping from an identifying string to the respective value of your type bar.
auto enumeration_names(bar)
{
return std::unordered_map<std::string_view, bar>{{"one", bar::one}, {"two", bar::two}, {"three", bar::three}};
}
} // namespace foo
int main(int argc, char const * argv[])
{
foo::bar value{};
sharg::parser parser{"my_program", argc, argv};
// Because of the enumeration_names function
// you can now add an option that takes a value of type bar:
auto vali = sharg::value_list_validator{(sharg::enumeration_names<foo::bar> | std::views::values)};
parser.add_option(
value,
sharg::config{.short_id = 'f', .long_id = "foo", .description = "Give me a value for foo.", .validator = vali});
try
{
parser.parse();
}
catch (sharg::parser_error const & ext) // the user did something wrong
{
std::cerr << "[PARSER ERROR] " << ext.what() << "\n"; // customize your error message
return -1;
}
}
A validator that checks whether a value is inside a list of valid values.
Definition: validators.hpp:176
#include <system_error>
#include <sharg/all.hpp>
namespace sharg::custom
{
// Specialise the sharg::custom::parsing data structure to enable parsing of std::errc.
template <>
struct parsing<std::errc>
{
// Specialise a mapping from an identifying string to the respective value of your type Foo.
{"no_error", std::errc{}},
{"timed_out", std::errc::timed_out},
{"invalid_argument", std::errc::invalid_argument},
{"io_error", std::errc::io_error}};
};
} // namespace sharg::custom
int main(int argc, char const * argv[])
{
std::errc value{};
sharg::parser parser{"my_program", argc, argv};
// Because of the parsing struct and
// the static member function enumeration_names
// you can now add an option that takes a value of type std::errc:
auto validator = sharg::value_list_validator{(sharg::enumeration_names<std::errc> | std::views::values)};
parser.add_option(value,
.long_id = "errc",
.description = "Give me a std::errc value.",
.validator = validator});
try
{
parser.parse();
}
catch (sharg::parser_error const & ext) // the user did something wrong
{
std::cerr << "[PARSER ERROR] " << ext.what() << "\n"; // customize your error message
return -1;
}
return 0;
}
auto const enumeration_names(size_t value)
Return a conversion map from std::string_view to option_type.
#include <sharg/all.hpp>
int main(int argc, char ** argv)
{
sharg::parser myparser{"awesome-app", argc, argv}; // initialize
int a{3};
myparser.add_option(a, sharg::config{.short_id = 'a', .long_id = "aint", .description = "Specify an integer."});
try
{
myparser.parse();
}
catch (sharg::parser_error const & ext) // the user did something wrong
{
std::cerr << "[PARSER ERROR] " << ext.what() << '\n'; // customize your error message
return -1;
}
if (myparser.is_option_set('a'))
std::cerr << "The user set option -a on the command line.\n";
if (myparser.is_option_set("awesome-parameter"))
std::cerr << "The user set option --awesome-parameter on the command line.\n";
// Asking for an option identifier that was not used before throws an error:
// myparser.is_option_set("foo"); // throws sharg::design_error
return 0;
}
#include <sharg/all.hpp>
int main(int argc, char ** argv)
{
sharg::parser myparser{"Grade-Average", argc, argv}; // initialize
std::string name{"Max Muster"}; // define default values directly in the variable.
bool bonus{false};
std::vector<double> grades{}; // you can also specify a vector that is treated as a list option.
myparser.add_option(name, sharg::config{.short_id = 'n', .long_id = "name", .description = "Your name please."});
myparser.add_flag(bonus, sharg::config{.short_id = 'b', .long_id = "bonus", .description = "Got a bonus?."});
myparser.add_positional_option(grades, sharg::config{.description = "Please specify your grades."});
try
{
myparser.parse();
}
catch (sharg::parser_error const & ext) // the user did something wrong
{
std::cerr << "[PARSER ERROR] " << ext.what() << '\n'; // customize your error message
return -1;
}
if (bonus)
grades.push_back(1.0); // extra good grade
double avg{0};
for (auto g : grades)
avg += g;
avg = avg / grades.size();
std::cerr << name << " has an average grade of " << avg << '\n';
return 0;
}
std::string description
The description to be shown on any (exported) help page.
Definition: config.hpp:71
#include <sharg/all.hpp>
int main(int argc, char ** argv)
{
sharg::parser myparser{"The-Age-App", argc, argv}; // initialize
int age{30}; // define default values directly in the variable
myparser.add_option(age, sharg::config{.short_id = 'a', .long_id = "user-age", .description = "Your age please."});
try
{
myparser.parse();
}
catch (sharg::parser_error const & ext) // the user did something wrong
{
std::cerr << "The-Age-App - [PARSER ERROR] " << ext.what() << '\n'; // customize your error message
return -1;
}
std::cerr << "integer given by user: " << age << '\n';
return 0;
}
#include <sharg/all.hpp>
int main(int argc, char ** argv)
{
sharg::parser myparser{"Penguin_Parade", argc, argv}; // initialize
myparser.info.version = "2.0.0";
myparser.info.date = "12.01.2017";
myparser.info.short_description = "Organize your penguin parade";
myparser.info.description.push_back("First Paragraph.");
myparser.info.description.push_back("Second Paragraph.");
myparser.info.examples.push_back("./penguin_parade Skipper Kowalski Rico Private -d 10 -m 02 -y 2017");
int d{01}; // day
int m{01}; // month
int y{2050}; // year
myparser.add_option(d, sharg::config{.short_id = 'd', .long_id = "day", .description = "Your preferred day."});
myparser.add_option(m, sharg::config{.short_id = 'm', .long_id = "month", .description = "Your preferred month."});
myparser.add_option(y, sharg::config{.short_id = 'y', .long_id = "year", .description = "Your preferred year."});
std::vector<std::string> penguin_names;
myparser.add_positional_option(penguin_names, sharg::config{.description = "Specify the names of the penguins."});
try
{
myparser.parse();
}
catch (sharg::parser_error const & ext) // the user did something wrong
{
std::cerr << ext.what() << "\n";
return -1;
}
// organize ...
return 0;
}
T push_back(T... args)
#define main test
#include <sharg/all.hpp>
int main(int argc, char ** argv)
{
int val{};
sharg::parser parser{"Eat-Me-App", argc, argv};
parser.add_subsection("Eating Numbers");
parser.add_option(val, sharg::config{.short_id = 'i', .long_id = "int", .description = "Desc."});
parser.parse();
return 0;
}
#undef main
int main()
{
std::string argv1{"./Eat-Me-App"}, argv2{"-h"};
std::array argv{argv1.data(), argv2.data()};
return test(argv.size(), argv.data());
}
void add_subsection(std::string const &title, bool const advanced_only=false)
Adds an help page subsection to the sharg::parser.
Definition: parser.hpp:564
T data(T... args)
#include <filesystem>
#include <fstream>
int main()
{
std::ifstream file{my_file}; // Create the file.
sharg::detail::safe_filesystem_entry file_guard{my_file}; // Safe cleanup in case of errors.
// Do something on the file, that can possibly throw.
// If an unhandled exception is thrown, the file guard destructor safely removes the file from the filesystem.
file_guard.remove(); // Explicitly remove the file.
}
Provides sharg::detail::safe_filesystem_entry.
T temp_directory_path(T... args)
int main()
{}
#include <sharg/all.hpp>
int main(int argc, char const ** argv)
{
sharg::parser myparser{"Test", argc, argv}; // initialize
int myint;
sharg::arithmetic_range_validator my_validator{2, 10};
myparser.add_option(myint,
.long_id = "integer",
.description = "Give me a number.",
.validator = my_validator});
// an exception will be thrown if the user specifies an integer
// that is not in range [2,10] (e.g. "./test_app -i 15")
try
{
myparser.parse();
}
catch (sharg::parser_error const & ext) // the user did something wrong
{
std::cerr << "[PARSER ERROR] " << ext.what() << "\n"; // customize your error message
return -1;
}
std::cerr << "integer given by user passed validation: " << myint << "\n";
return 0;
}
A validator that checks whether a number is inside a given range.
Definition: validators.hpp:80
#include <sharg/all.hpp>
int main(int argc, char const ** argv)
{
sharg::parser myparser{"Test", argc, argv}; // initialize
int myint;
sharg::value_list_validator my_validator{2, 4, 6, 8, 10};
myparser.add_option(myint,
.long_id = "integer",
.description = "Give me a number.",
.validator = my_validator});
// an exception will be thrown if the user specifies an integer
// that is not one of [2,4,6,8,10] (e.g. "./test_app -i 3")
try
{
myparser.parse();
}
catch (sharg::parser_error const & ext) // the user did something wrong
{
std::cerr << "[PARSER ERROR] " << ext.what() << "\n"; // customize your error message
return -1;
}
std::cerr << "integer given by user passed validation: " << myint << "\n";
return 0;
}
#include <sharg/all.hpp>
int main(int argc, char const ** argv)
{
sharg::parser myparser{"Test", argc, argv}; // initialize
auto vali = sharg::input_file_validator{{"fa", "fasta"}};
myparser.add_option(
myfile,
sharg::config{.short_id = 'f', .long_id = "file", .description = "Give me a filename.", .validator = vali});
// an exception will be thrown if the user specifies a filename
// that does not have one of the extensions ["fa","fasta"],
// does not exists, or is not readable.
try
{
myparser.parse();
}
catch (sharg::parser_error const & ext) // the user did something wrong
{
std::cerr << "[PARSER ERROR] " << ext.what() << "\n"; // customize your error message
return -1;
}
std::cerr << "filename given by user passed validation: " << myfile << "\n";
return 0;
}
A validator that checks if a given path is a valid input file.
Definition: validators.hpp:522
#include <sharg/all.hpp>
int main(int argc, char const ** argv)
{
sharg::parser myparser{"Test", argc, argv}; // initialize
std::string my_string;
sharg::regex_validator my_validator{"[a-zA-Z]+@[a-zA-Z]+\\.com"};
myparser.add_option(my_string,
.long_id = "str",
.description = "Give me a string.",
.validator = my_validator});
// an exception will be thrown if the user specifies a string
// that is no email address ending on .com
try
{
myparser.parse();
}
catch (sharg::parser_error const & ext) // the user did something wrong
{
std::cerr << "[PARSER ERROR] " << ext.what() << "\n"; // customize your error message
return -1;
}
std::cerr << "email address given by user passed validation: " << my_string << "\n";
return 0;
}
A validator that checks if a matches a regular expression pattern.
Definition: validators.hpp:977
#include <sharg/all.hpp>
int main(int argc, char const ** argv)
{
sharg::parser myparser{"Test", argc, argv}; // initialize
std::string file_name;
sharg::regex_validator absolute_path_validator{"(/[^/]+)+/.*\\.[^/\\.]+$"};
sharg::input_file_validator my_file_ext_validator{{"sa", "so"}};
myparser.add_option(file_name,
.long_id = "file",
.description = "Give me a file name with an absolute path.",
.validator = absolute_path_validator | my_file_ext_validator});
// an exception will be thrown if the user specifies a file name
// that is not an absolute path or does not have one of the file extension [sa,so]
try
{
myparser.parse();
}
catch (sharg::parser_error const & ext) // the user did something wrong
{
std::cerr << "[PARSER ERROR] " << ext.what() << "\n"; // customize your error message
return -1;
}
std::cout << "filename given by user passed validation: " << file_name << "\n";
return 0;
}
#include <sharg/all.hpp>
int main(int argc, char const ** argv)
{
sharg::parser myparser{"Test", argc, argv}; // initialize
myparser.add_option(mydir,
.long_id = "dir",
.description = "The directory containing the input files.",
// an exception will be thrown if the user specifies a directory that does not exists or has insufficient
// read permissions.
try
{
myparser.parse();
}
catch (sharg::parser_error const & ext) // the user did something wrong
{
std::cerr << "[PARSER ERROR] " << ext.what() << "\n"; // customize your error message
return -1;
}
std::cerr << "directory given by user passed validation: " << mydir << "\n";
return 0;
}
A validator that checks if a given path is a valid input directory.
Definition: validators.hpp:794
#include <sharg/all.hpp>
int main(int argc, char const ** argv)
{
sharg::parser myparser{"Test", argc, argv}; // initialize
myparser.add_option(myfile,
.long_id = "file",
.description = "The input file containing the sequences.",
.validator = sharg::input_file_validator{{"fa", "fasta"}}});
// an exception will be thrown if the user specifies a filename
// that does not have one of the extensions ["fa","fasta"] or if the file does not exist/is not readable.
try
{
myparser.parse();
}
catch (sharg::parser_error const & ext) // the user did something wrong
{
std::cerr << "[PARSER ERROR] " << ext.what() << "\n"; // customize your error message
return -1;
}
std::cerr << "filename given by user passed validation: " << myfile << "\n";
return 0;
}
#include <iostream>
int main()
{
// Default constructed validator has an empty extension list.
std::cerr << validator1.get_help_page_message() << '\n';
// Specify your own extensions for the input file.
std::cerr << validator2.get_help_page_message() << '\n';
return 0;
}
Provides some standard validators for (positional) options.
#include <sharg/all.hpp>
int main(int argc, char const ** argv)
{
sharg::parser myparser{"Test", argc, argv}; // initialize
myparser.add_option(mydir,
.long_id = "dir",
.description = "The output directory for storing the files.",
// an exception will be thrown if the user specifies a directory that cannot be created by the filesystem either
// because the parent path does not exists or the path has insufficient write permissions.
try
{
myparser.parse();
}
catch (sharg::parser_error const & ext) // the user did something wrong
{
std::cerr << "[PARSER ERROR] " << ext.what() << "\n"; // customize your error message
return -1;
}
std::cerr << "directory given by user passed validation: " << mydir << "\n";
return 0;
}
A validator that checks if a given path is a valid output directory.
Definition: validators.hpp:879
#include <sharg/all.hpp>
int main(int argc, char const ** argv)
{
sharg::parser myparser{"Test", argc, argv}; // initialize
// Use the sharg::output_file_open_options to indicate that you allow overwriting existing output files, ...
myparser.add_option(
myfile,
.long_id = "file",
.description = "Output file containing the processed sequences.",
.validator = sharg::output_file_validator{sharg::output_file_open_options::open_or_create,
{"fa", "fasta"}}});
// ... or that you will throw a sharg::validation_error if the user specified output file already exists
// No sharg::output_file_open_options is passed: The default sharg::output_file_open_options::create_new is used.
// Possible extensions can also be passed as separate arguments.
myparser.add_option(myfile,
.long_id = "file2",
.description = "Output file containing the processed sequences.",
.validator = sharg::output_file_validator{"fa", "fasta"}});
// an exception will be thrown if the user specifies a filename
// that does not have one of the extensions ["fa","fasta"],
// if the file already exists, or if the file is not writable.
try
{
myparser.parse();
}
catch (sharg::parser_error const & ext) // the user did something wrong
{
std::cerr << "[PARSER ERROR] " << ext.what() << "\n"; // customize your error message
return -1;
}
std::cerr << "filename given by user passed validation: " << myfile << "\n";
return 0;
}
A validator that checks if a given path is a valid output file.
Definition: validators.hpp:641
#include <iostream>
int main()
{
// Default constructed validator has an empty extension list.
std::cerr << validator1.get_help_page_message() << '\n';
// Specify your own extensions for the output file.
sharg::output_file_validator validator2{sharg::output_file_open_options::create_new,
std::vector{std::string{"exe"}, std::string{"fasta"}}};
std::cerr << validator2.get_help_page_message() << '\n';
// If you do not pass the output_file_open_options, the default of create_new is used.
std::cerr << validator3.get_help_page_message() << '\n';
// Instead of passing a std::vector<std::string>, you can also pass each extension as separate argument.
sharg::output_file_validator validator4{"exe", "fasta"};
std::cerr << validator4.get_help_page_message() << '\n';
return 0;
}