Merge branch '1.9.4' of tasktools.org:task into 1.9.4

This commit is contained in:
Paul Beckingham 2010-12-27 00:24:30 -05:00
commit 4a58fbdd53
9 changed files with 268 additions and 13 deletions

View file

@ -24,6 +24,8 @@
+ Added feature #574, default due dates (thanks to Erlan Sergaziev). + Added feature #574, default due dates (thanks to Erlan Sergaziev).
+ Added feature #575, including Danish holidays (thanks to Irfan Siddiqui). + Added feature #575, including Danish holidays (thanks to Irfan Siddiqui).
+ Eliminated dependency on ncurses. + Eliminated dependency on ncurses.
+ Added _query helper command for script writers, which accepts a filter like
any other report, but returns only full JSON.
+ Fixed bug #515, which displayed an incorrect message after duplicating a + Fixed bug #515, which displayed an incorrect message after duplicating a
non-existent task (thanks to Peter De Poorter). non-existent task (thanks to Peter De Poorter).
+ Fixed bug #529, where the 'depends' attribute was not mentioned in the + Fixed bug #529, where the 'depends' attribute was not mentioned in the

2
NEWS
View file

@ -11,6 +11,8 @@ New Features in taskwarrior 1.9.4
- The first month in the calendar report can now be changed with an offset - The first month in the calendar report can now be changed with an offset
value. value.
- No more dependency on ncurses. - No more dependency on ncurses.
- New '_query helper command for script writers, which accepts a filter like
any other report, but returns unformatted JSON.
- Assorted bug fixes. - Assorted bug fixes.
Please refer to the ChangeLog file for full details. There are too many to Please refer to the ChangeLog file for full details. There are too many to

View file

