Enhancement - Command Line Parsing
- Fixed problem where a blank ID was considered valid. For example, the command "task 1 -2" should use -2 as the description, but instead considered this to be the sequence 1,0,2. - Replaced old validId calls with the new validSequence calls. - A sequence has been redefined to be the first set of consecutive arguments that look like sequences. Once broken by a non-sequence argument, all remaining args, even if they look like a sequence, are not considered part of the sequence. This allows commands like "task append 1,3-5 Write 10 emails", where 10 is not part of the sequence because of the intervening "Write". - Unit tests (parse.t.cpp) that exercise the parsing of sequences. Should probably be expanded to cover more.
This commit is contained in:
@@ -299,6 +299,9 @@ static bool validAttribute (
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static bool validId (const std::string& input)
|
||||
{
|
||||
if (input.length () == 0)
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < input.length (); ++i)
|
||||
if (!::isdigit (input[i]))
|
||||
return false;
|
||||
@@ -329,7 +332,6 @@ static bool validSequence (
|
||||
|
||||
int id = ::atoi (range[0].c_str ());
|
||||
ids.push_back (id);
|
||||
// std::cout << "# seq: " << id << std::endl;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
@@ -344,10 +346,7 @@ static bool validSequence (
|
||||
return false;
|
||||
|
||||
for (int i = low; i <= high; ++i)
|
||||
// {
|
||||
ids.push_back (i);
|
||||
// std::cout << "# seq: " << i << std::endl;
|
||||
// }
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -357,7 +356,7 @@ static bool validSequence (
|
||||
}
|
||||
}
|
||||
|
||||
return ids.size () > 1 ? true : false;
|
||||
return ids.size () ? true : false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -448,8 +447,6 @@ bool validDuration (std::string& input)
|
||||
// ------- ----------------------------------
|
||||
// command first non-id recognized argument
|
||||
//
|
||||
// id ::= \d+
|
||||
//
|
||||
// substitution ::= "/" from "/" to "/g"
|
||||
// | "/" from "/" to "/" ;
|
||||
//
|
||||
@@ -459,8 +456,8 @@ bool validDuration (std::string& input)
|
||||
// attributes ::= word ":" value
|
||||
// | word ":"
|
||||
//
|
||||
// sequence ::= id "," sequence
|
||||
// | id "-" id ;
|
||||
// sequence ::= \d+ "," sequence
|
||||
// | \d+ "-" \d+ ;
|
||||
//
|
||||
// description (whatever isn't one of the above)
|
||||
void parse (
|
||||
@@ -471,6 +468,9 @@ void parse (
|
||||
{
|
||||
command = "";
|
||||
|
||||
bool foundSequence = false;
|
||||
bool foundSomethingAfterSequence = false;
|
||||
|
||||
std::string descCandidate = "";
|
||||
for (size_t i = 0; i < args.size (); ++i)
|
||||
{
|
||||
@@ -488,22 +488,20 @@ void parse (
|
||||
|
||||
// An id is the first argument found that contains all digits.
|
||||
if (lowerCase (command) != "add" && // "add" doesn't require an ID
|
||||
validSequence (arg, sequence))
|
||||
validSequence (arg, sequence) &&
|
||||
! foundSomethingAfterSequence)
|
||||
{
|
||||
foundSequence = true;
|
||||
foreach (id, sequence)
|
||||
task.addId (*id);
|
||||
}
|
||||
|
||||
else if (lowerCase (command) != "add" && // "add" doesn't require an ID
|
||||
task.getId () == 0 &&
|
||||
validId (arg))
|
||||
{
|
||||
task.setId (::atoi (arg.c_str ()));
|
||||
}
|
||||
|
||||
// Tags begin with + or - and contain arbitrary text.
|
||||
else if (validTag (arg))
|
||||
{
|
||||
if (foundSequence)
|
||||
foundSomethingAfterSequence = true;
|
||||
|
||||
if (arg[0] == '+')
|
||||
task.addTag (arg.substr (1, std::string::npos));
|
||||
else if (arg[0] == '-')
|
||||
@@ -514,6 +512,9 @@ void parse (
|
||||
// value.
|
||||
else if ((colon = arg.find (":")) != std::string::npos)
|
||||
{
|
||||
if (foundSequence)
|
||||
foundSomethingAfterSequence = true;
|
||||
|
||||
std::string name = lowerCase (arg.substr (0, colon));
|
||||
std::string value = arg.substr (colon + 1, std::string::npos);
|
||||
|
||||
@@ -536,12 +537,18 @@ void parse (
|
||||
// Substitution of description text.
|
||||
else if (validSubstitution (arg, from, to, global))
|
||||
{
|
||||
if (foundSequence)
|
||||
foundSomethingAfterSequence = true;
|
||||
|
||||
task.setSubstitution (from, to, global);
|
||||
}
|
||||
|
||||
// Command.
|
||||
else if (command == "")
|
||||
{
|
||||
if (foundSequence)
|
||||
foundSomethingAfterSequence = true;
|
||||
|
||||
std::string l = lowerCase (arg);
|
||||
if (isCommand (l) && validCommand (l))
|
||||
command = l;
|
||||
@@ -556,6 +563,9 @@ void parse (
|
||||
// Anything else is just considered description.
|
||||
else
|
||||
{
|
||||
if (foundSequence)
|
||||
foundSomethingAfterSequence = true;
|
||||
|
||||
if (descCandidate.length ())
|
||||
descCandidate += " ";
|
||||
descCandidate += arg;
|
||||
|
||||
Reference in New Issue
Block a user