diff --git a/src/Arguments.cpp b/src/Arguments.cpp index d8ce9acb4..1870c9506 100644 --- a/src/Arguments.cpp +++ b/src/Arguments.cpp @@ -154,7 +154,7 @@ void Arguments::capture (int argc, const char** argv) // be an absolute path, and Expression::expand_tokens would make a dog's // dinner out of it. std::vector parts; - if (is_multipart (argv[i], parts) && i != 0) + if (i && is_multipart (argv[i], parts)) { std::vector ::iterator part; for (part = parts.begin (); part != parts.end (); ++part) @@ -731,7 +731,7 @@ bool Arguments::is_multipart ( std::string part; while (n.getQuoted ('"', part) || n.getQuoted ('\'', part) || - n.getQuoted ('/', part) || +// n.getQuoted ('/', part) || <--- this line breaks subst. n.getUntilWS (part)) { n.skipWS (); @@ -864,14 +864,14 @@ bool Arguments::is_subst (const std::string& input) Nibbler n (input); if (n.skip ('/') && n.getUntil ('/', from) && + from.length () && n.skip ('/') && n.getUntil ('/', to) && n.skip ('/')) { n.skip ('g'); - if (n.depleted () && - ! Directory (input).exists () && // Ouch - expensive call. - from.length ()) + if (n.depleted () && + ! Directory (input).exists ()) // Ouch - expensive call. return true; } @@ -1376,6 +1376,14 @@ bool Arguments::extract_operator ( } //////////////////////////////////////////////////////////////////////////////// +// Almost all arguments are filters, except: +// subst +// program +// command +// rc +// override +// +// Special case: attr "limit" is ignored. Arguments Arguments::extract_read_only_filter () { Arguments filter; @@ -1389,7 +1397,6 @@ Arguments Arguments::extract_read_only_filter () arg->_third == "rc" || arg->_third == "override") { - ; } // Included. @@ -1424,6 +1431,10 @@ Arguments Arguments::extract_read_only_filter () } //////////////////////////////////////////////////////////////////////////////// +// A write filter includes id/uuid anywhere on the command line, but any other +// filter elements must occur before the command. +// +// Special case: attr "limit" is ignored. Arguments Arguments::extract_write_filter () { Arguments filter; @@ -1441,7 +1452,6 @@ Arguments Arguments::extract_write_filter () arg->_third == "rc" || arg->_third == "override") { - ; } // Included regardless of position. @@ -1471,10 +1481,13 @@ Arguments Arguments::extract_write_filter () // Error. else { - // substitution - throw std::string ("A substitution '") - + arg->_first - + "' is not allowed in a read-only command filter."; + if (before_command) + { + // substitution + throw std::string ("A substitution '") + + arg->_first + + "' is not allowed in a write command filter."; + } } } @@ -1574,13 +1587,13 @@ Arguments Arguments::extract_simple_words () } // Included. - else if (arg->_third == "tag" || - arg->_third == "pattern" || - arg->_third == "substitution" || - arg->_third == "id" || - arg->_third == "uuid" || - arg->_third == "op" || - arg->_third == "exp" || + else if (arg->_third == "tag" || + arg->_third == "pattern" || + arg->_third == "subst" || + arg->_third == "id" || + arg->_third == "uuid" || + arg->_third == "op" || + arg->_third == "exp" || arg->_third == "word") { // "limit" is special - it is recognized but not included in filters. diff --git a/src/Context.cpp b/src/Context.cpp index a694516df..99b21751c 100644 --- a/src/Context.cpp +++ b/src/Context.cpp @@ -119,8 +119,7 @@ int Context::initialize (int argc, const char** argv) // Instantiate built-in column objects. Column::factory (columns); - // Categorize all arguments one more time. - // TODO This may not be necessary. + // Categorize all arguments one more time. THIS IS NECESSARY. args.categorize (); // Handle default command and assumed 'info' command. diff --git a/src/Task.cpp b/src/Task.cpp index dc6c72bc0..0238433bd 100644 --- a/src/Task.cpp +++ b/src/Task.cpp @@ -861,8 +861,11 @@ void Task::substitute ( } } - set ("description", description); - setAnnotations (annotations); + if (changes) + { + set ("description", description); + setAnnotations (annotations); + } } //////////////////////////////////////////////////////////////////////////////// diff --git a/test/args.2.t b/test/args.2.t new file mode 100755 index 000000000..76f760f76 --- /dev/null +++ b/test/args.2.t @@ -0,0 +1,83 @@ +#! /usr/bin/perl +################################################################################ +## taskwarrior - a command line task list manager. +## +## Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez. +## All rights reserved. +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 2 of the License, or (at your option) any later +## version. +## +## This program is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, write to the +## +## Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, +## Boston, MA +## 02110-1301 +## USA +## +################################################################################ + +use strict; +use warnings; +use Test::More tests => 10; + +# Create the rc file. +if (open my $fh, '>', 'args.rc') +{ + print $fh "data.location=.\n", + "confirmation=off\n"; + close $fh; + ok (-r 'args.rc', 'Created args.rc'); +} + +# Test 'done' with en-passant changes. +qx{../src/task rc:args.rc add one}; +qx{../src/task rc:args.rc add two}; +qx{../src/task rc:args.rc add three}; +qx{../src/task rc:args.rc add four}; +qx{../src/task rc:args.rc add five}; + +qx{../src/task rc:args.rc 1 done oneanno}; +my $output = qx{../src/task rc:args.rc 1 info}; +like ($output, qr/oneanno/, 'done enpassant anno'); + +qx{../src/task rc:args.rc 2 done /two/TWO/}; +$output = qx{../src/task rc:args.rc 2 info}; +like ($output, qr/Description\s+TWO/, 'done enpassant subst'); + +qx{../src/task rc:args.rc 3 done +threetag}; +$output = qx{../src/task rc:args.rc 3 info}; +like ($output, qr/Tags\s+threetag/, 'done enpassant tag'); + +qx{../src/task rc:args.rc 4 done pri:H}; +$output = qx{../src/task rc:args.rc 4 info}; +like ($output, qr/Priority\s+H/, 'done enpassant priority'); + +qx{../src/task rc:args.rc 5 done pro:A}; +$output = qx{../src/task rc:args.rc 5 info}; +like ($output, qr/Project\s+A/, 'done enpassant project'); + +# Cleanup. +unlink 'pending.data'; +ok (!-r 'pending.data', 'Removed pending.data'); + +unlink 'completed.data'; +ok (!-r 'completed.data', 'Removed completed.data'); + +unlink 'undo.data'; +ok (!-r 'undo.data', 'Removed undo.data'); + +unlink 'args.rc'; +ok (!-r 'args.rc', 'Removed args.rc'); + +exit 0; + diff --git a/test/args.3.t b/test/args.3.t new file mode 100755 index 000000000..90c533ae6 --- /dev/null +++ b/test/args.3.t @@ -0,0 +1,83 @@ +#! /usr/bin/perl +################################################################################ +## taskwarrior - a command line task list manager. +## +## Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez. +## All rights reserved. +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 2 of the License, or (at your option) any later +## version. +## +## This program is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, write to the +## +## Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, +## Boston, MA +## 02110-1301 +## USA +## +################################################################################ + +use strict; +use warnings; +use Test::More tests => 10; + +# Create the rc file. +if (open my $fh, '>', 'args.rc') +{ + print $fh "data.location=.\n", + "confirmation=off\n"; + close $fh; + ok (-r 'args.rc', 'Created args.rc'); +} + +# Test 'delete' with en-passant changes. +qx{../src/task rc:args.rc add one}; +qx{../src/task rc:args.rc add two}; +qx{../src/task rc:args.rc add three}; +qx{../src/task rc:args.rc add four}; +qx{../src/task rc:args.rc add five}; + +qx{../src/task rc:args.rc 1 delete oneanno}; +my $output = qx{../src/task rc:args.rc 1 info}; +like ($output, qr/oneanno/, 'delete enpassant anno'); + +qx{../src/task rc:args.rc 2 delete /two/TWO/}; +$output = qx{../src/task rc:args.rc 2 info}; +like ($output, qr/Description\s+TWO/, 'delete enpassant subst'); + +qx{../src/task rc:args.rc 3 delete +threetag}; +$output = qx{../src/task rc:args.rc 3 info}; +like ($output, qr/Tags\s+threetag/, 'delete enpassant tag'); + +qx{../src/task rc:args.rc 4 delete pri:H}; +$output = qx{../src/task rc:args.rc 4 info}; +like ($output, qr/Priority\s+H/, 'delete enpassant priority'); + +qx{../src/task rc:args.rc 5 delete pro:A}; +$output = qx{../src/task rc:args.rc 5 info}; +like ($output, qr/Project\s+A/, 'delete enpassant project'); + +# Cleanup. +unlink 'pending.data'; +ok (!-r 'pending.data', 'Removed pending.data'); + +unlink 'completed.data'; +ok (!-r 'completed.data', 'Removed completed.data'); + +unlink 'undo.data'; +ok (!-r 'undo.data', 'Removed undo.data'); + +unlink 'args.rc'; +ok (!-r 'args.rc', 'Removed args.rc'); + +exit 0; + diff --git a/test/args.4.t b/test/args.4.t new file mode 100755 index 000000000..e1f89501d --- /dev/null +++ b/test/args.4.t @@ -0,0 +1,83 @@ +#! /usr/bin/perl +################################################################################ +## taskwarrior - a command line task list manager. +## +## Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez. +## All rights reserved. +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 2 of the License, or (at your option) any later +## version. +## +## This program is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, write to the +## +## Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, +## Boston, MA +## 02110-1301 +## USA +## +################################################################################ + +use strict; +use warnings; +use Test::More tests => 10; + +# Create the rc file. +if (open my $fh, '>', 'args.rc') +{ + print $fh "data.location=.\n", + "confirmation=off\n"; + close $fh; + ok (-r 'args.rc', 'Created args.rc'); +} + +# Test 'start' with en-passant changes. +qx{../src/task rc:args.rc add one}; +qx{../src/task rc:args.rc add two}; +qx{../src/task rc:args.rc add three}; +qx{../src/task rc:args.rc add four}; +qx{../src/task rc:args.rc add five}; + +qx{../src/task rc:args.rc 1 start oneanno}; +my $output = qx{../src/task rc:args.rc 1 info}; +like ($output, qr/oneanno/, 'start enpassant anno'); + +qx{../src/task rc:args.rc 2 start /two/TWO/}; +$output = qx{../src/task rc:args.rc 2 info}; +like ($output, qr/Description\s+TWO/, 'start enpassant subst'); + +qx{../src/task rc:args.rc 3 start +threetag}; +$output = qx{../src/task rc:args.rc 3 info}; +like ($output, qr/Tags\s+threetag/, 'start enpassant tag'); + +qx{../src/task rc:args.rc 4 start pri:H}; +$output = qx{../src/task rc:args.rc 4 info}; +like ($output, qr/Priority\s+H/, 'start enpassant priority'); + +qx{../src/task rc:args.rc 5 start pro:A}; +$output = qx{../src/task rc:args.rc 5 info}; +like ($output, qr/Project\s+A/, 'start enpassant project'); + +# Cleanup. +unlink 'pending.data'; +ok (!-r 'pending.data', 'Removed pending.data'); + +unlink 'completed.data'; +ok (!-r 'completed.data', 'Removed completed.data'); + +unlink 'undo.data'; +ok (!-r 'undo.data', 'Removed undo.data'); + +unlink 'args.rc'; +ok (!-r 'args.rc', 'Removed args.rc'); + +exit 0; + diff --git a/test/args.5.t b/test/args.5.t new file mode 100755 index 000000000..bcef61bc0 --- /dev/null +++ b/test/args.5.t @@ -0,0 +1,83 @@ +#! /usr/bin/perl +################################################################################ +## taskwarrior - a command line task list manager. +## +## Copyright 2006 - 2011, Paul Beckingham, Federico Hernandez. +## All rights reserved. +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 2 of the License, or (at your option) any later +## version. +## +## This program is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, write to the +## +## Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, +## Boston, MA +## 02110-1301 +## USA +## +################################################################################ + +use strict; +use warnings; +use Test::More tests => 10; + +# Create the rc file. +if (open my $fh, '>', 'args.rc') +{ + print $fh "data.location=.\n", + "confirmation=off\n"; + close $fh; + ok (-r 'args.rc', 'Created args.rc'); +} + +# Test 'stop' with en-passant changes. +qx{../src/task rc:args.rc add one}; +qx{../src/task rc:args.rc add two}; +qx{../src/task rc:args.rc add three}; +qx{../src/task rc:args.rc add four}; +qx{../src/task rc:args.rc add five}; + +qx{../src/task rc:args.rc 1 stop oneanno}; +my $output = qx{../src/task rc:args.rc 1 info}; +like ($output, qr/oneanno/, 'stop enpassant anno'); + +qx{../src/task rc:args.rc 2 stop /two/TWO/}; +$output = qx{../src/task rc:args.rc 2 info}; +like ($output, qr/Description\s+TWO/, 'stop enpassant subst'); + +qx{../src/task rc:args.rc 3 stop +threetag}; +$output = qx{../src/task rc:args.rc 3 info}; +like ($output, qr/Tags\s+threetag/, 'stop enpassant tag'); + +qx{../src/task rc:args.rc 4 stop pri:H}; +$output = qx{../src/task rc:args.rc 4 info}; +like ($output, qr/Priority\s+H/, 'stop enpassant priority'); + +qx{../src/task rc:args.rc 5 stop pro:A}; +$output = qx{../src/task rc:args.rc 5 info}; +like ($output, qr/Project\s+A/, 'stop enpassant project'); + +# Cleanup. +unlink 'pending.data'; +ok (!-r 'pending.data', 'Removed pending.data'); + +unlink 'completed.data'; +ok (!-r 'completed.data', 'Removed completed.data'); + +unlink 'undo.data'; +ok (!-r 'undo.data', 'Removed undo.data'); + +unlink 'args.rc'; +ok (!-r 'args.rc', 'Removed args.rc'); + +exit 0; +