Make CommandLine print boolean defaults as text.
And
- clarify the documentation
- make example arguments more explicit
- make "--boolArg" toggle the value, not set to true (this enables
toggle on default true values)
--- a/src/core/examples/command-line-example.cc Thu Aug 15 14:45:42 2013 -0400
+++ b/src/core/examples/command-line-example.cc Wed Aug 07 10:36:45 2013 -0700
@@ -18,7 +18,8 @@
* Author: Peter D. Barnes, Jr. <pdbarnes@llnl.gov>
*/
-#include <iostream> // boolalpha
+#include <iostream>
+#include <iomanip>
#include <string>
#include "ns3/core-module.h"
@@ -27,11 +28,11 @@
using namespace ns3;
-std::string g_val4="val4 default";
+std::string g_cbArg="cbArg default";
-bool SetVal4 (std::string val)
+bool SetCbArg (std::string val)
{
- g_val4 = val;
+ g_cbArg = val;
return true;
}
@@ -39,25 +40,28 @@
int main (int argc, char *argv[])
{
- int val1 = 1;
- bool val2 = false;
- std::string val3 = "val3 default";
+ int intArg = 1;
+ bool boolArg = false;
+ std::string strArg = "strArg default";
CommandLine cmd;
cmd.Usage ("CommandLine example program.\n"
"\n"
"This little program demonstrates how to use CommandLine.");
- cmd.AddValue ("val1", "an int argument", val1);
- cmd.AddValue ("val2", "a bool argument", val2);
- cmd.AddValue ("val3", "a string argument", val3);
- cmd.AddValue ("val4", "a string via callback", MakeCallback (SetVal4));
+ cmd.AddValue ("intArg", "an int argument", intArg);
+ cmd.AddValue ("boolArg", "a bool argument", boolArg);
+ cmd.AddValue ("strArg", "a string argument", strArg);
+ cmd.AddValue ("cbArg", "a string via callback", MakeCallback (SetCbArg));
cmd.Parse (argc, argv);
- std::cout << "val1:\t" << val1 << std::endl;
- std::cout << "val2:\t" << std::boolalpha << val2
- << std::noboolalpha << std::endl;
- std::cout << "val3:\t\"" << val3 << "\"" << std::endl;
- std::cout << "val4:\t\"" << g_val4 << "\"" << std::endl;
+ std::cout << std::left
+ << std::setw (10) << "intArg:" << intArg << std::endl;
+ std::cout << std::setw (10) << "boolArg:"
+ << std::boolalpha << boolArg
+ << std::noboolalpha << std::endl;
+
+ std::cout << std::setw (10) << "strArg:" << "\"" << strArg << "\"" << std::endl;
+ std::cout << std::setw (10) << "cbArg:" << "\"" << g_cbArg << "\"" << std::endl;
return 0;
}
--- a/src/core/model/command-line.cc Thu Aug 15 14:45:42 2013 -0400
+++ b/src/core/model/command-line.cc Wed Aug 07 10:36:45 2013 -0700
@@ -21,7 +21,7 @@
#include <algorithm> // for transform
#include <cctype> // for tolower
#include <cstdlib> // for exit
-#include <iomanip> // for setw
+#include <iomanip> // for setw, boolalpha
#include "command-line.h"
#include "log.h"
@@ -152,7 +152,7 @@
NS_LOG_FUNCTION (this);
os << m_name << " [Program Arguments] [General Arguments]"
- << std::endl;
+ << std::endl;
if (m_usage.length ())
{
@@ -174,16 +174,16 @@
for (Items::const_iterator i = m_items.begin (); i != m_items.end (); ++i)
{
os << " --"
- << std::left << std::setw (width) << ( (*i)->m_name + ":")
- << std::right
- << (*i)->m_help;
+ << std::left << std::setw (width) << ( (*i)->m_name + ":")
+ << std::right
+ << (*i)->m_help;
if ( (*i)->HasDefault ())
{
os << " [" << (*i)->GetDefault () << "]";
- }
+ }
os << std::endl;
-}
+ }
}
os << std::endl;
@@ -226,7 +226,7 @@
TypeId tid;
if (!TypeId::LookupByNameFailSafe (type, &tid))
{
- NS_FATAL_ERROR ("Unknown type="<<type<<" in --PrintAttributes");
+ NS_FATAL_ERROR ("Unknown type=" << type << " in --PrintAttributes");
}
os << "Attributes for TypeId " << tid.GetName () << std::endl;
@@ -317,7 +317,7 @@
{
NS_LOG_FUNCTION (this << name << value);
- NS_LOG_DEBUG ("Handle arg name="<<name<<" value="<<value);
+ NS_LOG_DEBUG ("Handle arg name=" << name << " value=" << value);
if (name == "PrintHelp" || name == "help")
{
// method below never returns.
@@ -384,7 +384,7 @@
}
bool
-CommandLine::CallbackItem::Parse (std::string value)
+CommandLine::CallbackItem::Parse (const std::string value)
{
NS_LOG_FUNCTION (this);
NS_LOG_DEBUG ("CommandLine::CallbackItem::Parse \"" << value << "\"");
@@ -418,13 +418,27 @@
}
template <>
+std::string
+CommandLineHelper::GetDefault<bool> (const bool & val)
+{
+ std::ostringstream oss;
+ oss << std::boolalpha << val;
+ return oss.str ();
+}
+
+template <>
bool
CommandLineHelper::UserItemParse<bool> (const std::string value, bool & val)
{
std::string src = value;
std::transform(src.begin(), src.end(), src.begin(), ::tolower);
- if ( (src.length () == 0) || (src == "true") || (src == "t"))
+ if (src.length () == 0)
+ {
+ val = ! val;
+ return true;
+ }
+ else if ( (src == "true") || (src == "t") )
{
val = true;
return true;
--- a/src/core/model/command-line.h Thu Aug 15 14:45:42 2013 -0400
+++ b/src/core/model/command-line.h Wed Aug 07 10:36:45 2013 -0700
@@ -44,8 +44,25 @@
* \brief Parse command-line arguments
*
* Instances of this class can be used to parse command-line
- * arguments: programs can register new arguments with
- * CommandLine::AddValue.
+ * arguments. Programs can register a general usage message with
+ * CommandLine::Usage, and arguments with CommandLine::AddValue.
+ * POD argument variables will be set directly; more general arguments
+ * can be processed via a Callback.
+ *
+ * CommandLine also provides handlers for these standard arguments:
+ * \code
+ * --PrintGlobals: Print the list of globals.
+ * --PrintGroups: Print the list of groups.
+ * --PrintGroup=[group]: Print all TypeIds of group.
+ * --PrintTypeIds: Print all TypeIds.
+ * --PrintAttributes=[typeid]: Print all attributes of typeid.
+ * --PrintHelp: Print this help message.
+ * \endcode
+ *
+ * The more common \c --help is a synonym for \c --PrintHelp; an example
+ * is given below.
+ *
+ * Finally, CommandLine processes Attribute and GlobalValue arguments.
*
* In use, arguments are given in the form
* \code
@@ -55,18 +72,20 @@
* Toggles, corresponding to boolean arguments, can be given in any of
* the forms
* \code
- * --toggle-1 --toggle-2=1 --toggle-3=t --toggle-4=true
+ * --toggle1 --toggle2=1 --toggle3=t --toggle4=true
* \endcode
- * all of which set the corresponding boolean variable to true.
+ * The first form changes the state of toggle1 from its default;
+ * all the rest set the corresponding boolean variable to true.
+ * \c 0, \c f and \c false are accepted to set the variable to false.
*
- * In addition, this class can be used to set the
- * initial value of every attribute in the system with the
+ * CommandLine can set the initial value of every attribute in the system
+ * with the
* \c --TypeIdName::AttributeName=value syntax, for example
* \code
* --Application::StartTime=3s
* \endcode
*
- * This class can also be used to set the value of every GlobalValue
+ * CommandLine can also set the value of every GlobalValue
* in the system with the \c --GlobalValueName=value syntax, for example
* \code
* --SchedulerType=HeapScheduler
@@ -76,33 +95,37 @@
* The heart of that example is this code:
*
* \code
- * int var1 = 1;
- * bool var2 = false;
- * std::string var3 = "";
+ * int intArg = 1;
+ * bool boolArg = false;
+ * std::string strArg = "strArg default";
*
* CommandLine cmd;
* cmd.Usage ("CommandLine example program.\n"
* "\n"
* "This little program demonstrates how to use CommandLine.");
- * cmd.AddValue ("val1", "an int argument", val1);
- * cmd.AddValue ("val2", "a bool argument", val2);
- * cmd.AddValue ("val3", "a string argument", val3);
+ * cmd.AddValue ("intArg", "an int argument", intArg);
+ * cmd.AddValue ("boolArg", "a bool argument", boolArg);
+ * cmd.AddValue ("strArg", "a string argument", strArg);
+ * cmd.AddValue ("cbArg", "a string via callback", MakeCallback (SetCbArg));
* cmd.Parse (argc, argv);
* \endcode
- * after which it prints the values of each variable.
+ * after which it prints the values of each variable. (The \c SetCbArg function
+ * is not shown.)
*
* Here is the output from a few runs of that program:
*
* \code
* $ ./waf --run="command-line-example"
- * val1: 1
- * val2: 0
- * val3: ""
+ * intArg: 1
+ * boolArg: false
+ * strArg: "strArg default"
+ * cbArg: "cbArg default"
*
- * $ ./waf --run="command-line-example --val1=2 --val2 --val3=Hello"
- * val1: 2
- * val2: 1
- * val3: "Hello"
+ * $ ./waf --run="command-line-example --intArg=2 --boolArg --strArg=Hello --cbArg=World"
+ * intArg: 2
+ * boolArg: true
+ * strArg: "Hello"
+ * cbArg: "World"
*
* $ ./waf --run="command-line-example --help"
* ns3-dev-command-line-example-debug [Program Arguments] [General Arguments]
@@ -112,9 +135,10 @@
* This little program demonstrates how to use CommandLine.
*
* Program Arguments:
- * --val1: an int argument
- * --val2: a bool argument
- * --val3: a string argument
+ * --intArg: an int argument [1]
+ * --boolArg: a bool argument [false]
+ * --strArg: a string argument [strArg default]
+ * --cbArg: a string via callback
*
* General Arguments:
* --PrintGlobals: Print the list of globals.
@@ -149,7 +173,7 @@
/**
* Supply the program usage and documentation.
*
- * \param usage Program usage message to write with help.
+ * \param usage Program usage message to write with \c --help.
*/
void Usage (const std::string usage);
@@ -172,9 +196,12 @@
* Add a program argument, using a Callback to parse the value
*
* \param name the name of the program-supplied argument
- * \param help the help text used by \c \-\-PrintHelp
- * \param callback a Callback function that will be invoked to parse
- * and collect the value. This is normally used by language bindings.
+ * \param help the help text used by \c --help
+ * \param callback a Callback function that will be invoked to parse and
+ * store the value.
+ *
+ * The callback should have the signature
+ * <tt>bool callback (const std::string value)</tt>
*/
void AddValue (const std::string &name,
const std::string &help,
@@ -237,7 +264,7 @@
* \param value the string representation
* \return true if parsing the value succeeded
*/
- virtual bool Parse (std::string value) = 0;
+ virtual bool Parse (const std::string value) = 0;
/**
* \return true if this item have a default value?
*/
@@ -262,7 +289,7 @@
* \param value the string representation
* \return true if parsing the value succeeded
*/
- virtual bool Parse (std::string value);
+ virtual bool Parse (const std::string value);
bool HasDefault () const;
std::string GetDefault () const;
@@ -284,7 +311,7 @@
* \param value the string representation
* \return true if parsing the value succeeded
*/
- virtual bool Parse (std::string value);
+ virtual bool Parse (const std::string value);
Callback<bool, std::string> m_callback; /**< The Callback */
};
@@ -329,15 +356,19 @@
std::string m_name; /**< The program name */
}; // class CommandLine
+
+/** \ingroup commandline
+ * \defgroup commandlinehelper Helpers to specialize on bool
+ */
/**
- * \ingroup commandline
- * Helpers for CommandLine
+ * \ingroup commandlinehelper
+ * \brief Helpers for CommandLine to specialize on bool
*/
namespace CommandLineHelper {
/**
- * \ingroup commandline
- * \brief Helper to specialize UserItem on bool
+ * \ingroup commandlinehelper
+ * \brief Helper to specialize UserItem::Parse on bool
*
* \param value the argument name
* \param val the argument location
@@ -350,6 +381,20 @@
bool UserItemParse<bool> (const std::string value, bool & val);
/**@}*/
+ /**
+ * \ingroup commandlinehelper
+ * \brief Helper to specialize UserItem::GetDefault on bool
+ *
+ * \param val the argument value
+ * \return the string representation of value
+ * @{
+ */
+ template <typename T>
+ std::string GetDefault (const T & val);
+ template <>
+ std::string GetDefault<bool> (const bool & val);
+ /**@}*/
+
} // namespace CommandLineHelper
@@ -388,15 +433,22 @@
std::string
CommandLine::UserItem<T>::GetDefault () const
{
+ return CommandLineHelper::GetDefault<T> (*m_valuePtr);
+}
+
+template <typename T>
+std::string
+CommandLineHelper::GetDefault (const T & val)
+{
std::ostringstream oss;
- oss << *m_valuePtr;
+ oss << val;
return oss.str ();
}
template <typename T>
bool
-CommandLine::UserItem<T>::Parse (std::string value)
+CommandLine::UserItem<T>::Parse (const std::string value)
{
return CommandLineHelper::UserItemParse<T> (value, *m_valuePtr);
}
@@ -411,26 +463,6 @@
return !iss.bad () && !iss.fail ();
}
-/**
- * \brief Overloaded operator << to print program usage (shortcut for CommandLine::PrintHelper)
- * \see CommandLine::PrintHelper
- *
- * Example usage:
- * @code
- * CommandLine cmd;
- * cmd.Parse (argc, argv);
- * ...
- *
- * std::cerr << cmd;
- * @endcode
- */
-inline std::ostream &
-operator << (std::ostream &os, const CommandLine &cmd)
-{
- cmd.PrintHelp (os);
- return os;
-}
-
} // namespace ns3
#endif /* COMMAND_LINE_H */