Merge branch '2.4.5' of ssh://git.tasktools.org/tm/task into 2.4.5

This commit is contained in:
Paul Beckingham 2015-06-30 07:54:22 -04:00
commit 5d02291077
36 changed files with 324 additions and 750 deletions

View file

@ -340,15 +340,42 @@ void CLI2::lexArguments ()
{
// Note: Starts interating at index 1, because ::handleArg0 has already
// processed it.
bool terminated = false;
for (unsigned int i = 1; i < _original_args.size (); ++i)
{
std::string lexeme;
Lexer::Type type;
Lexer lex (_original_args[i]);
lex.ambiguity (false);
// The terminator itself is captured.
if (_original_args[i] == "--")
{
terminated = true;
_args.push_back (A2 (_original_args[i], Lexer::Type::separator));
}
while (lex.token (lexeme, type))
_args.push_back (A2 (lexeme, type));
// Any arguments that are after the terminator are captured as words.
else if (terminated)
{
A2 word (_original_args[i], Lexer::Type::word);
word.tag ("TERMINATED");
_args.push_back (word);
}
// rc:<file> and rc.<name>[:=]<value> argumenst are captured whole.
else if (_original_args[i].substr (0, 3) == "rc:" ||
_original_args[i].substr (0, 3) == "rc.")
{
_args.push_back (A2 (_original_args[i], Lexer::Type::pair));
}
// Everything else gets lexed.
else
{
std::string lexeme;
Lexer::Type type;
Lexer lex (_original_args[i]);
lex.ambiguity (false);
while (lex.token (lexeme, type))
_args.push_back (A2 (lexeme, type));
}
}
if (context.config.getInteger ("debug.parser") >= 3)
@ -414,51 +441,6 @@ void CLI2::analyze ()
context.debug (dump ("CLI2::analyze end"));
}
/*
////////////////////////////////////////////////////////////////////////////////
// There are situations where a context filter is applied. This method
// determines whether one applies, and if so, applies it. Disqualifiers include:
// - filter contains ID or UUID
void CLI2::addContextFilter ()
{
// Detect if any context is set, and bail out if not
std::string contextName = context.config.get ("context");
if (contextName == "")
{
context.debug ("No context applied.");
return;
}
// Detect if UUID or ID is set, and bail out
for (auto& a : _args)
{
// TODO This looks wrong.
if (a.hasTag ("FILTER") &&
a.hasTag ("ATTRIBUTE") &&
! a.hasTag ("TERMINATED") &&
! a.hasTag ("WORD") &&
(a.attribute ("raw") == "id" || a.attribute ("raw") == "uuid"))
{
context.debug (format ("UUID/ID lexeme found '{1}', not applying context.", a.attribute ("raw")));
return;
}
}
// Apply context
context.debug ("Applying context: " + contextName);
std::string contextFilter = context.config.get ("context." + contextName);
if (contextFilter == "")
context.debug ("Context '" + contextName + "' not defined.");
else
{
addRawFilter ("( " + contextFilter + " )");
if (context.verbose ("context"))
context.footnote (format ("Context '{1}' set. Use 'task context none' to remove.", contextName));
}
}
*/
////////////////////////////////////////////////////////////////////////////////
// Process raw string.
void CLI2::addFilter (const std::string& arg)
@ -480,6 +462,52 @@ void CLI2::addFilter (const std::string& arg)
analyze ();
}
////////////////////////////////////////////////////////////////////////////////
// There are situations where a context filter is applied. This method
// determines whether one applies, and if so, applies it. Disqualifiers include:
// - filter contains ID or UUID
void CLI2::addContextFilter ()
{
// Detect if any context is set, and bail out if not
std::string contextName = context.config.get ("context");
if (contextName == "")
{
context.debug ("No context applied.");
return;
}
/*
// Detect if UUID or ID is set, and bail out
for (auto& a : _args)
{
// TODO This is needed, but the parsing is not yet complete, so the logic
// below is not valid.
if (a.hasTag ("FILTER") &&
a.hasTag ("ATTRIBUTE") &&
! a.hasTag ("TERMINATED") &&
! a.hasTag ("WORD") &&
(a.attribute ("raw") == "id" || a.attribute ("raw") == "uuid"))
{
context.debug (format ("UUID/ID lexeme found '{1}', not applying context.", a.attribute ("raw")));
return;
}
}
*/
// Apply context
context.debug ("Applying context: " + contextName);
std::string contextFilter = context.config.get ("context." + contextName);
if (contextFilter == "")
context.debug ("Context '" + contextName + "' not defined.");
else
{
addFilter (contextFilter);
if (context.verbose ("context"))
context.footnote (format ("Context '{1}' set. Use 'task context none' to remove.", contextName));
}
}
////////////////////////////////////////////////////////////////////////////////
// Parse the command line, identifiying filter components, expanding syntactic
// sugar as necessary.
@ -489,6 +517,9 @@ void CLI2::prepareFilter (bool applyContext)
_id_ranges.clear ();
_uuid_list.clear ();
if (applyContext)
addContextFilter ();
// Classify FILTER and MODIFICATION args, based on CMD and READCMD/WRITECMD.
bool changes = false;
bool foundCommand = false;
@ -711,13 +742,15 @@ void CLI2::aliasExpansion ()
for (auto& i : _args)
{
raw = i.attribute ("raw");
if (_aliases.find (raw) != _aliases.end ())
if (i.hasTag ("TERMINATED"))
{
reconstructed.push_back (i);
}
else if (_aliases.find (raw) != _aliases.end ())
{
for (auto& l : Lexer::split (_aliases[raw]))
{
A2 a (l, Lexer::Type::word);
a.tag ("ALIAS");
a.tag ("LEX");
reconstructed.push_back (a);
}
@ -725,15 +758,25 @@ void CLI2::aliasExpansion ()
changes = true;
}
else
{
reconstructed.push_back (i);
}
}
_args = reconstructed;
std::vector <std::string> reconstructedOriginals;
bool terminated = false;
for (auto& i : _original_args)
{
if (_aliases.find (i) != _aliases.end ())
if (i == "--")
terminated = true;
if (terminated)
{
reconstructedOriginals.push_back (i);
}
else if (_aliases.find (i) != _aliases.end ())
{
for (auto& l : Lexer::split (_aliases[i]))
reconstructedOriginals.push_back (l);
@ -742,7 +785,9 @@ void CLI2::aliasExpansion ()
changes = true;
}
else
{
reconstructedOriginals.push_back (i);
}
}
_original_args = reconstructedOriginals;

