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
18 my $todo_file = "$ENV{HOME}/todo/todo.txt";
19 my $done_file = "$ENV{HOME}/todo/done.txt";
20 my $not_done_file = "$ENV{HOME}/todo/not_done.txt";
26 contexts
=> \
&list_contexts
,
27 groups
=> \
&list_groups
,
30 change
=> \
&change_task
,
36 unless ( (defined $command) && (exists $dispatch{$command}) );
39 $dispatch{$command}->(@ARGV);
45 my $task = join (" ", @_);
46 quit
("") unless $task;
48 # find out the group of the task
49 my (undef, $group) = ( $task =~ m{(^|\s)(/\S*)(\s|$)} );
51 my ($parent, $number) = ( $group =~ /(.*?)\.(\d+)/ );
53 my $target_offset = @tasks;
55 # insert properly if its a subtask
58 # also remember to strip the number
59 $task =~ s/$parent\.$number/$parent/;
61 my @candidate_ids = grep_pos_in_tasks
($parent, ());
62 my $length = @candidate_ids;
64 if( $number <= $length ) {
65 $target_offset = $candidate_ids[$number - 1] - 1;
69 splice @tasks, $target_offset, 0, ($task);
77 @patterns = ("") unless @patterns;
81 foreach my $pattern ( @patterns ) {
82 $is_a_group = 1 if( $pattern =~ m{^/} );
83 @candidates = grep_pos_in_tasks
( $pattern, @candidates );
86 # list tasks only if they are the first task from their group.
89 foreach my $id ( @candidates ) {
90 unless ($is_a_group) {
91 my (undef,$group) = ( $tasks[$id - 1] =~ m{(^|\s)(/\S*)(\s|$)} );
93 my $first = (grep_pos_in_tasks
( $group, () ))[0];
94 $out{$group} = $id if ($id == $first);
101 print_tasks
( values %out );
107 return print_tasks
( (1 .. scalar(@tasks)) )
111 foreach my $pattern ( @patterns ) {
112 @candidates = grep_pos_in_tasks
( $pattern, @candidates );
115 # list only one task per group from these results.
118 foreach my $id ( @candidates ) {
119 my (undef,$group) = ( $tasks[$id - 1] =~ m{(^|\s)(/\S*)(\s|$)} );
121 $out{$group} = $id if (!exists $out{$group});
127 print_tasks
( values %out );
133 my $file = shift || quit
("no file to move to!");
135 quit
("invalid task number") unless ((defined $num) && ($num =~ /^\d+$/));
136 quit
("") if ($num > @tasks);
138 my $task = splice @tasks, $num - 1, 1;
139 append_to_file
($task, $file);
146 move_task
($num, $done_file);
152 move_task
($num, $not_done_file);
157 open TODO
, "<$todo_file" or return;
170 open LOCK
, ">$todo_file.lock" or quit
("cannot open lock file : $!");
173 open TODO
, ">$todo_file.$$" or quit
("cannot open $todo_file.$$ : $!");
174 print TODO
join( "\n", @tasks );
177 rename( "$todo_file.$$", $todo_file ) or quit
("cannot rename : $!");
183 sub grep_pos_in_tasks
188 @positions = ( 1 .. scalar(@tasks) ) if( @positions < 1 );
191 foreach my $pos ( @positions ) {
192 push @ret, $pos if ( $tasks[$pos - 1] =~ /$pattern/ );
200 my $task = shift or quit
("no task to append!");
201 my $file = shift or quit
("no file to append to!");
202 my ($day, $mon, $year) = (localtime) [3 .. 5];
206 open LOCK
, ">$file.lock" or quit
("cannot open lock file : $!");
209 open DONE
, ">>$file" or quit
("cannot open $file.$$ : $!");
210 print DONE
"$year-$mon-$day : $task", "\n";
230 $ret{$2}++ if (/(^|\s)($pattern.*?)(\s|$)/);
238 my @contexts = extract_tokens
('@');
239 print join( "\n", @contexts, "" );
244 my @groups = extract_tokens
('/');
245 print join( "\n", @groups, "" );
251 my $new_task = join(" ", @_);
253 quit
("not a valid task number") unless ((defined $num) && ($num =~ /^\d+$/));
254 quit
("") if ($num > @tasks);
256 $tasks[$num - 1] = $new_task;
264 foreach my $id ( sort { $a <=> $b } @ids ) {
265 print "$id : $tasks[$id - 1]", "\n";