Improve CCmdArgs (a generic command line parser in NeL Misc), fixes #257
This commit is contained in:
parent
4f24faebd6
commit
a51b0e6f6a
3 changed files with 501 additions and 127 deletions
|
@ -31,36 +31,86 @@ namespace NLMISC
|
||||||
class CCmdArgs
|
class CCmdArgs
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Sets the command line and init _Args variable. You must call this before calling main()
|
CCmdArgs();
|
||||||
void setArgs (int argc, const char **argv);
|
|
||||||
|
|
||||||
/// Sets the command line and init _Args variable. You must call this before calling main()
|
struct TArg
|
||||||
void setArgs (const char *args);
|
{
|
||||||
|
std::string shortName; // short argument. Eg: o for -o
|
||||||
|
std::string longName; // long argument. Eg: output for --output
|
||||||
|
|
||||||
|
std::string helpName; // name of argument in help. Eg: <output directory>
|
||||||
|
std::string helpDescription; // description of argument in help. Eg: Specifies the directory where to write generated files
|
||||||
|
|
||||||
|
bool found; // all values for this argument
|
||||||
|
std::vector<std::string> values; // all values for this argument
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<TArg> TArgs;
|
||||||
|
|
||||||
|
/// Add a TArg structure to arguments list.
|
||||||
|
void addArg(const TArg &arg);
|
||||||
|
|
||||||
|
/// Add an full argument to arguments list.
|
||||||
|
/// shortName is "p" of the argument is -p
|
||||||
|
/// longName is "print" of the argument is --print
|
||||||
|
/// helpName is the name that will be displayed in help if it's a required argument
|
||||||
|
/// helpDescription is the description of the argument that will be displayed in help
|
||||||
|
void addArg(const std::string &shortName, const std::string &longName, const std::string &helpName, const std::string &helpDescription);
|
||||||
|
|
||||||
|
/// Add a required argument to arguments list.
|
||||||
|
/// helpName is the name that will be displayed in help if it's a required argument
|
||||||
|
/// helpDescription is the description of the argument that will be displayed in help
|
||||||
|
void addArg(const std::string &helpName, const std::string &helpDescription);
|
||||||
|
|
||||||
|
/// Parse the command line from main() parameters argc and argv and process default arguments.
|
||||||
|
bool parse(int argc, char **argv);
|
||||||
|
|
||||||
|
/// Parse the command line from a std::string and process default arguments.
|
||||||
|
bool parse(const std::string &args);
|
||||||
|
|
||||||
|
/// Parse the command linefrom a std::vector<std::string> and process default arguments.
|
||||||
|
bool parse(const std::vector<std::string> &args);
|
||||||
|
|
||||||
/// Returns arguments of the program pass from the user to the program using parameters (ie: "myprog param1 param2")
|
/// Returns arguments of the program pass from the user to the program using parameters (ie: "myprog param1 param2")
|
||||||
const NLMISC::CVectorSString &getArgs () const { return _Args; }
|
const TArgs& getArgs() const { return _Args; }
|
||||||
|
|
||||||
/// Returns true if the argument if present in the command line (ie: haveArg('p') will return true if -p is in the command line)
|
/// Returns true if the argument if present in the command line (ie: haveArg("p") will return true if -p is in the command line)
|
||||||
bool haveArg (char argName) const;
|
bool haveArg(const std::string &argName) const;
|
||||||
|
|
||||||
/** Returns the parameter linked to an option
|
/** Returns the parameters linked to an option
|
||||||
* getArg('p') will return toto if -ptoto is in the command line
|
* getArg("p") will return toto if -ptoto is in the command line
|
||||||
* getArg('p') will return C:\Documents and Settings\toto.tmp if -p"C:\Documents and Settings\toto.tmp" is in the command line
|
* getArg("p") will return C:\Documents and Settings\toto.tmp if -p"C:\Documents and Settings\toto.tmp" is in the command line
|
||||||
* It'll thrown an Exception if the argName is not found
|
|
||||||
*/
|
*/
|
||||||
std::string getArg (char argName) const;
|
std::vector<std::string> getArg(const std::string &argName) const;
|
||||||
|
|
||||||
/// return true if named long arg is present on the commandline
|
/// return true if named long arg is present on the commandline
|
||||||
/// eg haveLongArg("toto") returns true if "--toto" or "--toto=xxx" can be found on commandline
|
/// eg haveLongArg("toto") returns true if "--toto" or "--toto=xxx" can be found on commandline
|
||||||
bool haveLongArg (const char* argName) const;
|
bool haveLongArg(const std::string &argName) const;
|
||||||
|
|
||||||
/// returns the value associated with the given named argument
|
/// returns values associated with the given named argument
|
||||||
/// both "--toto=xxx" and "--toto xxx" are acceptable
|
/// both "--toto=xxx" and "--toto xxx" are acceptable
|
||||||
/// quotes round arguments are stripped
|
/// quotes round arguments are stripped
|
||||||
std::string getLongArg (const char* argName) const;
|
std::vector<std::string> getLongArg(const std::string &argName) const;
|
||||||
|
|
||||||
|
/// return true if there are arguments that are required
|
||||||
|
bool needRequiredArg() const;
|
||||||
|
|
||||||
|
/// return true if required or optional args are present on the commandline
|
||||||
|
bool haveRequiredArg() const;
|
||||||
|
|
||||||
|
/// Returns all additional required parameters
|
||||||
|
std::vector<std::string> getRequiredArg() const;
|
||||||
|
|
||||||
|
/// Display help of the program.
|
||||||
|
void displayHelp();
|
||||||
|
|
||||||
|
/// Display version of the program.
|
||||||
|
void displayVersion();
|
||||||
protected:
|
protected:
|
||||||
|
std::string _ProgramName;
|
||||||
|
|
||||||
/// Array of arguments pass from the command line
|
/// Array of arguments pass from the command line
|
||||||
NLMISC::CVectorSString _Args;
|
TArgs _Args;
|
||||||
}; // class CCmdArgs
|
}; // class CCmdArgs
|
||||||
|
|
||||||
}; // NAMESPACE NLMISC
|
}; // NAMESPACE NLMISC
|
||||||
|
|
|
@ -18,12 +18,12 @@
|
||||||
// Includes
|
// Includes
|
||||||
//
|
//
|
||||||
#include "stdmisc.h"
|
#include "stdmisc.h"
|
||||||
|
|
||||||
#include "nel/misc/types_nl.h"
|
|
||||||
#include "nel/misc/sstring.h"
|
|
||||||
|
|
||||||
#include "nel/misc/cmd_args.h"
|
#include "nel/misc/cmd_args.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG_NEW
|
#ifdef DEBUG_NEW
|
||||||
#define new DEBUG_NEW
|
#define new DEBUG_NEW
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,114 +31,170 @@
|
||||||
namespace NLMISC
|
namespace NLMISC
|
||||||
{
|
{
|
||||||
|
|
||||||
bool CCmdArgs::haveArg(char argName) const
|
CCmdArgs::CCmdArgs()
|
||||||
{
|
{
|
||||||
for(uint32 i = 0; i < _Args.size(); i++)
|
// add help
|
||||||
|
addArg("h", "help", "", "Display this help");
|
||||||
|
|
||||||
|
// add version
|
||||||
|
addArg("v", "version", "", "Display version of this program");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCmdArgs::addArg(const TArg &arg)
|
||||||
|
{
|
||||||
|
_Args.push_back(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCmdArgs::addArg(const std::string &shortName, const std::string &longName, const std::string &helpName, const std::string &helpDescription)
|
||||||
|
{
|
||||||
|
TArg arg;
|
||||||
|
arg.shortName = shortName;
|
||||||
|
arg.longName = longName;
|
||||||
|
arg.helpName = helpName;
|
||||||
|
arg.helpDescription = helpDescription;
|
||||||
|
arg.found = false;
|
||||||
|
|
||||||
|
addArg(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCmdArgs::addArg(const std::string &helpName, const std::string &helpDescription)
|
||||||
|
{
|
||||||
|
TArg arg;
|
||||||
|
arg.helpName = helpName;
|
||||||
|
arg.helpDescription = helpDescription;
|
||||||
|
arg.found = false;
|
||||||
|
|
||||||
|
addArg(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCmdArgs::haveArg(const std::string &argName) const
|
||||||
|
{
|
||||||
|
// process each argument
|
||||||
|
for(uint i = 0; i < _Args.size(); i)
|
||||||
{
|
{
|
||||||
if(_Args[i].size() >= 2 && _Args[i][0] == '-')
|
const TArg &arg = _Args[i];
|
||||||
{
|
|
||||||
if(_Args[i][1] == argName)
|
// return true if long arg found
|
||||||
{
|
if (arg.shortName == argName) return arg.found;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CCmdArgs::getArg(char argName) const
|
std::vector<std::string> CCmdArgs::getArg(const std::string &argName) const
|
||||||
{
|
{
|
||||||
for(uint32 i = 0; i < _Args.size(); i++)
|
// process each argument
|
||||||
|
for(uint i = 0; i < _Args.size(); ++i)
|
||||||
{
|
{
|
||||||
if(_Args[i].size() >= 2 && _Args[i][0] == '-')
|
const TArg &arg = _Args[i];
|
||||||
{
|
|
||||||
if(_Args[i][1] == argName)
|
|
||||||
{
|
|
||||||
/* Remove the first and last '"' :
|
|
||||||
-c"C:\Documents and Settings\toto.tmp"
|
|
||||||
will return :
|
|
||||||
C:\Documents and Settings\toto.tmp
|
|
||||||
*/
|
|
||||||
uint begin = 2;
|
|
||||||
if(_Args[i].size() < 3)
|
|
||||||
return "";
|
|
||||||
//throw Exception ("Parameter '-%c' is malformed, missing content", argName);
|
|
||||||
|
|
||||||
if(_Args[i][begin] == '"')
|
// return values if short arg found
|
||||||
begin++;
|
if (arg.shortName == argName && arg.found) return arg.values;
|
||||||
|
|
||||||
// End
|
|
||||||
uint size = (uint)_Args[i].size();
|
|
||||||
if(size && _Args[i][size-1] == '"')
|
|
||||||
size--;
|
|
||||||
size = (uint)(std::max((int)0, (int)size-(int)begin));
|
|
||||||
return _Args[i].substr(begin, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
throw Exception("Parameter '-%c' is not found in command line", argName);
|
|
||||||
|
// return an empty vector
|
||||||
|
return std::vector<std::string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCmdArgs::haveLongArg(const char* argName) const
|
bool CCmdArgs::haveLongArg(const std::string &argName) const
|
||||||
{
|
{
|
||||||
for(uint32 i = 0; i < _Args.size(); i++)
|
// process each argument
|
||||||
|
for(uint i = 0; i < _Args.size(); ++i)
|
||||||
{
|
{
|
||||||
if(_Args[i].left(2)=="--" && _Args[i].leftCrop(2).splitTo('=')==argName)
|
const TArg &arg = _Args[i];
|
||||||
{
|
|
||||||
|
// return true if long arg found
|
||||||
|
if (arg.longName == argName) return arg.found;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> CCmdArgs::getLongArg(const std::string &argName) const
|
||||||
|
{
|
||||||
|
// process each argument
|
||||||
|
for(uint i = 0; i < _Args.size(); ++i)
|
||||||
|
{
|
||||||
|
const TArg &arg = _Args[i];
|
||||||
|
|
||||||
|
// return values if long arg found
|
||||||
|
if (arg.longName == argName && arg.found) return arg.values;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return an empty vector
|
||||||
|
return std::vector<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCmdArgs::needRequiredArg() const
|
||||||
|
{
|
||||||
|
// process each argument
|
||||||
|
for(uint i = 0; i < _Args.size(); ++i)
|
||||||
|
{
|
||||||
|
const TArg &arg = _Args[i];
|
||||||
|
|
||||||
|
// they don't have any short or long name, but need a name in help
|
||||||
|
if (arg.shortName.empty() && arg.longName.empty() && !arg.helpName.empty())
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CCmdArgs::getLongArg (const char* argName) const
|
bool CCmdArgs::haveRequiredArg() const
|
||||||
{
|
{
|
||||||
for (uint32 i = 0; i < _Args.size(); i++)
|
// process each argument
|
||||||
{
|
for(uint i = 0; i < _Args.size(); ++i)
|
||||||
if (_Args[i].left(2)=="--" && _Args[i].leftCrop(2).splitTo('=')==argName)
|
{
|
||||||
{
|
const TArg &arg = _Args[i];
|
||||||
NLMISC::CSString val= _Args[i].splitFrom('=');
|
|
||||||
if (!val.empty())
|
|
||||||
{
|
|
||||||
return val.unquoteIfQuoted();
|
|
||||||
}
|
|
||||||
if (i+1<_Args.size() && _Args[i+1].c_str()[0]!='-')
|
|
||||||
{
|
|
||||||
return _Args[i+1].unquoteIfQuoted();
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::string();
|
// they don't have any short or long name, but need a name in help
|
||||||
}
|
if (arg.shortName.empty() && arg.longName.empty() && !arg.helpName.empty())
|
||||||
|
return !arg.values.empty();
|
||||||
}
|
}
|
||||||
return std::string();
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCmdArgs::setArgs(const char *args)
|
std::vector<std::string> CCmdArgs::getRequiredArg() const
|
||||||
{
|
{
|
||||||
_Args.push_back ("<ProgramName>");
|
// process each argument
|
||||||
|
for(uint i = 0; i < _Args.size(); ++i)
|
||||||
|
{
|
||||||
|
const TArg &arg = _Args[i];
|
||||||
|
|
||||||
std::string sargs (args);
|
// they don't have any short or long name, but need a name in help
|
||||||
|
if (arg.shortName.empty() && arg.longName.empty() && !arg.helpName.empty())
|
||||||
|
return arg.values;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return an empty vector
|
||||||
|
return std::vector<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCmdArgs::parse(const std::string &args)
|
||||||
|
{
|
||||||
|
std::vector<std::string> argv;
|
||||||
std::string::size_type pos1 = 0, pos2 = 0;
|
std::string::size_type pos1 = 0, pos2 = 0;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// Look for the first non space character
|
// Look for the first non space character
|
||||||
pos1 = sargs.find_first_not_of (" ", pos2);
|
pos1 = args.find_first_not_of (" ", pos2);
|
||||||
if(pos1 == std::string::npos) break;
|
if(pos1 == std::string::npos) break;
|
||||||
|
|
||||||
// Look for the first space or "
|
// Look for the first space or "
|
||||||
pos2 = sargs.find_first_of (" \"", pos1);
|
pos2 = args.find_first_of (" \"", pos1);
|
||||||
if(pos2 != std::string::npos)
|
if(pos2 != std::string::npos)
|
||||||
{
|
{
|
||||||
// " ?
|
// " ?
|
||||||
if(sargs[pos2] == '"')
|
if(args[pos2] == '"')
|
||||||
{
|
{
|
||||||
// Look for the final \"
|
// Look for the final \"
|
||||||
pos2 = sargs.find_first_of ("\"", pos2+1);
|
pos2 = args.find_first_of ("\"", pos2+1);
|
||||||
if(pos2 != std::string::npos)
|
if(pos2 != std::string::npos)
|
||||||
{
|
{
|
||||||
// Look for the first space
|
// Look for the first space
|
||||||
pos2 = sargs.find_first_of (" ", pos2+1);
|
pos2 = args.find_first_of (" ", pos2+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,18 +202,277 @@ void CCmdArgs::setArgs(const char *args)
|
||||||
// Compute the size of the string to extract
|
// Compute the size of the string to extract
|
||||||
std::string::difference_type length = (pos2 != std::string::npos) ? pos2-pos1 : std::string::npos;
|
std::string::difference_type length = (pos2 != std::string::npos) ? pos2-pos1 : std::string::npos;
|
||||||
|
|
||||||
std::string tmp = sargs.substr (pos1, length);
|
std::string tmp = args.substr (pos1, length);
|
||||||
_Args.push_back (tmp);
|
argv.push_back (tmp);
|
||||||
}
|
}
|
||||||
while(pos2 != std::string::npos);
|
while(pos2 != std::string::npos);
|
||||||
|
|
||||||
|
return parse(argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCmdArgs::setArgs(int argc, const char **argv)
|
bool CCmdArgs::parse(int argc, char **argv)
|
||||||
{
|
{
|
||||||
for (sint i = 0; i < argc; i++)
|
// convert C strings to STL strings
|
||||||
|
std::vector<std::string> args;
|
||||||
|
|
||||||
|
for(sint i = 0; i < argc; ++i)
|
||||||
{
|
{
|
||||||
_Args.push_back (argv[i]);
|
args.push_back(argv[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return parse(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCmdArgs::parse(const std::vector<std::string> &argv)
|
||||||
|
{
|
||||||
|
// no parameters
|
||||||
|
if (argv.empty()) return false;
|
||||||
|
|
||||||
|
// first argument is always the program name
|
||||||
|
_ProgramName = CFile::getFilename(argv.front());
|
||||||
|
|
||||||
|
// arguments count
|
||||||
|
uint argc = argv.size();
|
||||||
|
|
||||||
|
// process each argument
|
||||||
|
for (sint i = 1; i < argc; i++)
|
||||||
|
{
|
||||||
|
std::string name = argv[i];
|
||||||
|
|
||||||
|
#ifdef NL_OS_WINDOWS
|
||||||
|
// support / and - under Windows, arguments should be at least 2 characters
|
||||||
|
if (name.size() > 1 && (name[0] == '-' || name[0] == '/'))
|
||||||
|
#else
|
||||||
|
if (name.size() > 1 && name[0] == '-')
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
// it's a long name if using --
|
||||||
|
bool useLongName = name[0] == '-' && name[1] == '-';
|
||||||
|
|
||||||
|
// extract argument name
|
||||||
|
name = name.substr(useLongName ? 2:1);
|
||||||
|
|
||||||
|
std::string value;
|
||||||
|
|
||||||
|
if (useLongName)
|
||||||
|
{
|
||||||
|
// look if using = to define value
|
||||||
|
std::string::size_type pos = name.find('=');
|
||||||
|
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
// value is second part, name the first one
|
||||||
|
value = name.substr(pos+1);
|
||||||
|
name = name.substr(0, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (name.length() > 1)
|
||||||
|
{
|
||||||
|
value = name.substr(1);
|
||||||
|
name = name.substr(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// process each argument definition
|
||||||
|
for(uint j = 0; j < _Args.size(); ++j)
|
||||||
|
{
|
||||||
|
TArg &arg = _Args[j];
|
||||||
|
|
||||||
|
// only process arguments of the right type
|
||||||
|
if ((useLongName && name != arg.longName) || (!useLongName && name != arg.shortName)) continue;
|
||||||
|
|
||||||
|
// argument is found
|
||||||
|
arg.found = true;
|
||||||
|
|
||||||
|
// another argument is required
|
||||||
|
if (!arg.helpName.empty())
|
||||||
|
{
|
||||||
|
// if the value hasn't be specified by =
|
||||||
|
if (value.empty() && i+1 < argc)
|
||||||
|
{
|
||||||
|
// take next argument
|
||||||
|
value = argv[++i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// add argument value if not empty
|
||||||
|
if (!value.empty())
|
||||||
|
{
|
||||||
|
arg.values.push_back(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// process each argument definition
|
||||||
|
for(uint j = 0, len = _Args.size(); j < len; ++j)
|
||||||
|
{
|
||||||
|
TArg &arg = _Args[j];
|
||||||
|
|
||||||
|
// only process arguments that don't have a name
|
||||||
|
if (!arg.shortName.empty() || !arg.longName.empty()) continue;
|
||||||
|
|
||||||
|
// in fact, if there are more than one required arguments, all arguments are added in first one to simplify
|
||||||
|
arg.values.push_back(name);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// process help if requested or if required arguments are missing
|
||||||
|
if (haveLongArg("help") || (needRequiredArg() && !haveRequiredArg()))
|
||||||
|
{
|
||||||
|
displayHelp();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// process version
|
||||||
|
if (haveLongArg("version"))
|
||||||
|
{
|
||||||
|
displayVersion();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCmdArgs::displayHelp()
|
||||||
|
{
|
||||||
|
// display program name
|
||||||
|
printf("Usage: %s ", _ProgramName.c_str());
|
||||||
|
|
||||||
|
// display optional parameters
|
||||||
|
for(uint i = 0; i < _Args.size(); ++i)
|
||||||
|
{
|
||||||
|
const TArg &arg = _Args[i];
|
||||||
|
|
||||||
|
// only short argument is displayed
|
||||||
|
if (!arg.shortName.empty())
|
||||||
|
{
|
||||||
|
printf("[-%s", arg.shortName.c_str());
|
||||||
|
|
||||||
|
// a parameter is required
|
||||||
|
if (!arg.helpName.empty())
|
||||||
|
{
|
||||||
|
printf("<%s>", arg.helpName.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sint last = -1;
|
||||||
|
|
||||||
|
// look for last required argument
|
||||||
|
for(uint i = 0; i < _Args.size(); ++i)
|
||||||
|
{
|
||||||
|
if (_Args[i].shortName.empty()) last = (sint)i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// display required arguments
|
||||||
|
for(uint i = 0; i < _Args.size(); ++i)
|
||||||
|
{
|
||||||
|
const TArg &arg = _Args[i];
|
||||||
|
|
||||||
|
// they don't have any short or long name, but need a name in help
|
||||||
|
if (arg.shortName.empty() && arg.longName.empty() && !arg.helpName.empty())
|
||||||
|
{
|
||||||
|
printf(" <%s>", arg.helpName.c_str());
|
||||||
|
|
||||||
|
// if last argument, it can support additional arguments
|
||||||
|
if ((sint)i == last)
|
||||||
|
{
|
||||||
|
printf(" [%s...]", arg.helpName.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
// display details on each argument
|
||||||
|
for(uint i = 0; i < _Args.size(); ++i)
|
||||||
|
{
|
||||||
|
const TArg &arg = _Args[i];
|
||||||
|
|
||||||
|
// not an optional argument
|
||||||
|
if (arg.shortName.empty() && arg.longName.empty()) continue;
|
||||||
|
|
||||||
|
// a tab
|
||||||
|
printf("\t");
|
||||||
|
|
||||||
|
// display short argument
|
||||||
|
if (!arg.shortName.empty())
|
||||||
|
{
|
||||||
|
printf("-%s", arg.shortName.c_str());
|
||||||
|
|
||||||
|
// and it's required argument
|
||||||
|
if (!arg.helpName.empty())
|
||||||
|
{
|
||||||
|
printf(" <%s>", arg.helpName.c_str());
|
||||||
|
printf(" or -%s<%s>", arg.shortName.c_str(), arg.helpName.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// display long argument
|
||||||
|
if (!arg.longName.empty())
|
||||||
|
{
|
||||||
|
if (!arg.helpName.empty())
|
||||||
|
{
|
||||||
|
// prepend a coma if a short argument was already displayed
|
||||||
|
if (!arg.shortName.empty())
|
||||||
|
{
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// display first syntax for long argument, --arg <value>
|
||||||
|
printf("--%s <%s>", arg.longName.c_str(), arg.helpName.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepend " or " if 3 formats for argument
|
||||||
|
if (!arg.shortName.empty() || !arg.helpName.empty())
|
||||||
|
{
|
||||||
|
printf(" or ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// display second syntax for long argument, --arg=<value>
|
||||||
|
printf("--%s", arg.longName.c_str());
|
||||||
|
|
||||||
|
if (!arg.helpName.empty())
|
||||||
|
{
|
||||||
|
printf("=<%s>", arg.helpName.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// display argument description
|
||||||
|
if (!arg.helpDescription.empty())
|
||||||
|
{
|
||||||
|
printf(" : %s", arg.helpDescription.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// process each argument
|
||||||
|
for(uint i = 0; i < _Args.size(); ++i)
|
||||||
|
{
|
||||||
|
const TArg &arg = _Args[i];
|
||||||
|
|
||||||
|
// only display required arguments
|
||||||
|
if (arg.shortName.empty() && arg.longName.empty() && !arg.helpName.empty() && !arg.helpDescription.empty())
|
||||||
|
{
|
||||||
|
printf("\t%s : %s\n", arg.helpName.c_str(), arg.helpDescription.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCmdArgs::displayVersion()
|
||||||
|
{
|
||||||
|
// display a verbose version string
|
||||||
|
#ifdef BUILD_DATE
|
||||||
|
printf("%s %s (built on %s)\nCopyright (C) %s\n", _ProgramName.c_str(), NL_VERSION, BUILD_DATE, COPYRIGHT);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // NAMESPACE NLMISC
|
}; // NAMESPACE NLMISC
|
||||||
|
|
|
@ -24,54 +24,63 @@
|
||||||
#include <nel/3d/register_3d.h>
|
#include <nel/3d/register_3d.h>
|
||||||
#include <nel/3d/scene.h>
|
#include <nel/3d/scene.h>
|
||||||
|
|
||||||
int printHelp(const NLMISC::CCmdArgs &args)
|
|
||||||
{
|
|
||||||
printf("NeL Mesh Export\n");
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
NLMISC::CApplicationContext app;
|
NLMISC::CApplicationContext app;
|
||||||
|
|
||||||
NLMISC::CCmdArgs args;
|
NLMISC::CCmdArgs args;
|
||||||
args.setArgs(argc, (const char **)argv);
|
|
||||||
|
|
||||||
if (args.getArgs().size() == 1
|
args.addArg("d", "dst", "destination", "Destination directory path");
|
||||||
|| args.haveArg('h')
|
args.addArg("", "dependlog", "log", "Dependencies log path");
|
||||||
|| args.haveLongArg("help"))
|
args.addArg("", "errorlog", "log", "Errors log path");
|
||||||
return printHelp(args);
|
args.addArg("filename", "Filename of 3D model to convert");
|
||||||
|
|
||||||
const NLMISC::CSString &filePath = args.getArgs().back();
|
if (!args.parse(argc, argv)) return EXIT_SUCCESS;
|
||||||
if (!NLMISC::CFile::fileExists(filePath))
|
|
||||||
{
|
|
||||||
printHelp(args);
|
|
||||||
nlerror("File '%s' does not exist", filePath.c_str());
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
CMeshUtilsSettings settings;
|
const std::vector<std::string> &filePathes = args.getRequiredArg();
|
||||||
settings.SourceFilePath = filePath;
|
|
||||||
|
|
||||||
if (args.haveArg('d'))
|
|
||||||
settings.DestinationDirectoryPath = args.getArg('d');
|
|
||||||
if (settings.DestinationDirectoryPath.empty())
|
|
||||||
settings.DestinationDirectoryPath = args.getLongArg("dst");
|
|
||||||
if (settings.DestinationDirectoryPath.empty())
|
|
||||||
settings.DestinationDirectoryPath = filePath + "_export";
|
|
||||||
settings.DestinationDirectoryPath += "/";
|
|
||||||
|
|
||||||
settings.ToolDependLog = args.getLongArg("dependlog");
|
|
||||||
if (settings.ToolDependLog.empty())
|
|
||||||
settings.ToolDependLog = settings.DestinationDirectoryPath + "depend.log";
|
|
||||||
settings.ToolErrorLog = args.getLongArg("errorlog");
|
|
||||||
if (settings.ToolErrorLog.empty())
|
|
||||||
settings.ToolErrorLog = settings.DestinationDirectoryPath + "error.log";
|
|
||||||
|
|
||||||
NL3D::CScene::registerBasics();
|
NL3D::CScene::registerBasics();
|
||||||
NL3D::registerSerial3d();
|
NL3D::registerSerial3d();
|
||||||
|
|
||||||
return exportScene(settings);
|
sint res = 0;
|
||||||
|
|
||||||
|
for(uint i = 0; i < filePathes.size(); ++i)
|
||||||
|
{
|
||||||
|
std::string filePath = filePathes[i];
|
||||||
|
|
||||||
|
if (!NLMISC::CFile::fileExists(filePath))
|
||||||
|
{
|
||||||
|
nlerror("File '%s' does not exist", filePath.c_str());
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
CMeshUtilsSettings settings;
|
||||||
|
settings.SourceFilePath = filePath;
|
||||||
|
|
||||||
|
if (args.haveArg("d"))
|
||||||
|
settings.DestinationDirectoryPath = args.getArg("d").front();
|
||||||
|
|
||||||
|
if (settings.DestinationDirectoryPath.empty())
|
||||||
|
settings.DestinationDirectoryPath = filePath + "_export";
|
||||||
|
|
||||||
|
settings.DestinationDirectoryPath = NLMISC::standardizePath(settings.DestinationDirectoryPath);
|
||||||
|
|
||||||
|
if (args.haveLongArg("dependlog"))
|
||||||
|
settings.ToolDependLog = args.getLongArg("dependlog").front();
|
||||||
|
|
||||||
|
if (settings.ToolDependLog.empty())
|
||||||
|
settings.ToolDependLog = settings.DestinationDirectoryPath + "depend.log";
|
||||||
|
|
||||||
|
if (args.haveLongArg("errorlog"))
|
||||||
|
settings.ToolErrorLog = args.getLongArg("errorlog").front();
|
||||||
|
|
||||||
|
if (settings.ToolErrorLog.empty())
|
||||||
|
settings.ToolErrorLog = settings.DestinationDirectoryPath + "error.log";
|
||||||
|
|
||||||
|
res = exportScene(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* end of file */
|
/* end of file */
|
||||||
|
|
Loading…
Reference in a new issue