4 #### Copyright 2008, Devendra Gera <gera@theoldmonk.net>,
5 #### All rights reserved.
7 #### This is Free Software, released under the terms of the GNU General Public
8 #### License, version 2. A copy of the license can be obtained by emailing the
9 #### author, or from http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
11 #### As noted in the License, this software does not come with any warranty,
12 #### explicit or implied. This program might, and would be buggy. Use it at
19 my $todo_file = "$ENV{HOME}/todo/todo.txt";
20 my $done_file = "$ENV{HOME}/todo/done.txt";
21 my $not_done_file = "$ENV{HOME}/todo/not_done.txt";
27 contexts
=> \
&list_contexts
,
28 groups
=> \
&list_groups
,
31 change
=> \
&change_task
,
35 my $command = shift || "ls";
37 unless ( (defined $command) && (exists $dispatch{$command}) );
40 $dispatch{$command}->(@ARGV);
46 my $task = join (" ", @_);
47 quit
("") unless $task;
49 # find out the group of the task
50 my (undef, $group) = ( $task =~ m{(^|\s)(/\S*)(\s|$)} );
52 my ($parent, $number) = ( $group =~ /(.*?)\.(\d+)/ );
54 my $target_offset = @tasks;
56 # insert properly if its a subtask
59 # also remember to strip the number
60 $task =~ s/$parent\.$number/$parent/;
62 my @candidate_ids = grep_pos_in_tasks
($parent, ());
63 my $length = @candidate_ids;
65 if( $number <= $length ) {
66 $target_offset = $candidate_ids[$number - 1] - 1;
70 splice @tasks, $target_offset, 0, ($task);
78 @patterns = ("") unless @patterns;
82 foreach my $pattern ( @patterns ) {
83 $is_a_group = 1 if( $pattern =~ m{^/} );
84 @candidates = grep_pos_in_tasks
( $pattern, @candidates );
87 # list tasks only if they are the first task from their group.
90 foreach my $id ( @candidates ) {
91 unless ($is_a_group) {
92 my (undef,$group) = ( $tasks[$id - 1] =~ m{(^|\s)(/\S*)(\s|$)} );
94 my $first = (grep_pos_in_tasks
( $group, () ))[0];
95 $out{$group} = $id if ($id == $first);
102 print_tasks
( values %out );
108 return print_tasks
( (1 .. scalar(@tasks)) )
112 foreach my $pattern ( @patterns ) {
113 @candidates = grep_pos_in_tasks
( $pattern, @candidates );
116 # list only one task per group from these results.
119 foreach my $id ( @candidates ) {
120 my (undef,$group) = ( $tasks[$id - 1] =~ m{(^|\s)(/\S*)(\s|$)} );
122 $out{$group} = $id if (!exists $out{$group});
128 print_tasks
( values %out );
134 my $file = shift || quit
("no file to move to!");
136 quit
("invalid task number") unless ((defined $num) && ($num =~ /^\d+$/));
137 quit
("") if ($num > @tasks);
139 my $task = splice @tasks, $num - 1, 1;
140 append_to_file
($task, $file);
147 my $num = ($flag =~ /^\d+$/) ?
$flag : shift;
149 my $ask = ($flag eq "-i") ?
1 : 0;
151 print "delete task $num <$tasks[$num - 1]> ?";
154 return if ($resp =~ /^n/i); # return if negative
157 move_task
($num, $done_file);
163 move_task
($num, $not_done_file);
168 open TODO
, "<$todo_file" or return;
181 open LOCK
, ">$todo_file.lock" or quit
("cannot open lock file : $!");
184 open TODO
, ">$todo_file.$$" or quit
("cannot open $todo_file.$$ : $!");
185 print TODO
join( "\n", @tasks );
188 rename( "$todo_file.$$", $todo_file ) or quit
("cannot rename : $!");
194 sub grep_pos_in_tasks
199 @positions = ( 1 .. scalar(@tasks) ) if( @positions < 1 );
202 foreach my $pos ( @positions ) {
203 push @ret, $pos if ( $tasks[$pos - 1] =~ /$pattern/ );
211 my $task = shift or quit
("no task to append!");
212 my $file = shift or quit
("no file to append to!");
213 my ($day, $mon, $year) = (localtime) [3 .. 5];
217 open LOCK
, ">$file.lock" or quit
("cannot open lock file : $!");
220 open DONE
, ">>$file" or quit
("cannot open $file.$$ : $!");
221 print DONE
"$year-$mon-$day : $task", "\n";
241 $ret{$2}++ if (/(^|\s)($pattern.*?)(\s|$)/);
249 my @contexts = extract_tokens
('@');
250 print join( "\n", @contexts, "" );
255 my @groups = extract_tokens
('/');
256 print join( "\n", @groups, "" );
262 my $new_task = join(" ", @_);
264 quit
("not a valid task number") unless ((defined $num) && ($num =~ /^\d+$/));
265 quit
("") if ($num > @tasks);
267 if($new_task =~ /^\s*$/) {
268 # wow - we don't have a task here - so we'll get one.
269 my $term = new Term
::ReadLine
'gtdo';
270 $new_task = $term->readline( "new task >", $tasks[$num - 1] );
273 return if($new_task =~ /^\s*$/);
275 $tasks[$num - 1] = $new_task;
283 foreach my $id ( sort { $a <=> $b } @ids ) {
284 print "$id : $tasks[$id - 1]", "\n";