mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
Bug
- Tag matching was being performed using the regex \b<tag>\b, which makes taskwarrior dependent on regex lib bugs for basic functionality. This is now modified to use pseudo-operators _hastag_ and _notag_.
This commit is contained in:
parent
78e5891cd3
commit
09431caf1c
5 changed files with 72 additions and 54 deletions
73
src/A3.cpp
73
src/A3.cpp
|
@ -74,30 +74,34 @@ static struct
|
|||
char associativity;
|
||||
} operators[] =
|
||||
{
|
||||
// Operator Precedence Type Symbol Associativity
|
||||
{ "and", 5, 'b', 0, 'l' }, // Conjunction
|
||||
{ "xor", 4, 'b', 0, 'l' }, // Disjunction
|
||||
// Operator Precedence Type Symbol Associativity
|
||||
{ "and", 5, 'b', 0, 'l' }, // Conjunction
|
||||
{ "xor", 4, 'b', 0, 'l' }, // Disjunction
|
||||
|
||||
{ "or", 3, 'b', 0, 'l' }, // Disjunction
|
||||
{ "<=", 10, 'b', 1, 'l' }, // Less than or equal
|
||||
{ ">=", 10, 'b', 1, 'l' }, // Greater than or equal
|
||||
{ "!~", 9, 'b', 1, 'l' }, // Regex non-match
|
||||
{ "!=", 9, 'b', 1, 'l' }, // Inequal
|
||||
{ "or", 3, 'b', 0, 'l' }, // Disjunction
|
||||
{ "<=", 10, 'b', 1, 'l' }, // Less than or equal
|
||||
{ ">=", 10, 'b', 1, 'l' }, // Greater than or equal
|
||||
{ "!~", 9, 'b', 1, 'l' }, // Regex non-match
|
||||
{ "!=", 9, 'b', 1, 'l' }, // Inequal
|
||||
|
||||
{ "=", 9, 'b', 1, 'l' }, // Equal
|
||||
// { "^", 16, 'b', 1, 'r' }, // Exponent
|
||||
{ ">", 10, 'b', 1, 'l' }, // Greater than
|
||||
{ "~", 9, 'b', 1, 'l' }, // Regex match
|
||||
{ "!", 15, 'u', 1, 'r' }, // Not
|
||||
// { "-", 15, 'u', 1, 'r' }, // Unary minus
|
||||
{ "*", 13, 'b', 1, 'l' }, // Multiplication
|
||||
{ "/", 13, 'b', 1, 'l' }, // Division
|
||||
// { "%", 13, 'b', 1, 'l' }, // Modulus
|
||||
{ "+", 12, 'b', 1, 'l' }, // Addition
|
||||
{ "-", 12, 'b', 1, 'l' }, // Subtraction
|
||||
{ "<", 10, 'b', 1, 'l' }, // Less than
|
||||
{ "(", 0, 'b', 1, 'l' }, // Precedence start
|
||||
{ ")", 0, 'b', 1, 'l' }, // Precedence end
|
||||
{ "=", 9, 'b', 1, 'l' }, // Equal
|
||||
// { "^", 16, 'b', 1, 'r' }, // Exponent
|
||||
{ ">", 10, 'b', 1, 'l' }, // Greater than
|
||||
{ "~", 9, 'b', 1, 'l' }, // Regex match
|
||||
{ "!", 15, 'u', 1, 'r' }, // Not
|
||||
|
||||
{ "_hastag_", 9, 'b', 0, 'l'}, // +tag [Pseudo-op]
|
||||
{ "_notag_", 9, 'b', 0, 'l'}, // -tag [Pseudo-op]
|
||||
|
||||
// { "-", 15, 'u', 1, 'r' }, // Unary minus
|
||||
{ "*", 13, 'b', 1, 'l' }, // Multiplication
|
||||
{ "/", 13, 'b', 1, 'l' }, // Division
|
||||
// { "%", 13, 'b', 1, 'l' }, // Modulus
|
||||
{ "+", 12, 'b', 1, 'l' }, // Addition
|
||||
{ "-", 12, 'b', 1, 'l' }, // Subtraction
|
||||
{ "<", 10, 'b', 1, 'l' }, // Less than
|
||||
{ "(", 0, 'b', 1, 'l' }, // Precedence start
|
||||
{ ")", 0, 'b', 1, 'l' }, // Precedence end
|
||||
};
|
||||
|
||||
#define NUM_MODIFIER_NAMES (sizeof (modifierNames) / sizeof (modifierNames[0]))
|
||||
|
@ -1047,24 +1051,16 @@ const A3 A3::expand (const A3& input) const
|
|||
throw format (STRING_A3_UNKNOWN_ATTMOD, mod);
|
||||
}
|
||||
|
||||
// [+-]value --> tags ~/!~ value
|
||||
// [+-]value --> tags _hastag_/_notag_ value
|
||||
else if (arg->_category == Arg::cat_tag)
|
||||
{
|
||||
char type;
|
||||
std::string value;
|
||||
extract_tag (arg->_raw, type, value);
|
||||
|
||||
expanded.push_back (Arg ("tags", Arg::type_string, Arg::cat_dom));
|
||||
expanded.push_back (Arg (type == '+' ? "~" : "!~", Arg::cat_op));
|
||||
#ifdef DARWIN
|
||||
expanded.push_back (Arg ("tags", Arg::type_string, Arg::cat_dom_));
|
||||
expanded.push_back (Arg (type == '+' ? "_hastag_" : "_notag_", Arg::cat_op));
|
||||
expanded.push_back (Arg (value, Arg::type_string, Arg::cat_literal));
|
||||
#else
|
||||
#ifdef SOLARIS
|
||||
expanded.push_back (Arg ("\\<" + value + "\\>", Arg::type_string, Arg::cat_rx));
|
||||
#else
|
||||
expanded.push_back (Arg ("\\b" + value + "\\b", Arg::type_string, Arg::cat_rx));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
// word --> description ~ word
|
||||
|
@ -2053,23 +2049,24 @@ void A3::dump (const std::string& label)
|
|||
color_map[Arg::cat_program] = Color ("bold blue on blue");
|
||||
color_map[Arg::cat_command] = Color ("bold cyan on cyan");
|
||||
color_map[Arg::cat_rc] = Color ("bold red on red");
|
||||
color_map[Arg::cat_override] = Color ("bold red on red");
|
||||
color_map[Arg::cat_override] = color_map[Arg::cat_rc];
|
||||
color_map[Arg::cat_terminator] = Color ("bold yellow on yellow");
|
||||
color_map[Arg::cat_literal] = Color ("white on gray4");
|
||||
|
||||
// Filter colors.
|
||||
color_map[Arg::cat_attr] = Color ("bold red on gray4");
|
||||
color_map[Arg::cat_attmod] = Color ("bold red on gray4");
|
||||
color_map[Arg::cat_attmod] = color_map[Arg::cat_attr];
|
||||
color_map[Arg::cat_pattern] = Color ("cyan on gray4");
|
||||
color_map[Arg::cat_subst] = Color ("bold cyan on gray4");
|
||||
color_map[Arg::cat_op] = Color ("green on gray4");
|
||||
color_map[Arg::type_string] = Color ("bold yellow on gray4");
|
||||
color_map[Arg::cat_rx] = Color ("bold yellow on gray4");
|
||||
color_map[Arg::type_date] = Color ("bold yellow on gray4");
|
||||
color_map[Arg::cat_rx] = color_map[Arg::type_string];
|
||||
color_map[Arg::type_date] = color_map[Arg::type_string];
|
||||
color_map[Arg::cat_dom] = Color ("bold white on gray4");
|
||||
color_map[Arg::cat_dom_] = color_map[Arg::cat_dom];
|
||||
color_map[Arg::type_duration] = Color ("magenta on gray4");
|
||||
color_map[Arg::cat_id] = Color ("white on gray4");
|
||||
color_map[Arg::cat_uuid] = Color ("white on gray4");
|
||||
color_map[Arg::cat_uuid] = color_map[Arg::cat_id];
|
||||
|
||||
// Default.
|
||||
color_map[Arg::cat_none] = Color ("black on white");
|
||||
|
|
|
@ -178,6 +178,7 @@ const std::string Arg::category_name (Arg::category c)
|
|||
case Arg::cat_pattern: return "pattern";
|
||||
case Arg::cat_tag: return "tag";
|
||||
case Arg::cat_dom: return "dom";
|
||||
case Arg::cat_dom_: return "[dom]";
|
||||
case Arg::cat_op: return "op";
|
||||
case Arg::cat_literal: return "literal";
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
class Arg
|
||||
{
|
||||
public:
|
||||
enum category {cat_none=1, cat_terminator, cat_program, cat_command, cat_rc, cat_override, cat_attr, cat_attmod, cat_id, cat_uuid, cat_subst, cat_pattern, cat_rx, cat_tag, cat_dom, cat_op, cat_literal};
|
||||
enum category {cat_none=1, cat_terminator, cat_program, cat_command, cat_rc, cat_override, cat_attr, cat_attmod, cat_id, cat_uuid, cat_subst, cat_pattern, cat_rx, cat_tag, cat_dom_, cat_dom, cat_op, cat_literal};
|
||||
enum type {type_none=20, type_pseudo, type_bool, type_string, type_date, type_duration, type_number};
|
||||
|
||||
Arg ();
|
||||
|
|
49
src/E9.cpp
49
src/E9.cpp
|
@ -135,21 +135,23 @@ void E9::eval (const Task& task, std::vector <Arg>& value_stack)
|
|||
Arg left = value_stack.back ();
|
||||
value_stack.pop_back ();
|
||||
|
||||
if (arg->_raw == "and") operator_and (result, left, right);
|
||||
else if (arg->_raw == "or") operator_or (result, left, right);
|
||||
else if (arg->_raw == "xor") operator_xor (result, left, right);
|
||||
else if (arg->_raw == "<") operator_lt (result, left, right);
|
||||
else if (arg->_raw == "<=") operator_lte (result, left, right);
|
||||
else if (arg->_raw == ">=") operator_gte (result, left, right);
|
||||
else if (arg->_raw == ">") operator_gt (result, left, right);
|
||||
else if (arg->_raw == "!=") operator_inequal (result, left, right, case_sensitive);
|
||||
else if (arg->_raw == "=") operator_equal (result, left, right, case_sensitive);
|
||||
else if (arg->_raw == "~") operator_match (result, left, right, case_sensitive, task);
|
||||
else if (arg->_raw == "!~") operator_nomatch (result, left, right, case_sensitive, task);
|
||||
else if (arg->_raw == "*") operator_multiply (result, left, right);
|
||||
else if (arg->_raw == "/") operator_divide (result, left, right);
|
||||
else if (arg->_raw == "+") operator_add (result, left, right);
|
||||
else if (arg->_raw == "-") operator_subtract (result, left, right);
|
||||
if (arg->_raw == "and") operator_and (result, left, right);
|
||||
else if (arg->_raw == "or") operator_or (result, left, right);
|
||||
else if (arg->_raw == "xor") operator_xor (result, left, right);
|
||||
else if (arg->_raw == "<") operator_lt (result, left, right);
|
||||
else if (arg->_raw == "<=") operator_lte (result, left, right);
|
||||
else if (arg->_raw == ">=") operator_gte (result, left, right);
|
||||
else if (arg->_raw == ">") operator_gt (result, left, right);
|
||||
else if (arg->_raw == "!=") operator_inequal (result, left, right, case_sensitive);
|
||||
else if (arg->_raw == "=") operator_equal (result, left, right, case_sensitive);
|
||||
else if (arg->_raw == "~") operator_match (result, left, right, case_sensitive, task);
|
||||
else if (arg->_raw == "!~") operator_nomatch (result, left, right, case_sensitive, task);
|
||||
else if (arg->_raw == "*") operator_multiply (result, left, right);
|
||||
else if (arg->_raw == "/") operator_divide (result, left, right);
|
||||
else if (arg->_raw == "+") operator_add (result, left, right);
|
||||
else if (arg->_raw == "-") operator_subtract (result, left, right);
|
||||
else if (arg->_raw == "_hastag_") operator_hastag (result, right, false, task);
|
||||
else if (arg->_raw == "_notag_") operator_hastag (result, right, true, task);
|
||||
else
|
||||
throw format (STRING_E9_UNSUPPORTED, arg->_raw);
|
||||
}
|
||||
|
@ -628,6 +630,23 @@ void E9::operator_subtract (Arg& result, Arg& left, Arg& right)
|
|||
// std::cout << "# " << left << " <operator_subtract> " << right << " --> " << result << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void E9::operator_hastag (
|
||||
Arg& result,
|
||||
Arg& right,
|
||||
bool invert,
|
||||
const Task& task)
|
||||
{
|
||||
result._type = Arg::type_bool;
|
||||
|
||||
if (task.hasTag (right._raw))
|
||||
result._value = invert ? "false" : "true";
|
||||
else
|
||||
result._value = invert ? "true" : "false";
|
||||
|
||||
std::cout << "# tags" << (invert ? " <operator_notag> " : " <operator_hastag> ") << right << " --> " << result << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const Arg E9::coerce (const Arg& input, const Arg::type type)
|
||||
{
|
||||
|
|
1
src/E9.h
1
src/E9.h
|
@ -67,6 +67,7 @@ private:
|
|||
void operator_divide (Arg&, Arg&, Arg&);
|
||||
void operator_add (Arg&, Arg&, Arg&);
|
||||
void operator_subtract (Arg&, Arg&, Arg&);
|
||||
void operator_hastag (Arg&, Arg&, bool, const Task&);
|
||||
|
||||
const Arg coerce (const Arg&, const Arg::type);
|
||||
bool get_bool (const Arg&);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue