mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
Expressions reboot
- Implemented A3::is_dom obsoleting Nibbler::getDOM. - Implemented A3::is_duration. - Implemented A3::is_pattern to replace Nibbler::getQuoted call. - Improved A3::is_attr, A3::is_attmod. - Obsoleted A3::is_multipart.
This commit is contained in:
parent
f502ee0c52
commit
c39f8bd6af
2 changed files with 162 additions and 91 deletions
246
src/A3.cpp
246
src/A3.cpp
|
@ -33,6 +33,7 @@
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <Directory.h>
|
#include <Directory.h>
|
||||||
#include <Date.h>
|
#include <Date.h>
|
||||||
|
#include <Duration.h>
|
||||||
#include <ViewText.h>
|
#include <ViewText.h>
|
||||||
#include <text.h>
|
#include <text.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
@ -636,7 +637,7 @@ const A3 A3::tokenize (const A3& input) const
|
||||||
output.push_back (Arg (s, "string"));
|
output.push_back (Arg (s, "string"));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (n.getQuoted ('/', s, true))
|
else if (is_pattern (n, s))
|
||||||
{
|
{
|
||||||
std::cout << "# pattern '" << s << "'\n";
|
std::cout << "# pattern '" << s << "'\n";
|
||||||
output.push_back (Arg (s, "pattern"));
|
output.push_back (Arg (s, "pattern"));
|
||||||
|
@ -660,7 +661,7 @@ const A3 A3::tokenize (const A3& input) const
|
||||||
output.push_back (Arg (s, "attmod"));
|
output.push_back (Arg (s, "attmod"));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (n.getDOM (s))
|
else if (is_dom (n, s))
|
||||||
{
|
{
|
||||||
std::cout << "# dom '" << s << "'\n";
|
std::cout << "# dom '" << s << "'\n";
|
||||||
output.push_back (Arg (s, "dom"));
|
output.push_back (Arg (s, "dom"));
|
||||||
|
@ -678,6 +679,12 @@ const A3 A3::tokenize (const A3& input) const
|
||||||
output.push_back (Arg (Date (t).toString (date_format), "date"));
|
output.push_back (Arg (Date (t).toString (date_format), "date"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (is_duration (n, s))
|
||||||
|
{
|
||||||
|
std::cout << "# duration '" << s << "'\n";
|
||||||
|
output.push_back (Arg (s, "duration"));
|
||||||
|
}
|
||||||
|
|
||||||
else if (n.getNumber (d))
|
else if (n.getNumber (d))
|
||||||
{
|
{
|
||||||
std::cout << "# num '" << d << "'\n";
|
std::cout << "# num '" << d << "'\n";
|
||||||
|
@ -722,35 +729,31 @@ bool A3::is_attr (Nibbler& n, std::string& result)
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string value;
|
std::string value;
|
||||||
|
|
||||||
if (n.getName (name))
|
// If there is a valid attribute name.
|
||||||
|
if (n.getName (name) &&
|
||||||
|
name.length () &&
|
||||||
|
is_attribute (name, name))
|
||||||
{
|
{
|
||||||
if (name.length ())
|
if (n.skip (':'))
|
||||||
{
|
{
|
||||||
if (n.skip (':'))
|
// Both quoted and unquoted Att's are accepted.
|
||||||
|
// Consider removing this for a stricter parse.
|
||||||
|
if (n.getQuoted ('"', value) ||
|
||||||
|
n.getQuoted ('\'', value) ||
|
||||||
|
n.getName (value) ||
|
||||||
|
n.getUntilEOS (value) ||
|
||||||
|
n.depleted ())
|
||||||
{
|
{
|
||||||
// Both quoted and unquoted Att's are accepted.
|
|
||||||
// Consider removing this for a stricter parse.
|
|
||||||
if (n.getQuoted ('"', value) ||
|
|
||||||
n.getQuoted ('\'', value) ||
|
|
||||||
n.getName (value) ||
|
|
||||||
n.getUntilEOS (value) ||
|
|
||||||
n.depleted ())
|
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
TODO Eliminate anything that looks like a URL.
|
// TODO Reject anything that looks like a URL.
|
||||||
// Exclude certain URLs, that look like attrs.
|
// Exclude certain URLs, that look like attrs.
|
||||||
if (value.find ('@') <= n.cursor () ||
|
if (value.find ('@') <= n.cursor () ||
|
||||||
value.find ('/') <= n.cursor ())
|
value.find ('/') <= n.cursor ())
|
||||||
return false;
|
return false;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Validate and canonicalize attribute name.
|
result = name + ':' + value;
|
||||||
if (is_attribute (name, name))
|
return true;
|
||||||
{
|
|
||||||
result = name + ':' + value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -768,16 +771,20 @@ bool A3::is_attmod (Nibbler& n, std::string& result)
|
||||||
std::string modifier;
|
std::string modifier;
|
||||||
std::string value;
|
std::string value;
|
||||||
|
|
||||||
|
// If there is a valid attribute name.
|
||||||
if (n.getName (name) &&
|
if (n.getName (name) &&
|
||||||
name.length ())
|
name.length () &&
|
||||||
|
is_attribute (name, name))
|
||||||
{
|
{
|
||||||
if (n.skip ('.'))
|
if (n.skip ('.'))
|
||||||
{
|
{
|
||||||
// Skip the negation character.
|
// Skip the negation character.
|
||||||
n.skip ('~');
|
n.skip ('~');
|
||||||
|
|
||||||
|
// If there is a valid modifier name.
|
||||||
if (n.getName (modifier) &&
|
if (n.getName (modifier) &&
|
||||||
modifier.length ())
|
modifier.length () &&
|
||||||
|
is_modifier (modifier, modifier))
|
||||||
{
|
{
|
||||||
if (n.skip (':'))
|
if (n.skip (':'))
|
||||||
{
|
{
|
||||||
|
@ -797,19 +804,15 @@ bool A3::is_attmod (Nibbler& n, std::string& result)
|
||||||
return false;
|
return false;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Validate and canonicalize attribute name.
|
result = name + '.' + modifier + ':' + value;
|
||||||
if (is_attribute (name, name) &&
|
return true;
|
||||||
is_modifier (modifier, modifier))
|
|
||||||
{
|
|
||||||
result = name + '.' + modifier + ':' + value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
n.restore ();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -856,9 +859,122 @@ bool A3::is_modifier (const std::string& input, std::string& canonical)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// DOM references are one of the following:
|
||||||
|
//
|
||||||
|
// 1. Fixed string
|
||||||
|
// DOM::get_references
|
||||||
|
// 2. Attribute
|
||||||
|
// <attr>
|
||||||
|
// 3. Task-specific attribute
|
||||||
|
// <id>.<attr>
|
||||||
|
// <uuid>.<attr>
|
||||||
|
// 4. Configuration value
|
||||||
|
// rc.<name>
|
||||||
|
//
|
||||||
|
bool A3::is_dom (Nibbler& n, std::string& result)
|
||||||
|
{
|
||||||
|
n.save ();
|
||||||
|
std::string name;
|
||||||
|
int id;
|
||||||
|
std::string uuid;
|
||||||
|
|
||||||
|
// Fixed string reference.
|
||||||
|
std::vector <std::string> refs = context.dom.get_references ();
|
||||||
|
if (n.getOneOf (refs, result))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Configuration.
|
||||||
|
if (n.getLiteral ("rc."))
|
||||||
|
{
|
||||||
|
result = "rc.";
|
||||||
|
while (n.getWord (name))
|
||||||
|
{
|
||||||
|
result += name;
|
||||||
|
|
||||||
|
if (n.skip ('.'))
|
||||||
|
result += '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
n.restore ();
|
||||||
|
|
||||||
|
// <id>.<attr>
|
||||||
|
if (n.getInt (id) &&
|
||||||
|
n.skip ('.') &&
|
||||||
|
n.getName (name) &&
|
||||||
|
name.length () &&
|
||||||
|
is_attribute (name, name))
|
||||||
|
{
|
||||||
|
result = format (id) + '.' + name;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
n.restore ();
|
||||||
|
|
||||||
|
// <uuid>.<attr>
|
||||||
|
if (n.getUUID (uuid) &&
|
||||||
|
n.skip ('.') &&
|
||||||
|
n.getName (name) &&
|
||||||
|
name.length () &&
|
||||||
|
is_attribute (name, name))
|
||||||
|
{
|
||||||
|
result = uuid + '.' + name;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
n.restore ();
|
||||||
|
|
||||||
|
// Attribute.
|
||||||
|
if (n.getName (name) &&
|
||||||
|
name.length () &&
|
||||||
|
is_attribute (name, name))
|
||||||
|
{
|
||||||
|
result = name;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
n.restore ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool A3::is_duration (Nibbler& n, std::string& result)
|
||||||
|
{
|
||||||
|
n.save ();
|
||||||
|
|
||||||
|
int quantity;
|
||||||
|
std::string unit;
|
||||||
|
|
||||||
|
std::vector <std::string> units = Duration::get_units ();
|
||||||
|
|
||||||
|
if (n.getInt (quantity) &&
|
||||||
|
n.getOneOf (units, unit))
|
||||||
|
{
|
||||||
|
result = format (quantity) + unit;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
n.restore ();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// /<pattern>/
|
||||||
|
bool A3::is_pattern (Nibbler& n, std::string& result)
|
||||||
|
{
|
||||||
|
std::string pattern;
|
||||||
|
if (n.getQuoted ('/', pattern) &&
|
||||||
|
pattern.length () > 0)
|
||||||
|
{
|
||||||
|
result = '/' + pattern + '/';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -874,26 +990,6 @@ bool A3::is_modifier (const std::string& input, std::string& canonical)
|
||||||
|
|
||||||
|
|
||||||
#ifdef NOPE
|
#ifdef NOPE
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
bool A3::is_multipart (
|
|
||||||
const std::string& input,
|
|
||||||
std::vector <std::string>& parts)
|
|
||||||
{
|
|
||||||
parts.clear ();
|
|
||||||
Nibbler n (input);
|
|
||||||
std::string part;
|
|
||||||
while (n.getQuoted ('"', part) ||
|
|
||||||
n.getQuoted ('\'', part) ||
|
|
||||||
// n.getQuoted ('/', part) || <--- this line breaks subst.
|
|
||||||
n.getUntilWS (part))
|
|
||||||
{
|
|
||||||
n.skipWS ();
|
|
||||||
parts.push_back (part);
|
|
||||||
}
|
|
||||||
|
|
||||||
return parts.size () > 1 ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// /<from>/<to>/[g]
|
// /<from>/<to>/[g]
|
||||||
//
|
//
|
||||||
|
@ -923,23 +1019,6 @@ bool A3::is_subst (const std::string& input)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// /<pattern>/
|
|
||||||
bool A3::is_pattern (const std::string& input)
|
|
||||||
{
|
|
||||||
std::string::size_type first = input.find ('/', 0);
|
|
||||||
std::string::size_type second = input.find ('/', first + 1);
|
|
||||||
std::string::size_type third = input.find ('/', second + 1);
|
|
||||||
|
|
||||||
if (first == 0 &&
|
|
||||||
second == input.length () - 1 &&
|
|
||||||
third == std::string::npos &&
|
|
||||||
second > 1)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// <id>[-<id>][,<id>[-<id>]]
|
// <id>[-<id>][,<id>[-<id>]]
|
||||||
bool A3::is_id (const std::string& input)
|
bool A3::is_id (const std::string& input)
|
||||||
|
@ -1629,6 +1708,10 @@ bool A3::valid_modifier (const std::string& modifier)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void A3::dump (const std::string& label)
|
void A3::dump (const std::string& label)
|
||||||
{
|
{
|
||||||
|
@ -1640,7 +1723,6 @@ void A3::dump (const std::string& label)
|
||||||
color_map["override"] = Color ("bold red on red");
|
color_map["override"] = Color ("bold red on red");
|
||||||
color_map["terminator"] = Color ("bold yellow on yellow");
|
color_map["terminator"] = Color ("bold yellow on yellow");
|
||||||
color_map["word"] = Color ("white on gray4");
|
color_map["word"] = Color ("white on gray4");
|
||||||
color_map["none"] = Color ("black on white");
|
|
||||||
|
|
||||||
// Filter colors.
|
// Filter colors.
|
||||||
color_map["attr"] = Color ("bold red on gray4");
|
color_map["attr"] = Color ("bold red on gray4");
|
||||||
|
@ -1649,21 +1731,11 @@ void A3::dump (const std::string& label)
|
||||||
color_map["op"] = Color ("green on gray4");
|
color_map["op"] = Color ("green on gray4");
|
||||||
color_map["string"] = Color ("bold yellow on gray4");
|
color_map["string"] = Color ("bold yellow on gray4");
|
||||||
color_map["date"] = Color ("bold yellow on gray4");
|
color_map["date"] = Color ("bold yellow on gray4");
|
||||||
/*
|
color_map["dom"] = Color ("bold white on gray4");
|
||||||
color_map["tag"] = Color ("green on gray2");
|
color_map["duration"] = Color ("magenta on gray4");
|
||||||
color_map["id"] = Color ("yellow on gray2");
|
|
||||||
color_map["uuid"] = Color ("yellow on gray2");
|
// Default.
|
||||||
color_map["subst"] = Color ("bold cyan on gray2");
|
color_map["none"] = Color ("black on white");
|
||||||
color_map["exp"] = Color ("bold green on gray2");
|
|
||||||
*/
|
|
||||||
// color_map["none"] = Color ("white on gray2");
|
|
||||||
// Fundamentals.
|
|
||||||
/*
|
|
||||||
color_map["lvalue"] = Color ("bold green on rgb010");
|
|
||||||
color_map["int"] = Color ("bold yellow on rgb010");
|
|
||||||
color_map["number"] = Color ("bold yellow on rgb010");
|
|
||||||
color_map["rx"] = Color ("bold red on rgb010");
|
|
||||||
*/
|
|
||||||
|
|
||||||
Color color_debug (context.config.get ("color.debug"));
|
Color color_debug (context.config.get ("color.debug"));
|
||||||
std::stringstream out;
|
std::stringstream out;
|
||||||
|
|
7
src/A3.h
7
src/A3.h
|
@ -109,13 +109,12 @@ public:
|
||||||
static bool is_attmod (Nibbler&, std::string&);
|
static bool is_attmod (Nibbler&, std::string&);
|
||||||
static bool is_attribute (const std::string&, std::string&);
|
static bool is_attribute (const std::string&, std::string&);
|
||||||
static bool is_modifier (const std::string&, std::string&);
|
static bool is_modifier (const std::string&, std::string&);
|
||||||
|
static bool is_dom (Nibbler&, std::string&);
|
||||||
|
static bool is_duration (Nibbler&, std::string&);
|
||||||
|
static bool is_pattern (Nibbler&, std::string&);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
|
|
||||||
static bool is_multipart (const std::string&, std::vector <std::string>&);
|
|
||||||
static bool is_subst (const std::string&);
|
static bool is_subst (const std::string&);
|
||||||
static bool is_pattern (const std::string&);
|
|
||||||
static bool is_id (const std::string&);
|
static bool is_id (const std::string&);
|
||||||
static bool is_uuid (const std::string&);
|
static bool is_uuid (const std::string&);
|
||||||
static bool is_tag (const std::string&);
|
static bool is_tag (const std::string&);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue