=================================================================== RCS file: /cvs/todotxt/Text-Todo/bin/todo.pl,v retrieving revision 1.2 retrieving revision 1.10 diff -u -r1.2 -r1.10 --- todotxt/Text-Todo/bin/todo.pl 2010/01/10 07:13:54 1.2 +++ todotxt/Text-Todo/bin/todo.pl 2010/01/11 00:18:25 1.10 @@ -1,5 +1,5 @@ #!/usr/bin/perl -# $RedRiver: todo.pl,v 1.1 2010/01/09 05:25:44 andrew Exp $ +# $RedRiver: todo.pl,v 1.9 2010/01/11 00:17:38 andrew Exp $ ######################################################################## # todo.pl *** a perl version of todo.sh. Uses Text::Todo. # @@ -22,28 +22,34 @@ # option defaults my $config_file = $ENV{HOME} . '/todo.cfg'; +CONFIG: foreach my $f ( $config_file, $ENV{HOME} . '/.todo.cfg', ) { + if ( -e $f ) { + $config_file = $f; + last CONFIG; + } +} my %actions = ( - add => \&unsupported, - addto => \&unsupported, - append => \&unsupported, - archive => \&unsupported, - command => \&unsupported, - del => \&unsupported, - depri => \&unsupported, - do => \&unsupported, - help => \&unsupported, + add => \&add, + addto => \&addto, + append => \&append, + archive => \&archive, + command => \&command, + del => \&del, + depri => \&depri, + do => \&mark_done, + help => \&help, list => \&list, - listall => \&unsupported, - listcon => \&unsupported, - listfile => \&unsupported, - listpri => \&unsupported, - listproj => \&unsupported, - move => \&unsupported, - prepend => \&unsupported, - pri => \&unsupported, - replace => \&unsupported, - report => \&unsupported, + listall => \&listall, + listcon => \&listcon, + listfile => \&listfile, + listpri => \&listpri, + listproj => \&listproj, + move => \&move, + prepend => \&prepend, + pri => \&pri, + replace => \&replace, + report => \&report, ); my %aliases = ( @@ -55,7 +61,7 @@ lsa => 'listall', lsc => 'listcon', lf => 'listfile', - lsp => 'listri', + lsp => 'listpri', lsprj => 'listproj', mv => 'move', prep => 'prepend', @@ -79,9 +85,9 @@ usage( $opts{h} ); } -my @unsupported = grep { defined $opts{$_} } qw( @ + f h p P n t v V ); +my @unsupported = grep { defined $opts{$_} } qw( @ + f h p P t v V ); if (@unsupported) { - die 'Unsupported options: ' . ( join q{, }, @unsupported ) . "\n"; + warn 'Unsupported options: ' . ( join q{, }, @unsupported ) . "\n"; } if ( $opts{d} ) { @@ -96,16 +102,257 @@ usage(); } +sub add { + my ( $config, @entry ) = @_; + if ( !@entry ) { + die "usage: todo.pl add 'item'\n"; + } + + my $entry = join q{ }, @entry; + + my $todo = Text::Todo->new($config); + if ( $todo->add($entry) ) { + my @list = $todo->list; + my $lines = scalar @list; + + print "TODO: '$entry' added on line $lines\n"; + + return $lines; + } + die "Unable to add [$entry]\n"; +} + +sub addto { + my ( $config, $file, @entry ) = @_; + if ( !( $file && @entry ) ) { + die "usage: todo.pl addto DEST 'TODO ITEM'\n"; + } + + my $entry = join q{ }, @entry; + + my $todo = Text::Todo->new($config); + + $file = $todo->file($file); + if ( $todo->addto( $file, $entry ) ) { + my @list = $todo->listfile($file); + my $lines = scalar @list; + + print "TODO: '$entry' added to $file on line $lines\n"; + + return $lines; + } + die "Unable to add [$entry]\n"; +} + +sub append { + my ( $config, $line, @text ) = @_; + if ( !( $line && @text && $line =~ /^\d+$/xms ) ) { + die 'usage: todo.pl append ITEM# "TEXT TO APPEND"' . "\n"; + } + + my $text = join q{ }, @text; + + my $todo = Text::Todo->new($config); + my $entry = $todo->list->[ $line - 1 ]; + + if ( $entry->append($text) && $todo->save ) { + return printf "%02d: %s\n", $line, $entry->text; + } + die "Unable to append\n"; +} + +sub archive { + my ($config) = @_; + my $todo = Text::Todo->new($config); + + my $file = $todo->file; + + my $archived = $todo->archive; + if ( defined $archived ) { + return print "TODO: $file archived.\n"; + } + die "Unable to archive $file\n"; +} + +sub command { return &unsupported } + +sub del { + my ( $config, $line ) = @_; + if ( !( $line && $line =~ /^\d+$/xms ) ) { + die 'usage: todo.pl del ITEM#' . "\n"; + } + my $todo = Text::Todo->new($config); + + my $entry = $todo->list->[ $line - 1 ]; + print "Delete '" . $entry->text . "'? (y/n)\n"; + warn "XXX No delete confirmation currently!\n"; + + if ( $opts{n} ) { + if ( $todo->del($entry) && $todo->save ) { + return print 'TODO: \'', $entry->text, "' deleted.\n"; + } + } + else { + my $text = $entry->text; + if ( $entry->replace(q{}) && $todo->save ) { + return print 'TODO: \'', $text, "' deleted.\n"; + } + } + + die "Unable to delete entry\n"; +} + +sub depri { + my ( $config, $line ) = @_; + if ( !( $line && $line =~ /^\d+$/xms ) ) { + die 'usage: todo.pl del ITEM#' . "\n"; + } + my $todo = Text::Todo->new($config); + + my $entry = $todo->list->[ $line - 1 ]; + if ( $entry->depri && $todo->save ) { + return print $line, ': ', $entry->text, "\n", + 'TODO: ', $line, " deprioritized.\n"; + } + die "Unable to deprioritize entry\n"; +} + +sub mark_done { return &unsupported } +sub help { return &unsupported } + sub list { + my ( $config, $term ) = @_; + my $todo = Text::Todo->new($config); + + my @list = _number_list( $todo->list ); + my $shown = _show_sorted_list( $term, @list ); + + return _show_list_footer( $shown, scalar @list, $config->{todo_file} ); +} + +sub listall { + my ( $config, $term ) = @_; + my $todo = Text::Todo->new($config); + + my @list = _number_list( + $todo->listfile('todo_file'), + $todo->listfile('done_file'), + ); + my $shown = _show_sorted_list( $term, @list ); + + return _show_list_footer( $shown, scalar @list, $config->{'todo_dir'} ); +} + +sub listcon { my ($config) = @_; my $todo = Text::Todo->new($config); - $todo->load( $config->{todo_file} ) || die "Couldn't load todo_file\n"; + return print map {"\@$_\n"} $todo->listcon; +} - foreach my $entry ( sort { lc $a->text cmp lc $b->text } $todo->list ) { - print $entry->text, "\n" or warn "Couldn't print: \n"; +sub listfile { + my ( $config, $file, $term ) = @_; + if ( !$file ) { + die "usage: todo.pl listfile SRC [TERM]\n"; } + my $todo = Text::Todo->new($config); + + my @list = _number_list( $todo->listfile($file) ); + my $shown = _show_sorted_list( $term, @list ); + + return _show_list_footer( $shown, scalar @list, $file ); } +sub listpri { + my ( $config, $pri ) = @_; + + my $todo = Text::Todo->new($config); + + my @list = _number_list( $todo->listfile('todo_file') ); + my @pri_list; + if ($pri) { + $pri = uc $pri; + if ( $pri !~ /^[A-Z]$/xms ) { + die "usage: todo.pl listpri PRIORITY\n", + "note: PRIORITY must a single letter from A to Z.\n"; + } + @pri_list = grep { + defined $_->{entry}->priority + && $_->{entry}->priority eq $pri + } @list; + } + else { + @pri_list = grep { $_->{entry}->priority } @list; + } + + my $shown = _show_sorted_list( undef, @pri_list ); + + return _show_list_footer( $shown, scalar @list, $config->{todo_file} ); +} + +sub listproj { + my ($config) = @_; + my $todo = Text::Todo->new($config); + return print map {"\+$_\n"} $todo->listproj; +} + +sub move { return &unsupported } + +sub prepend { + my ( $config, $line, @text ) = @_; + if ( !( $line && @text && $line =~ /^\d+$/xms ) ) { + die 'usage: todo.pl prepend ITEM# "TEXT TO PREPEND"' . "\n"; + } + + my $text = join q{ }, @text; + + my $todo = Text::Todo->new($config); + my $entry = $todo->list->[ $line - 1 ]; + + if ( $entry->prepend($text) && $todo->save ) { + return printf "%02d: %s\n", $line, $entry->text; + } + die "Unable to prepend\n"; +} + +sub pri { return &unsupported } +sub replace { return &unsupported } +sub report { return &unsupported } + +sub _number_list { + my (@list) = @_; + + my $line = 1; + return map { { line => $line++, entry => $_, } } @list; +} + +sub _show_sorted_list { + my ( $term, @list ) = @_; + $term = defined $term ? quotemeta($term) : ''; + + my $shown = 0; + my @sorted = map { sprintf "%02d %s", $_->{line}, $_->{entry}->text } + sort { lc $a->{entry}->text cmp lc $b->{entry}->text } @list; + + foreach my $line ( grep {/$term/xms} @sorted ) { + print $line, "\n"; + $shown++; + } + + return $shown; +} + +sub _show_list_footer { + my ( $shown, $total, $file ) = @_; + + $shown ||= 0; + $total ||= 0; + + print "-- \n"; + print "TODO: $shown of $total tasks shown from $file\n"; + + return 1; +} + sub unsupported { die "Unsupported action\n" } sub usage { @@ -114,11 +361,11 @@ print <<'EOL'; * command list taken from todo.sh for compatibility Usage: todo.pl [-fhpantvV] [-d todo_config] action - EOL if ($long) { print <<'EOL'; + Actions: add|a "THING I NEED TO DO +project @context" addto DEST "TEXT TO ADD" @@ -155,7 +402,7 @@ my ($file) = @_; my %config; - open my $fh, '<', $file or die "Unable to open [$file]: $!"; + open my $fh, '<', $file or die "Unable to open [$file] : $!"; LINE: while (<$fh>) { s/\r?\n$//xms; s/\s*\#.*$//xms;