View file

@ -73,10 +73,8 @@ public:
void add (const std::string&);
void analyze ();
/*
void addContextFilter ();
*/
void addFilter (const std::string& arg);
void addContextFilter ();
void prepareFilter (bool applyContext = true);
const std::vector <std::string> getWords (bool filtered = true);
bool canonicalize (std::string&, const std::string&, const std::string&) const;

View file

@ -73,7 +73,8 @@ void Filter::subset (const std::vector <Task>& input, std::vector <Task>& output
context.timer_filter.start ();
_startCount = (int) input.size ();
// context.cli2.prepareFilter (applyContext);
context.cli2.prepareFilter (applyContext);
std::vector <std::pair <std::string, Lexer::Type>> precompiled;
for (auto& a : context.cli2._args)
if (a.hasTag ("FILTER"))
@ -118,6 +119,8 @@ void Filter::subset (std::vector <Task>& output, bool applyContext /* = true */)
{
context.timer_filter.start ();
context.cli2.prepareFilter (applyContext);
std::vector <std::pair <std::string, Lexer::Type>> precompiled;
for (auto& a : context.cli2._args)
if (a.hasTag ("FILTER"))
@ -179,7 +182,7 @@ void Filter::subset (std::vector <Task>& output, bool applyContext /* = true */)
}
else
{
safety (precompiled.size ());
safety ();
context.timer_filter.stop ();
for (auto& task : context.tdb2.pending.get_tasks ())
@ -258,7 +261,7 @@ bool Filter::pendingOnly ()
////////////////////////////////////////////////////////////////////////////////
// Disaster avoidance mechanism. If a WRITECMD has no filter, then it can cause
// all tasks to be modified. This is usually not intended.
void Filter::safety (unsigned int terms)
void Filter::safety ()
{
for (auto& a : context.cli2._args)
{
@ -266,19 +269,16 @@ void Filter::safety (unsigned int terms)
{
if (a.hasTag ("WRITECMD"))
{
if (terms)
{
if (! context.config.getBoolean ("allow.empty.filter"))
throw std::string (STRING_TASK_SAFETY_ALLOW);
if (! context.config.getBoolean ("allow.empty.filter"))
throw std::string (STRING_TASK_SAFETY_ALLOW);
// If user is willing to be asked, this can be avoided.
if (context.config.getBoolean ("confirmation") &&
confirm (STRING_TASK_SAFETY_VALVE))
return;
// If user is willing to be asked, this can be avoided.
if (context.config.getBoolean ("confirmation") &&
confirm (STRING_TASK_SAFETY_VALVE))
return;
// Sounds the alarm.
throw std::string (STRING_TASK_SAFETY_FAIL);
}
// Sounds the alarm.
throw std::string (STRING_TASK_SAFETY_FAIL);
}
// CMD was found.

View file

@ -43,7 +43,7 @@ public:
void subset (const std::vector <Task>&, std::vector <Task>&, bool applyContext = true);
void subset (std::vector <Task>&, bool applyContext = true);
bool pendingOnly ();
void safety (unsigned int);
void safety ();
private:
int _startCount;

View file

@ -61,16 +61,9 @@ void ISO8601d::ambiguity (bool value)
// | date-ext 'T' time-ext offset-ext # Specified TZ
// | date-ext 'T' time-ext # Local
// | date-ext # Local
// | date 'T' time 'Z'
// | date 'T' time offset-ext
// | date 'T' time
// | date
// | time-ext 'Z'
// | time-ext offset-ext Not needed
// | time-ext
// | time 'Z'
// | time offset
// | time
// ;
//
// date-ext ::= ±YYYYY-MM-DD Νot needed
@ -83,37 +76,14 @@ void ISO8601d::ambiguity (bool value)
// | YYYY-Www
// ;
//
// date ::= ±YYYYYMMDD Νot needed
// | ±YYYYYWwwD Νot needed
// | ±YYYYYWww Νot needed
// | ±YYYYYDDD Νot needed
// | ±YYYYYMM Νot needed
// | ±YYYYY Νot needed
// | ±YYY Νot needed
// | YYYYMMDD Ambiguous (number)
// | YYYYWwwD
// | YYYYWww
// | YYYYDDD Ambiguous (number)
// | YYYY-MM
// | YYYY Ambiguous (number)
// | YY Ambiguous (number)
// ;
//
// time-ext ::= hh:mm:ss[,ss]
// | hh:mm[,mm]
// | hh[,hh] Ambiguous (number)
// ;
//
// time ::= hhmmss[,ss] Ambiguous (number)
// | hhmm[,mm] Ambiguous (number)
// | hh[,hh] Ambiguous (number)
// ;
//
// time-utc-ext ::= hh:mm[:ss] 'Z' ;
// time-utc ::= hh[mm[ss]] 'Z' ;
//
// offset-ext ::= ±hh[:mm] ;
// offset ::= ±hh[mm] ;
//
// Not yet supported:
//
@ -136,12 +106,7 @@ bool ISO8601d::parse (const std::string& input, std::string::size_type& start)
parse_date_ext (n) ||
parse_time_utc_ext (n) ||
parse_time_off_ext (n) ||
parse_date_time (n) ||
parse_date (n, _ambiguity) ||
parse_time_utc (n) ||
parse_time_off (n) ||
parse_time_ext (n) || // Time last, as it is the most permissive.
parse_time (n, _ambiguity))
parse_time_ext (n)) // Time last, as it is the most permissive.
{
// Check the values and determine time_t.
if (validate ())
@ -214,47 +179,6 @@ bool ISO8601d::parse_date_time_ext (Nibbler& n)
return false;
}
////////////////////////////////////////////////////////////////////////////////
// date 'T' time 'Z'
// date 'T' time offset
// date 'T' time
bool ISO8601d::parse_date_time (Nibbler& n)
{
Nibbler backup (n);
if (parse_date (n, true))
{
if (n.skip ('T') &&
parse_time (n, true))
{
if (n.skip ('Z'))
{
_utc = true;
if (!Lexer::isDigit (n.next ()))
return true;
}
else if (parse_off (n))
{
if (!Lexer::isDigit (n.next ()))
return true;
}
if (!Lexer::isDigit (n.next ()))
return true;
}
// Restore date
_year = 0;
_month = 0;
_week = 0;
_weekday = 0;
_julian = 0;
_day = 0;
}
n = backup;
return false;
}
////////////////////////////////////////////////////////////////////////////////
// YYYY-MM-DD
// YYYY-DDD
@ -303,64 +227,6 @@ bool ISO8601d::parse_date_ext (Nibbler& n)
return false;
}
////////////////////////////////////////////////////////////////////////////////
// YYYYMMDD Ambiguous (number)
// YYYYWwwD
// YYYYWww
// YYYYDDD Ambiguous (number)
// YYYY-MM
bool ISO8601d::parse_date (Nibbler& n, bool ambiguous)
{
Nibbler backup (n);
int year;
if (n.getDigit4 (year))
{
int month;
if (n.skip ('W'))
{
int week;
if (n.getDigit2 (week))
{
_week = week;
int day;
if (n.getDigit (day))
_weekday = day;
_year = year;
if (!Lexer::isDigit (n.next ()))
return true;
}
}
else if (n.skip ('-'))
{
if (n.getDigit2 (_month))
{
_year = year;
if (!Lexer::isDigit (n.next ()))
return true;
}
}
else if (n.getDigit4 (month))
{
_year = year;
_month = month / 100;
_day = month % 100;
if (!Lexer::isDigit (n.next ()))
return true;
}
else if (ambiguous && n.getDigit3 (_julian))
{
_year = year;
if (!Lexer::isDigit (n.next ()))
return true;
}
}
n = backup;
return false;
}
////////////////////////////////////////////////////////////////////////////////
// ±hh[:mm]
bool ISO8601d::parse_off_ext (Nibbler& n)
@ -394,37 +260,7 @@ bool ISO8601d::parse_off_ext (Nibbler& n)
}
////////////////////////////////////////////////////////////////////////////////
// ±hh[mm]
bool ISO8601d::parse_off (Nibbler& n)
{
Nibbler backup (n);
std::string sign;
if (n.getN (1, sign))
{
if (sign == "+" || sign == "-")
{
int offset;
int hh;
if (n.getDigit2 (hh))
{
offset = hh * 3600;
int mm;
if (n.getDigit2 (mm))
offset += mm * 60;
_offset = (sign == "-") ? -offset : offset;
if (!Lexer::isDigit (n.next ()))
return true;
}
}
}
n = backup;
return false;
}
////////////////////////////////////////////////////////////////////////////////
// hh[:mm[:ss]]
// hh:mm[:ss]
bool ISO8601d::parse_time_ext (Nibbler& n)
{
Nibbler backup (n);
@ -433,20 +269,15 @@ bool ISO8601d::parse_time_ext (Nibbler& n)
int mm;
int ss;
if (n.getDigit2 (hh) &&
!n.getDigit (mm))
n.skip (':') &&
n.getDigit2 (mm))
{
seconds = hh * 3600;
seconds = (hh * 3600) + (mm * 60);
if (n.skip (':') &&
n.getDigit2 (mm) &&
!n.getDigit (ss))
n.getDigit2 (ss))
{
seconds += mm * 60;
if (n.skip (':') &&
n.getDigit2 (ss))
seconds += ss;
seconds += ss;
_seconds = seconds;
return true;
}
@ -463,35 +294,6 @@ bool ISO8601d::parse_time_ext (Nibbler& n)
return false;
}
////////////////////////////////////////////////////////////////////////////////
// hhmm[ss]
bool ISO8601d::parse_time (Nibbler& n, bool ambiguous)
{
if (!ambiguous)
return false;
Nibbler backup (n);
int seconds = 0;
int hh;
int mm;
if (n.getDigit2 (hh) &&
n.getDigit2 (mm))
{
seconds = hh * 3600 + mm * 60;
int ss;
if (n.getDigit2 (ss))
seconds += ss;
_seconds = seconds;
if (!Lexer::isDigit (n.next ()))
return true;
}
n = backup;
return false;
}
////////////////////////////////////////////////////////////////////////////////
// time-ext 'Z'
bool ISO8601d::parse_time_utc_ext (Nibbler& n)
@ -509,23 +311,6 @@ bool ISO8601d::parse_time_utc_ext (Nibbler& n)
return false;
}
////////////////////////////////////////////////////////////////////////////////
// time 'Z'
bool ISO8601d::parse_time_utc (Nibbler& n)
{
n.save ();
if (parse_time (n, true) &&
n.skip ('Z'))
{
_utc = true;
if (!Lexer::isDigit (n.next ()))
return true;
}
n.restore ();
return false;
}
////////////////////////////////////////////////////////////////////////////////
// time-ext offset-ext
bool ISO8601d::parse_time_off_ext (Nibbler& n)
@ -542,22 +327,6 @@ bool ISO8601d::parse_time_off_ext (Nibbler& n)
return false;
}
////////////////////////////////////////////////////////////////////////////////
// time offset
bool ISO8601d::parse_time_off (Nibbler& n)
{
Nibbler backup (n);
if (parse_time (n, true) &&
parse_off (n))
{
if (!Lexer::isDigit (n.next ()))
return true;
}
n = backup;
return false;
}
////////////////////////////////////////////////////////////////////////////////
// Using Zeller's Congruence.
int ISO8601d::dayOfWeek (int year, int month, int day)

