[BACK]Return to Todo.pm CVS log [TXT][DIR] Up to [local] / todotxt / Text-Todo / lib / Text

Diff for /todotxt/Text-Todo/lib/Text/Todo.pm between version 1.1 and 1.8

version 1.1, 2009/07/09 19:21:34 version 1.8, 2010/01/09 06:26:43
Line 1 
Line 1 
 package Text::Todo;  package Text::Todo;
   
 # $RedRiver$  # $RedRiver: Todo.pm,v 1.6 2010/01/09 05:15:20 andrew Exp $
   
 use warnings;  use warnings;
 use strict;  use strict;
 use Carp;  use Carp;
   
   use Class::Std::Utils;
   use Text::Todo::Entry;
   use File::Spec;
   
   use Data::Dumper;
   
 use version; our $VERSION = qv('0.0.1');  use version; our $VERSION = qv('0.0.1');
   
 # Other recommended modules (uncomment to use):  {
 #  use IO::Prompt;  
 #  use Perl6::Export;  
 #  use Perl6::Slurp;  
 #  use Perl6::Say;  
   
       my %path_of;
       my %list_of;
       my %loaded_of;
   
 # Module implementation here      sub new {
           my ( $class, $options ) = @_;
   
           my $self = bless anon_scalar(), $class;
           my $ident = ident($self);
   
 1; # Magic true value required at end of module          $path_of{$ident} = {
               todo_dir    => undef,
               todo_file   => 'todo.txt',
               done_file   => undef,
               report_file => undef,
           };
   
           if ($options) {
               if ( ref $options eq 'HASH' ) {
                   foreach my $opt ( keys %{$options} ) {
                       if ( exists $path_of{$ident}{$opt} ) {
                           $self->_path_to( $opt, $options->{$opt} );
                       }
                       else {
                           carp "Invalid option [$opt]";
                       }
                   }
               }
               else {
                   if ( -d $options ) {
                       $self->_path_to( 'todo_dir', $options );
                   }
                   elsif ( $options =~ /\.txt$/ixms ) {
                       $self->_path_to( 'todo_file', $options );
                   }
                   else {
                       carp "Unknown options [$options]";
                   }
               }
           }
   
           my $file = $self->_path_to('todo_file');
           if ( defined $file && -e $file ) {
               $self->load();
           }
   
           return $self;
       }
   
       sub _path_to {
           my ( $self, $type, $path ) = @_;
           my $ident = ident($self);
   
           if ( $type eq 'todo_dir' ) {
               if ($path) {
                   $path_of{$ident}{$type} = $path;
               }
               return $path_of{$ident}{$type};
           }
   
           if ($path) {
               my ( $volume, $directories, $file )
                   = File::Spec->splitpath($path);
               $path_of{$ident}{$type} = $file;
   
               if ($volume) {
                   $directories = File::Spec->catdir( $volume, $directories );
               }
   
               # XXX Should we save complete paths to each file, mebbe only if
               # the dirs are different?
               if ($directories) {
                   $path_of{$ident}{todo_dir} = $directories;
               }
           }
   
           if ( $type =~ /(todo|done|report)_file/xms ) {
               if ( my ( $pre, $post )
                   = $path_of{$ident}{$type} =~ /^(.*)$1(.*)\.txt$/ixms )
               {
                   foreach my $f qw( todo done report ) {
                       if ( !defined $path_of{$ident}{ $f . '_file' } ) {
                           $path_of{$ident}{ $f . '_file' }
                               = $pre . $f . $post . '.txt';
                       }
                   }
               }
           }
   
           if ( defined $path_of{$ident}{todo_dir} ) {
               return File::Spec->catfile( $path_of{$ident}{todo_dir},
                   $path_of{$ident}{$type} );
           }
   
           return;
       }
   
       sub file {
           my ( $self, $file ) = @_;
           my $ident = ident($self);
   
           if ( defined $file && exists $path_of{$ident}{$file} ) {
               $file = $self->_path_to($file);
           }
           else {
               $file = $self->_path_to( 'todo_file', $file );
           }
   
           return $file;
       }
   
       sub load {
           my ( $self, $file ) = @_;
           my $ident = ident($self);
   
           $loaded_of{$ident} = undef;
   
           if ( $list_of{$ident} = $self->listfile($file) ) {
               $loaded_of{$ident} = $file;
               return 1;
           }
   
           return;
       }
   
       sub listfile {
           my ( $self, $file ) = @_;
   
           $file = $self->file($file);
   
           if ( !defined $file ) {
               carp q{file can't be found};
               return;
           }
   
           if ( !-e $file ) {
               carp "file [$file] does not exist";
               return;
           }
   
           my @list;
           open my $fh, '<', $file or croak "Couldn't open [$file]: $!";
           while (<$fh>) {
               s/\r?\n$//xms;
               next if !length $_;
               push @list, Text::Todo::Entry->new($_);
           }
           close $fh or croak "Couldn't close [$file]: $!";
   
           return wantarray ? @list : \@list;
       }
   
       sub save {
           my ( $self, $file ) = @_;
           my $ident = ident($self);
   
           $file = $self->file($file);
           if ( !defined $file ) {
               croak q{todo file can't be found};
           }
   
           open my $fh, '>', $file or croak "Couldn't open [$file]: $!";
           foreach my $e ( @{ $list_of{$ident} } ) {
               print {$fh} $e->text . "\n"
                   or croak "Couldn't print to [$file]: $!";
           }
           close $fh or croak "Couldn't close [$file]: $!";
   
           return 1;
       }
   
       sub list {
           my ($self) = @_;
           my $ident = ident($self);
   
           return if !$list_of{$ident};
           return wantarray ? @{ $list_of{$ident} } : $list_of{$ident};
       }
   
       sub listpri {
           my ($self) = @_;
   
           my @list = grep { $_->priority } $self->list;
   
           return wantarray ? @list : \@list;
       }
   
       sub add {
           my ( $self, $entry ) = @_;
           my $ident = ident($self);
   
           if ( !ref $entry ) {
               $entry = Text::Todo::Entry->new($entry);
           }
           elsif ( ref $entry ne 'Text::Todo::Entry' ) {
               croak(
                   'entry is a ' . ref($entry) . ' not a Text::Todo::Entry!' );
           }
   
           push @{ $list_of{$ident} }, $entry;
   
           return $entry;
       }
   
       sub del {
           my ( $self, $src ) = @_;
           my $ident = ident($self);
   
           my $id = $self->_find_entry_id($src);
   
           my @list = $self->list;
           my $entry = splice @list, $id, 1;
           $list_of{$ident} = \@list;
   
           return $entry;
       }
   
       sub move {
           my ( $self, $entry, $dst ) = @_;
           my $ident = ident($self);
   
           my $src  = $self->_find_entry_id($entry);
           my @list = $self->list;
   
           splice @list, $dst, 0, splice @list, $src, 1;
   
           $list_of{$ident} = \@list;
   
           return 1;
       }
   
       sub listproj {
           my ( $self, $entry, $dst ) = @_;
           my $ident = ident($self);
   
           my %available_projects;
           foreach my $e ( $self->list ) {
               foreach my $p ( $e->projects ) {
                   $available_projects{$p} = 1;
               }
           }
   
           my @projects = sort keys %available_projects;
   
           return wantarray ? @projects : \@projects;
       }
   
       sub archive { carp 'unsupported'; return }
   
       sub addto {
           my ( $self, $file, $entry ) = @_;
           my $ident = ident($self);
   
           $file = $self->file($file);
           if ( !defined $file ) {
               croak q{file can't be found};
           }
   
           open my $fh, '>>', $file or croak "Couldn't open [$file]: $!";
           print {$fh} $entry, "\n"
               or croak "Couldn't print to [$file]: $!";
           close $fh or croak "Couldn't close [$file]: $!";
   
           if ( defined $loaded_of{$ident} && $file eq $loaded_of{$ident} ) {
               return $self->load($file);
           }
   
           return 1;
       }
   
       sub _find_entry_id {
           my ( $self, $entry ) = @_;
           my $ident = ident($self);
   
           if ( ref $entry ) {
               if ( ref $entry ne 'Text::Todo::Entry' ) {
                   croak(    'entry is a '
                           . ref($entry)
                           . ' not a Text::Todo::Entry!' );
               }
   
               my @list = $self->list;
               foreach my $id ( 0 .. $#list ) {
                   if ( $list[$id] eq $entry ) {
                       return $id;
                   }
               }
           }
           elsif ( $entry =~ /^\d+$/xms ) {
               return $entry;
           }
   
           croak "Invalid entry [$entry]!";
       }
   }
   
   1;    # Magic true value required at end of module
 __END__  __END__
   
 =head1 NAME  =head1 NAME
   
 Text::Todo - [One line description of module's purpose here]  Text::Todo - Perl interface to todo_txt files
   
   
 =head1 VERSION  =head1 VERSION
   
 This document describes Text::Todo version 0.0.1  I will have to figure out how to include $VERSION in this somehow.
   
   Perhaps RCS Id is good enough?
   
       $Id$
   
 =head1 SYNOPSIS  =head1 SYNOPSIS
   
     use Text::Todo;      use Text::Todo;
   
 =for author to fill in:  
     Brief code example(s) here showing commonest usage(s).  
     This section will be as far as many users bother reading  
     so make it as educational and exeplary as possible.  
   
   
 =head1 DESCRIPTION  =head1 DESCRIPTION
   
 =for author to fill in:  For more information see L<http://todotxt.com>
     Write a full description of the module and its features here.  
     Use subsections (=head2, =head3) as appropriate.  
   
   
 =head1 INTERFACE  =head1 INTERFACE
   
 =for author to fill in:  =head2 new
     Write a separate section listing the public components of the modules  
     interface. These normally consist of either subroutines that may be  
     exported, or methods that may be called on objects belonging to the  
     classes provided by the module.  
   
   =head2 load
   
   =head2 save
   
   =head2 file
   
   =head2 list
   
   =head2 add
   
 =head1 DIAGNOSTICS  =head1 DIAGNOSTICS
   
 =for author to fill in:  =for author to fill in:
Line 82 
Line 374 
   
 =head1 CONFIGURATION AND ENVIRONMENT  =head1 CONFIGURATION AND ENVIRONMENT
   
 =for author to fill in:  
     A full explanation of any configuration system(s) used by the  
     module, including the names and locations of any configuration  
     files, and the meaning of any environment variables or properties  
     that can be set. These descriptions must also include details of any  
     configuration language used.  
   
 Text::Todo requires no configuration files or environment variables.  Text::Todo requires no configuration files or environment variables.
   
   Someday it should be able to read and use the todo.sh config file.
   
   
 =head1 DEPENDENCIES  =head1 DEPENDENCIES
   
 =for author to fill in:  =for author to fill in:
Line 105 
Line 392 
   
 =head1 INCOMPATIBILITIES  =head1 INCOMPATIBILITIES
   
 =for author to fill in:  
     A list of any modules that this module cannot be used in conjunction  
     with. This may be due to name conflicts in the interface, or  
     competition for system or program resources, or due to internal  
     limitations of Perl (for example, many modules that use source code  
     filters are mutually incompatible).  
   
 None reported.  None reported.
   
   
 =head1 BUGS AND LIMITATIONS  =head1 BUGS AND LIMITATIONS
   
 =for author to fill in:  
     A list of known problems with the module, together with some  
     indication Whether they are likely to be fixed in an upcoming  
     release. Also a list of restrictions on the features the module  
     does provide: data types that cannot be handled, performance issues  
     and the circumstances in which they may arise, practical  
     limitations on the size of data sets, special cases that are not  
     (yet) handled, etc.  
   
 No bugs have been reported.  No bugs have been reported.
   

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.8

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>