Index: boost/program_options/errors.hpp =================================================================== --- boost/program_options/errors.hpp (Revision 57020) +++ boost/program_options/errors.hpp (Arbeitskopie) @@ -38,6 +38,14 @@ std::string tokens, msg; }; + /** Class thrown when a required/mandatory option is missing */ + class BOOST_PROGRAM_OPTIONS_DECL required_option : public error { + public: + required_option(const std::string& name) + : error(std::string("missing required option ").append(name)) + {} + }; + /** Class thrown when option name is not recognized. */ class BOOST_PROGRAM_OPTIONS_DECL unknown_option : public error { public: Index: boost/program_options/value_semantic.hpp =================================================================== --- boost/program_options/value_semantic.hpp (Revision 57020) +++ boost/program_options/value_semantic.hpp (Arbeitskopie) @@ -44,6 +44,11 @@ */ virtual bool is_composing() const = 0; + /** Returns true if value must be given. Non-optional value + + */ + virtual bool is_required() const = 0; + /** Parses a group of tokens that specify a value of option. Stores the result in 'value_store', using whatever representation is desired. May be be called several times if value of the same @@ -132,6 +137,8 @@ bool is_composing() const { return false; } + bool is_required() const { return false; } + /** If 'value_store' is already initialized, or new_tokens has more than one elements, throws. Otherwise, assigns the first string from 'new_tokens' to 'value_store', without @@ -177,7 +184,8 @@ the value when it's known. The parameter can be NULL. */ typed_value(T* store_to) : m_store_to(store_to), m_composing(false), - m_multitoken(false), m_zero_tokens(false) + m_multitoken(false), m_zero_tokens(false), + m_required(false) {} /** Specifies default value, which will be used @@ -265,6 +273,12 @@ m_zero_tokens = true; return this; } + + typed_value* required() + { + m_required = true; + return this; + } public: // value semantic overrides @@ -292,7 +306,9 @@ } } + bool is_required() const { return m_required; } + /** Creates an instance of the 'validator' class and calls its operator() to perform the actual conversion. */ void xparse(boost::any& value_store, @@ -335,7 +351,7 @@ std::string m_default_value_as_text; boost::any m_implicit_value; std::string m_implicit_value_as_text; - bool m_composing, m_implicit, m_multitoken, m_zero_tokens; + bool m_composing, m_implicit, m_multitoken, m_zero_tokens, m_required; boost::function1 m_notifier; }; Index: libs/program_options/src/value_semantic.cpp =================================================================== --- libs/program_options/src/value_semantic.cpp (Revision 57020) +++ libs/program_options/src/value_semantic.cpp (Arbeitskopie) @@ -171,13 +171,15 @@ check_first_occurrence(v); string s(get_single_string(xs)); if (!s.empty() && ( - (*s.begin() == '\'' && *s.rbegin() == '\'' || - *s.begin() == '"' && *s.rbegin() == '"'))) + ((*s.begin() == '\'' && *s.rbegin() == '\'') || + (*s.begin() == '"' && *s.rbegin() == '"')))) { v = any(s.substr(1, s.size()-2)); } else + { v = any(s); + } } #if !defined(BOOST_NO_STD_WSTRING) @@ -186,8 +188,8 @@ { check_first_occurrence(v); wstring s(get_single_string(xs)); - if (*s.begin() == L'\'' && *s.rbegin() == L'\'' || - *s.begin() == L'"' && *s.rbegin() == L'"') + if ((*s.begin() == L'\'' && *s.rbegin() == L'\'') || + (*s.begin() == L'"' && *s.rbegin() == L'"')) v = any(s.substr(1, s.size()-2)); else v = any(s); Index: libs/program_options/src/cmdline.cpp =================================================================== --- libs/program_options/src/cmdline.cpp (Revision 57020) +++ libs/program_options/src/cmdline.cpp (Arbeitskopie) @@ -309,8 +309,25 @@ } } result.swap(result2); - + // This checks if all required options occur + const std::vector< shared_ptr >& + all_options = m_desc->options(); + for (unsigned i = 0; i < all_options.size(); ++i) { + if (all_options[i]->semantic()->is_required()) { + bool found_required = false; + for (unsigned j = 0; !found_required && j < result.size(); ++j) { + if (all_options[i]->key(result[j].string_key) == result[j].string_key) { // REVISIT, is this compare ok? + found_required = true; + } + } + if (!found_required) { + boost::throw_exception(required_option( + all_options[i]->format_name())); + } + } + } + // Assign position keys to positional options. int position_key = 0; for(unsigned i = 0; i < result.size(); ++i) {