@ -1,13 +1,8 @@
#compdef task #compdef task
# #
# This script is currently unmaintained and was released for an earlier version
# of taskwarrior. We welcome any zsh user that wants to contribute to
# taskwarrior to take a look at this script and either confirm its working
# status or improve it. Please contact us at support@taskwarrior.org if you
# have further questions on how to contribute to taskwarrior.
#
# zsh completion for taskwarrior # zsh completion for taskwarrior
# #
# Copyright 2010 Johannes Schlatow
# Copyright 2009 P.C. Shyamshankar # Copyright 2009 P.C. Shyamshankar
# All rights reserved. # All rights reserved.
# #
@ -32,9 +27,38 @@
# 02110-1301 # 02110-1301
# USA # USA
# #
typeset -g _task_cmds _task_projects _task_tags _task_config _task_modifiers
typeset -g _task_cmds _task_projects=($(task _projects))
_task_tags=($(task _tags))
_task_ids=($(task _ids))
_task_config=($(task _config))
_task_modifiers=(
'before' \
'after' \
'none' \
'any' \
'is' \
'isnt' \
'has' \
'hasnt' \
'startswith' \
'endswith' \
'word' \
'noword'
)
_task_cmds=($(task _commands)) _task_cmds=($(task _commands))
_task_idCmds=(
'append' \
'prepend' \
'annotate' \
'denotate' \
'edit' \
'duplicate' \
'info' \
'start' \
'stop' \
'done'
)
_task() { _task() {
_arguments -s -S \ _arguments -s -S \
@ -42,18 +66,177 @@ _task() {
return 0 return 0
} }
local -a reply args word
word=$'[^\0]#\0'
# priorities
local -a task_priorities
_regex_words task_prios 'task priorities' \
'H:High' \
'M:Middle' \
'L:Low'
task_priorities=("$reply[@]")
# projects
local -a task_projects
task_projects=(
/"$word"/
":task_projects:task projects:compadd -a _task_projects"
)
local -a _task_dates
_regex_words _task_dates 'task dates' \
'tod*ay:Today' \
'yes*terday:Yesterday' \
'tom*orrow:Tomorrow' \
'sow:Start of week' \
'soww:Start of work week' \
'socw:Start of calendar week' \
'som:Start of month' \
'soy:Start of year' \
'eow:End of week' \
'eoww:End of work week' \
'eocw:End of calendar week' \
'eom:End of month' \
'eoy:End of year' \
'mon:Monday' \
'tue:Tuesday'\
'wed:Wednesday' \
'thu:Thursday' \
'fri:Friday' \
'sat:Saturday' \
'sun:Sunday'
_task_dates=("$reply[@]")
local -a _task_reldates
_regex_words _task_reldates 'task reldates' \
'hrs:n hours' \
'day:n days' \
'1st:first' \
'2nd:second' \
'3rd:third' \
'th:4th, 5th, etc.' \
'wks:weeks'
_task_reldates=("$reply[@]")
task_dates=(
\( "$_task_dates[@]" \|
\( /$'[0-9][0-9]#'/- \( "$_task_reldates[@]" \) \)
\)
)
_regex_words _task_freqs 'task frequencies' \
'daily:Every day' \
'day:Every day' \
'weekdays:Every day skipping weekend days' \
'weekly:Every week' \
'biweekly:Every two weeks' \
'fortnight:Every two weeks' \
'quarterly:Every three months' \
'semiannual:Every six months' \
'annual:Every year' \
'yearly:Every year' \
'biannual:Every two years' \
'biyearly:Every two years'
_task_freqs=("$reply[@]")
local -a _task_frequencies
_regex_words _task_frequencies 'task frequencies' \
'd:days' \
'w:weeks' \
'q:quarters' \
'y:years'
_task_frequencies=("$reply[@]")
task_freqs=(
\( "$_task_freqs[@]" \|
\( /$'[0-9][0-9]#'/- \( "$_task_frequencies[@]" \) \)
\)
)
# attributes
local -a task_attributes
_regex_words -t ':' task_attr 'task attributes' \
'pro*ject:Project name:$task_projects' \
'du*e:Due date:$task_dates' \
'wa*it:Date until task becomes pending:$task_dates' \
're*cur:Recurrence frequency:$task_freqs' \
'pri*ority:priority:$task_priorities' \
'un*til:Recurrence end date:$task_dates' \
'fg:Foreground color' \
'bg:Background color' \
'li*mit:Desired number of rows in report'
task_attributes=("$reply[@]")
args=(
\( "$task_attributes[@]" \|
\( /'(project|due|wait|recur|priority|until|fg|bg|limit).'/- \( /$'[^:]#:'/ ":task_mods:modifiers:compadd -S ':' -a _task_modifiers" \) \) \|
\( /'(rc).'/- \( /$'[^:]#:'/ ":task_config:config:compadd -S ':' -a _task_config" \) \) \|
\( /'(+|-)'/- \( /"$word"/ ":task_rtag:remove tag:compadd -a _task_tags" \) \) \|
\( /"$word"/ \)
\) \#
)
_regex_arguments _task_attributes "${args[@]}"
## task commands
# default completion
(( $+functions[_task_default] )) ||
_task_default() {
_task_attributes "$@"
}
# commands expecting an ID
(( $+functions[_task_id] )) ||
_task_id() {
if (( CURRENT < 3 )); then
_describe -t ids 'task IDs' _task_ids
else
_task_attributes "$@"
fi
}
# merge completion
(( $+functions[_task_merge] )) ||
_task_merge() {
_files
}
# modify (task [0-9]* ...) completion
(( $+functions[_task_modify] )) ||
_task_modify() {
_describe -t commands 'task command' _task_idCmds
_task_attributes "$@"
}
## first level completion => task sub-command completion
(( $+functions[_task_commands] )) || (( $+functions[_task_commands] )) ||
_task_commands() { _task_commands() {
local cmd ret=1 local cmd ret=1
if (( CURRENT == 1 )); then if (( CURRENT == 1 )); then
_describe -t commands 'task command' _task_cmds # TODO add descriptions (assoz array)
else _describe -t commands 'task command' _task_cmds
# TODO match more than one ID
_describe -t ids 'task IDs' _task_ids
# TODO sorting
elif [[ $words[1] =~ ^[0-9]*$ ]] then
_call_function ret _task_modify
return ret
else
local curcontext="${curcontext}" local curcontext="${curcontext}"
cmd="${_task_cmds[(r)$words[1]:*]%%:*}" # cmd="${_task_cmds[(r)$words[1]:*]%%:*}"
cmd="${_task_cmds[(r)$words[1]]}"
idCmd="${(M)_task_idCmds[@]:#$words[1]}"
if (( $#cmd )); then if (( $#cmd )); then
curcontext="${curcontext%:*:*}:task-${cmd}" curcontext="${curcontext%:*:*}:task-${cmd}"
_call_function ret _task_${cmd} || _message "No command remaining."
if (( $#idCmd )); then
_call_function ret _task_id
else
_call_function ret _task_${cmd} ||
_call_function ret _task_default ||
_message "No command remaining."
fi
else else
_message "Unknown subcommand ${cmd}" _message "Unknown subcommand ${cmd}"
fi fi

View file

@ -135,6 +135,7 @@ void Cmd::load ()
commands.push_back ("_config"); commands.push_back ("_config");
commands.push_back ("_version"); commands.push_back ("_version");
commands.push_back ("_urgency"); commands.push_back ("_urgency");
commands.push_back ("_query");
commands.push_back ("export.csv"); commands.push_back ("export.csv");
commands.push_back ("export.ical"); commands.push_back ("export.ical");
commands.push_back ("export.yaml"); commands.push_back ("export.yaml");
@ -241,6 +242,7 @@ bool Cmd::isReadOnlyCommand ()
command == "_config" || command == "_config" ||
command == "_version" || command == "_version" ||
command == "_urgency" || command == "_urgency" ||
command == "_query" ||
command == "export.csv" || command == "export.csv" ||
command == "export.ical" || command == "export.ical" ||
command == "export.yaml" || command == "export.yaml" ||

View file

@ -259,6 +259,7 @@ int Context::dispatch (std::string &out)
else if (cmd.command == "_config") { rc = handleCompletionConfig (out); } else if (cmd.command == "_config") { rc = handleCompletionConfig (out); }
else if (cmd.command == "_version") { rc = handleCompletionVersion (out); } else if (cmd.command == "_version") { rc = handleCompletionVersion (out); }
else if (cmd.command == "_urgency") { rc = handleUrgency (out); } else if (cmd.command == "_urgency") { rc = handleUrgency (out); }
else if (cmd.command == "_query") { rc = handleQuery (out); }
else if (cmd.command == "" && else if (cmd.command == "" &&
sequence.size ()) { rc = handleModify (out); } sequence.size ()) { rc = handleModify (out); }

View file

@ -424,6 +424,29 @@ std::string Task::composeYAML () const
return out.str (); return out.str ();
} }
////////////////////////////////////////////////////////////////////////////////
std::string Task::composeJSON () const
{
std::stringstream out;
out << "{";
std::map <std::string, Att>::const_iterator i;
for (i = this->begin (); i != this->end (); ++i)
{
if (i != this->begin ())
out << ",";
out << "\""
<< i->second.name ()
<< "\":\""
<< i->second.value ()
<< "\"";
}
out << "}";
return out.str ();
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void Task::getAnnotations (std::vector <Att>& annotations) const void Task::getAnnotations (std::vector <Att>& annotations) const
{ {

View file

@ -45,6 +45,7 @@ public:
void parse (const std::string&); void parse (const std::string&);
std::string composeCSV () const; std::string composeCSV () const;
std::string composeYAML () const; std::string composeYAML () const;
std::string composeJSON () const;
// Status values. // Status values.
enum status {pending, completed, deleted, recurring, waiting}; enum status {pending, completed, deleted, recurring, waiting};

View file

@ -552,6 +552,46 @@ int handleUrgency (std::string& outs)
return 0; return 0;
} }
////////////////////////////////////////////////////////////////////////////////
int handleQuery (std::string& outs)
{
int rc = 0;
if (context.hooks.trigger ("pre-query-command"))
{
// Get all the tasks.
std::vector <Task> tasks;
context.tdb.lock (context.config.getBoolean ("locking"));
handleRecurrence ();
context.tdb.load (tasks, context.filter);
context.tdb.commit ();
context.tdb.unlock ();
// Filter sequence.
if (context.sequence.size ())
context.filter.applySequence (tasks, context.sequence);
// Note: "limit:" feature not supported.
// Compose output.
outs = "{";
std::vector <Task>::iterator t;
for (t = tasks.begin (); t != tasks.end (); ++t)
{
if (t != tasks.begin ())
outs += ",\n";
outs += t->composeJSON ();
}
outs += "}\n";
context.hooks.trigger ("post-query-command");
}
return rc;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
int handleCompletionIDs (std::string& outs) int handleCompletionIDs (std::string& outs)
{ {

View file

@ -68,6 +68,7 @@ int handleCompletionIDs (std::string&);
int handleCompletionConfig (std::string&); int handleCompletionConfig (std::string&);
int handleCompletionVersion (std::string&); int handleCompletionVersion (std::string&);
int handleUrgency (std::string&); int handleUrgency (std::string&);
int handleQuery (std::string&);
int handleVersion (std::string&); int handleVersion (std::string&);
int handleConfig (std::string&); int handleConfig (std::string&);
int handleShow (std::string&); int handleShow (std::string&);