Ticket #1131: program_options_implicit_2.patch

File program_options_implicit_2.patch, 7.6 KB (added by Bryan Green <bgreen0@…>, 15 years ago)

updated patch, per mailing list comments

  • boost/program_options/detail/value_semantic.hpp

     
    1616    std::string
    1717    typed_value<T, charT>::name() const
    1818    {
    19         if (!m_default_value.empty() && !m_default_value_as_text.empty()) {
     19        if (!m_implicit_value.empty() && !m_implicit_value_as_text.empty()) {
     20            std::string msg = "[=arg(=" + m_implicit_value_as_text + ")]";
     21            if (!m_default_value.empty() && !m_default_value_as_text.empty())
     22                msg += " (=" + m_default_value_as_text + ")";
     23            return msg;
     24        }
     25        else if (!m_default_value.empty() && !m_default_value_as_text.empty()) {
    2026            return arg + " (=" + m_default_value_as_text + ")";
    2127        } else {
    2228            return arg;
     
    155161    xparse(boost::any& value_store,
    156162           const std::vector<std::basic_string<charT> >& new_tokens) const
    157163    {
    158         validate(value_store, new_tokens, (T*)0, 0);
     164        // If no tokens were given, and the option accepts an implicit
     165        // value, then assign the implicit value as the stored value;
     166        // otherwise, validate the user-provided token(s).
     167        if (new_tokens.empty() && !m_implicit_value.empty())
     168            value_store = m_implicit_value;
     169        else
     170            validate(value_store, new_tokens, (T*)0, 0);
    159171    }
    160172
    161173    template<class T>
  • boost/program_options/value_semantic.hpp

     
    204204            return this;
    205205        }
    206206
     207        /** Specifies an implicit value, which will be used
     208            if the option is given, but without an adjacent value.
     209            Using this implies that an explicit value is optional, but if
     210            given, must be strictly adjacent to the option, i.e.: '-ovalue'
     211            or '--option=value'.  Giving '-o' or '--option' will cause the
     212            implicit value to be applied.
     213        */
     214        typed_value* implicit_value(const T &v)
     215        {
     216            m_implicit_value = boost::any(v);
     217            m_implicit_value_as_text =
     218                boost::lexical_cast<std::string>(v);
     219            return this;
     220        }
     221
     222        /** Specifies an implicit value, which will be used
     223            if the option is given, but without an adjacent value.
     224            Using this implies that an explicit value is optional, but if
     225            given, must be strictly adjacent to the option, i.e.: '-ovalue'
     226            or '--option=value'.  Giving '-o' or '--option' will cause the
     227            implicit value to be applied.
     228            Unlike the above overload, the type 'T' need not provide
     229            operator<< for ostream, but textual representation of default
     230            value must be provided by the user.
     231        */
     232        typed_value* implicit_value(const T &v, const std::string& textual)
     233        {
     234            m_implicit_value = boost::any(v);
     235            m_implicit_value_as_text = textual;
     236            return this;
     237        }
     238
    207239        /** Specifies a function to be called when the final value
    208240            is determined. */
    209241        typed_value* notifier(function1<void, const T&> f)
     
    243275
    244276        unsigned min_tokens() const
    245277        {
    246             if (m_zero_tokens) {
     278            if (m_zero_tokens || !m_implicit_value.empty()) {
    247279                return 0;
    248280            } else {
    249281                return 1;
     
    301333        // as boost::optional to avoid unnecessary instantiations.
    302334        boost::any m_default_value;
    303335        std::string m_default_value_as_text;
     336        boost::any m_implicit_value;
     337        std::string m_implicit_value_as_text;
    304338        bool m_composing, m_implicit, m_multitoken, m_zero_tokens;
    305339        boost::function1<void, const T&> m_notifier;
    306340    };
  • libs/program_options/test/variable_map_test.cpp

     
    102102    BOOST_CHECK(vm3["vee"].as<string>() == "42");
    103103    BOOST_CHECK(vm3["voo"].as<string>() == "1");
    104104    BOOST_CHECK(vm3["iii"].as<int>() == 123);
     105
     106    options_description desc3;
     107    desc3.add_options()
     108    ("imp", po::value<int>()->implicit_value(100))
     109    ("iim", po::value<int>()->implicit_value(200)->default_value(201))
     110    ("mmp,m", po::value<int>()->implicit_value(123)->default_value(124))
     111    ;
     112    char* cmdline6_[] = {  "--imp=1 -m" };
     113    vector<string> cmdline6 = sv(cmdline6_,
     114                                 sizeof(cmdline6_)/sizeof(cmdline6_[0]));
     115    parsed_options a6 = command_line_parser(cmdline6).options(desc3).run();
     116
     117    variables_map vm4;
     118    store(a6, vm4);
     119    notify(vm4);
     120    BOOST_REQUIRE(vm4.size() == 3);
     121    BOOST_CHECK(vm4["imp"].as<int>() == 1);
     122    BOOST_CHECK(vm4["iim"].as<int>() == 201);
     123    BOOST_CHECK(vm4["mmp"].as<int>() == 123);
    105124}
    106125
    107126int stored_value;
  • libs/program_options/src/cmdline.cpp

     
    329329           
    330330            max_tokens -= opt.value.size();
    331331
     332            // A value is optional if min_tokens == 0, but max_tokens > 0.
     333            // If a value is optional, it must appear in opt.value (because
     334            // it was 'adjacent'.  Otherwise, remove the expectation of a
     335            // non-adjacent value.  (For now, we just check max_tokens == 1,
     336            // as there is no current support for max_tokens>1)
     337            if (min_tokens == 0 && max_tokens == 1 && opt.value.empty())
     338                --max_tokens;
     339
    332340            // Everything's OK, move the values to the result.           
    333341            for(;!other_tokens.empty() && max_tokens--; ) {
    334342                opt.value.push_back(other_tokens[0]);
  • libs/program_options/example/options_description.cpp

     
    2626{
    2727    try {
    2828        int opt;
     29        int portnum;
    2930        po::options_description desc("Allowed options");
    3031        desc.add_options()
    3132            ("help", "produce help message")
    3233            ("optimization", po::value<int>(&opt)->default_value(10),
    3334                  "optimization level")
     35            ("verbose,v", po::value<int>()->implicit_value(1),
     36                  "enable verbosity (optionally specify level)")
     37            ("listen,l", po::value<int>(&portnum)->implicit_value(1001)
     38                  ->default_value(0,"no"),
     39                  "listen on a port.")
    3440            ("include-path,I", po::value< vector<string> >(),
    3541                  "include path")
    3642            ("input-file", po::value< vector<string> >(), "input file")
     
    6268                 << vm["input-file"].as< vector<string> >() << "\n";
    6369        }
    6470
     71        if (vm.count("verbose")) {
     72            cout << "Verbosity enabled.  Level is " << vm["verbose"].as<int>()
     73                 << "\n";
     74        }
     75
    6576        cout << "Optimization level is " << opt << "\n";               
     77
     78        cout << "Listen port is " << portnum << "\n";               
    6679    }
    6780    catch(exception& e)
    6881    {