View file

@ -45,17 +45,11 @@ public:
private:
bool parse_date_time_ext (Nibbler&);
bool parse_date_time (Nibbler&);
bool parse_date_ext (Nibbler&);
bool parse_date (Nibbler&, bool);
bool parse_off_ext (Nibbler&);
bool parse_off (Nibbler&);
bool parse_time_ext (Nibbler&);
bool parse_time (Nibbler&, bool);
bool parse_time_utc_ext (Nibbler&);
bool parse_time_utc (Nibbler&);
bool parse_time_off_ext (Nibbler&);
bool parse_time_off (Nibbler&);
int dayOfWeek (int, int, int);
bool validate ();
void resolve ();

View file

@ -324,6 +324,15 @@ void Lexer::dequote (std::string& input)
}
}
////////////////////////////////////////////////////////////////////////////////
bool Lexer::wasQuoted (const std::string& input)
{
if (input.find_first_of (" \t()") != std::string::npos)
return true;
return false;
}
////////////////////////////////////////////////////////////////////////////////
bool Lexer::isEOS () const
{

View file

@ -63,18 +63,19 @@ public:
// Static helpers.
static const std::string typeName (const Lexer::Type&);
static bool isWhitespace (int);
static bool isAlpha (int);
static bool isDigit (int);
static bool isHexDigit (int);
static bool isIdentifierStart (int);
static bool isIdentifierNext (int);
static bool isSingleCharOperator (int);
static bool isDoubleCharOperator (int, int, int);
static bool isTripleCharOperator (int, int, int, int);
static bool isBoundary (int, int);
static bool isPunctuation (int);
static void dequote (std::string&);
static bool isWhitespace (int);
static bool isAlpha (int);
static bool isDigit (int);
static bool isHexDigit (int);
static bool isIdentifierStart (int);
static bool isIdentifierNext (int);
static bool isSingleCharOperator (int);
static bool isDoubleCharOperator (int, int, int);
static bool isTripleCharOperator (int, int, int, int);
static bool isBoundary (int, int);
static bool isPunctuation (int);
static void dequote (std::string&);
static bool wasQuoted (const std::string&);
// Helpers.
bool isEOS () const;

View file

@ -1092,6 +1092,7 @@ bool Task::hasTag (const std::string& tag) const
{
// Synthetic tags - dynamically generated, but do not occupy storage space.
// Note: This list must match that in CmdInfo::execute.
// Note: This list must match that in ::feedback_reserved_tags.
if (tag == "BLOCKED") return is_blocked;
if (tag == "UNBLOCKED") return !is_blocked;
if (tag == "BLOCKING") return is_blocking;
@ -2094,11 +2095,13 @@ void Task::modify (modType type, bool text_required /* = false */)
else if (a._lextype == Lexer::Type::tag)
{
std::string tag = a.attribute ("name");
feedback_reserved_tags (tag);
if (a.attribute ("sign") == "+")
{
context.debug (label + "tags <-- add '" + tag + "'");
addTag (tag);
feedback_special_tags ((*this), tag);
feedback_special_tags (*this, tag);
}
else
{

View file

@ -63,8 +63,7 @@ int CmdCalc::execute (std::string& output)
// Compile all the args into one expression.
std::string expression;
std::vector <std::string> words = context.cli2.getWords ();
for (auto& word : words)
for (auto& word : context.cli2.getWords ())
expression += word + " ";
// Evaluate according to preference.

View file

@ -81,10 +81,7 @@ int CmdCustom::execute (std::string& output)
// Add the report filter to any existing filter.
if (reportFilter != "")
{
context.cli2.addFilter (reportFilter);
context.cli2.prepareFilter ();
}
// Apply filter.
handleRecurrence ();

View file

@ -303,6 +303,7 @@ int CmdInfo::execute (std::string& output)
// Virtual tags.
{
// Note: This list must match that in Task::hasTag.
// Note: This list must match that in ::feedback_reserved_tags.
std::string virtualTags = "";
if (task.hasTag ("ACTIVE")) virtualTags += "ACTIVE ";
if (task.hasTag ("ANNOTATED")) virtualTags += "ANNOTATED ";

View file

@ -351,6 +351,41 @@ void feedback_affected (const std::string& effect, const Task& task)
}
}
////////////////////////////////////////////////////////////////////////////////
// Implements feedback and error when adding a reserved tag name.
void feedback_reserved_tags (const std::string& tag)
{
// Note: This list must match that in Task::hasTag.
// Note: This list must match that in CmdInfo::execute.
if (tag == "BLOCKED" ||
tag == "UNBLOCKED" ||
tag == "BLOCKING" ||
tag == "READY" ||
tag == "DUE" ||
tag == "DUETODAY" ||
tag == "TODAY" ||
tag == "YESTERDAY" ||
tag == "TOMORROW" ||
tag == "OVERDUE" ||
tag == "WEEK" ||
tag == "MONTH" ||
tag == "YEAR" ||
tag == "ACTIVE" ||
tag == "SCHEDULED" ||
tag == "CHILD" ||
tag == "UNTIL" ||
tag == "ANNOTATED" ||
tag == "TAGGED" ||
tag == "PARENT" ||
tag == "WAITING" ||
tag == "PENDING" ||
tag == "COMPLETED" ||
tag == "DELETED")
{
throw format (STRING_FEEDBACK_TAG_VIRTUAL, tag);
}
}
////////////////////////////////////////////////////////////////////////////////
// Implements feedback when adding special tags to a task.
void feedback_special_tags (const Task& task, const std::string& tag)

View file

@ -792,6 +792,7 @@
#define STRING_FEEDBACK_TAG_NONAG "Das besondere Schlagwort 'nonag' verhindert Nachfragen, wenn diese Aufgabe geändert wird."
#define STRING_FEEDBACK_TAG_NOCAL "Das besondere Schlagwort 'nocal' verhindert, dass diese Aufgabe im 'calendar'-Report erscheint."
#define STRING_FEEDBACK_TAG_NEXT "Das besondere Schlagwort 'next' erhöht die Dringlichkeit dieser Aufgabe, sodass sie im 'next'-Report erscheint."
#define STRING_FEEDBACK_TAG_VIRTUAL "Virtual tags (including '{1}') are reserved and may not be added or removed."
#define STRING_FEEDBACK_UNBLOCKED "Aufgabe {1} '{2}' entsperrt."
#define STRING_FEEDBACK_EXPIRED "Aufgabe {1} '{2}' ist abgelaufen und wurde gelöscht."
#define STRING_FEEDBACK_BACKLOG "Lokale Änderungen. Datenabgleich erforderlich."

View file

@ -372,7 +372,7 @@
#define STRING_CMD_UDAS_ORPHANS "{1} Orphan UDAs"
#define STRING_CMD_DELETE_USAGE "Deletes the specified task"
#define STRING_CMD_DELETE_CONFIRM "Permanently delete task {1} '{2}'?"
#define STRING_CMD_DELETE_CONFIRM "Delete task {1} '{2}'?"
#define STRING_CMD_DELETE_TASK "Deleting task {1} '{2}'."
#define STRING_CMD_DELETE_TASK_R "Deleting recurring task {1} '{2}'."
#define STRING_CMD_DELETE_CONFIRM_R "This is a recurring task. Do you want to delete all pending recurrences of this same task?"
@ -792,6 +792,7 @@
#define STRING_FEEDBACK_TAG_NONAG "The 'nonag' special tag will prevent nagging when this task is modified."
#define STRING_FEEDBACK_TAG_NOCAL "The 'nocal' special tag will keep this task off the 'calendar' report."
#define STRING_FEEDBACK_TAG_NEXT "The 'next' special tag will boost the urgency of this task so it appears on the 'next' report."
#define STRING_FEEDBACK_TAG_VIRTUAL "Virtual tags (including '{1}') are reserved and may not be added or removed."
#define STRING_FEEDBACK_UNBLOCKED "Unblocked {1} '{2}'."
#define STRING_FEEDBACK_EXPIRED "Task {1} '{2}' expired and was deleted."
#define STRING_FEEDBACK_BACKLOG "There are local changes. Sync required."

View file

@ -792,6 +792,7 @@
#define STRING_FEEDBACK_TAG_NONAG "Speciala etikedo 'nonag' antaŭmalebligitos molestojn, kiam oni modifus tiun taskon."
#define STRING_FEEDBACK_TAG_NOCAL "Speciala etikedo 'nocal' ekskluzivos tiun taskon ĉe raporto 'calendar'."
#define STRING_FEEDBACK_TAG_NEXT "Speciala etikedo 'next' pligrandigos la urĝecon de tiu tasko por ke ĝi aperus ĉe raporto 'next'."
#define STRING_FEEDBACK_TAG_VIRTUAL "Virtual tags (including '{1}') are reserved and may not be added or removed."
#define STRING_FEEDBACK_UNBLOCKED "Malblokis {1} '{2}'."
#define STRING_FEEDBACK_EXPIRED "Tasko {1} '{2}' fortempiĝis do estis viŝata."
#define STRING_FEEDBACK_BACKLOG "Estas lokaj ŝanĝoj. Sinkronigo devita."

View file

@ -804,6 +804,7 @@
#define STRING_FEEDBACK_TAG_NONAG "La marca especial 'nonag' evitará el recuerdo fastidioso cuando la tarea sea modificada."
#define STRING_FEEDBACK_TAG_NOCAL "La marca especial 'nocal' mantendrá esta tarea fuera del informe 'calendar'."
#define STRING_FEEDBACK_TAG_NEXT "La etiqueta especial 'next' aumentará la urgencia de esta tarea para que aparezca en el informe 'next'."
#define STRING_FEEDBACK_TAG_VIRTUAL "Virtual tags (including '{1}') are reserved and may not be added or removed."
#define STRING_FEEDBACK_UNBLOCKED "Desbloqueada {1} '{2}'."
#define STRING_FEEDBACK_EXPIRED "La tarea {1} '{2}' caducó y fue eliminada."
#define STRING_FEEDBACK_BACKLOG "Hay modificaciones locales. Se require una sincronización."

View file

@ -792,6 +792,7 @@
#define STRING_FEEDBACK_TAG_NONAG "The 'nonag' special tag will prevent nagging when this task is modified."
#define STRING_FEEDBACK_TAG_NOCAL "The 'nocal' special tag will keep this task off the 'calendar' report."
#define STRING_FEEDBACK_TAG_NEXT "The 'next' special tag will boost the urgency of this task so it appears on the 'next' report."
#define STRING_FEEDBACK_TAG_VIRTUAL "Virtual tags (including '{1}') are reserved and may not be added or removed."
#define STRING_FEEDBACK_UNBLOCKED "Unblocked {1} '{2}'."
#define STRING_FEEDBACK_EXPIRED "Tâche {1} '{2}' a expiré et a été supprimée."
#define STRING_FEEDBACK_BACKLOG "Il y a des changements locaux. Synchronisation requise."

View file

@ -791,6 +791,7 @@
#define STRING_FEEDBACK_TAG_NONAG "Il tag speciale 'nonag' eviterà problemi quando il task è modificato."
#define STRING_FEEDBACK_TAG_NOCAL "Il tag speciale 'nocal' manterrà il task fuori dal report 'calendar'."
#define STRING_FEEDBACK_TAG_NEXT "Il tag speciale 'next' aumenterà l'urgenza di questo task in modo che appaia nel report 'next'."
#define STRING_FEEDBACK_TAG_VIRTUAL "Virtual tags (including '{1}') are reserved and may not be added or removed."
#define STRING_FEEDBACK_UNBLOCKED "Sbloccato {1} '{2}'."
#define STRING_FEEDBACK_EXPIRED "Il task {1} '{2}' è scaduto ed è stato eliminato"
#define STRING_FEEDBACK_BACKLOG "There are local changes. Sync required."

View file

@ -792,6 +792,7 @@
#define STRING_FEEDBACK_TAG_NONAG "The 'nonag' special tag will prevent nagging when this task is modified."
#define STRING_FEEDBACK_TAG_NOCAL "The 'nocal' special tag will keep this task off the 'calendar' report."
#define STRING_FEEDBACK_TAG_NEXT "The 'next' special tag will boost the urgency of this task so it appears on the 'next' report."
#define STRING_FEEDBACK_TAG_VIRTUAL "Virtual tags (including '{1}') are reserved and may not be added or removed."
#define STRING_FEEDBACK_UNBLOCKED "Unblocked {1} '{2}'."
#define STRING_FEEDBACK_EXPIRED "Task {1} '{2}' expired and was deleted."
#define STRING_FEEDBACK_BACKLOG "There are local changes. Sync required."

View file

@ -792,6 +792,7 @@
#define STRING_FEEDBACK_TAG_NONAG "Specjalny tag 'nonag' uchroni przed upierdliwością kiedy zadanie jest modyfikowane."
#define STRING_FEEDBACK_TAG_NOCAL "Specjalny tag 'nocal' spowoduje nie dodawanie zadania do kalendarza."
#define STRING_FEEDBACK_TAG_NEXT "Specjalny tag 'next' podniesie pilność tego zadania co spowoduje wyświetlenie go w raporcie 'next'."
#define STRING_FEEDBACK_TAG_VIRTUAL "Virtual tags (including '{1}') are reserved and may not be added or removed."
#define STRING_FEEDBACK_UNBLOCKED "Odblokowane {1} '{2}'."
#define STRING_FEEDBACK_EXPIRED "Zadanie {1} '{2}' jest przedawnione i zostało usunięte."
#define STRING_FEEDBACK_BACKLOG "Wykryto lokalne zmiany. Wymagana synchronizacja."

View file

@ -792,6 +792,7 @@
#define STRING_FEEDBACK_TAG_NONAG "A marca especial 'nonag' irá prevenir avisos quando a tarefa é modificada."
#define STRING_FEEDBACK_TAG_NOCAL "A marca especial 'nocal' irá manter esta tarefa ausente do relatório de 'calendário'."
#define STRING_FEEDBACK_TAG_NEXT "A marca especial 'next' irá aumentar a urgência desta tarefa de modo a que apareça no relatório 'next'."
#define STRING_FEEDBACK_TAG_VIRTUAL "Virtual tags (including '{1}') are reserved and may not be added or removed."
#define STRING_FEEDBACK_UNBLOCKED "Desbloqueada {1} '{2}'."
#define STRING_FEEDBACK_EXPIRED "Tarefa {1} '{2}' expirou e foi eliminada."
#define STRING_FEEDBACK_BACKLOG "Há modificações locais. Necessário sincronizar (sync)."

View file

@ -67,6 +67,7 @@ std::string renderAttribute (const std::string&, const std::string&, const std::
void feedback_affected (const std::string&);
void feedback_affected (const std::string&, int);
void feedback_affected (const std::string&, const Task&);
void feedback_reserved_tags (const std::string&);
void feedback_special_tags (const Task&, const std::string&);
void feedback_unblocked (const Task&);
void feedback_backlog ();