=================================================================== RCS file: /cvs/todotxt/Text-Todo/lib/Text/Todo/Entry.pm,v retrieving revision 1.10 retrieving revision 1.16 diff -u -r1.10 -r1.16 --- todotxt/Text-Todo/lib/Text/Todo/Entry.pm 2010/01/09 07:07:31 1.10 +++ todotxt/Text-Todo/lib/Text/Todo/Entry.pm 2010/01/10 22:49:53 1.16 @@ -1,6 +1,6 @@ package Text::Todo::Entry; -# $RedRiver: Entry.pm,v 1.9 2010/01/08 17:41:56 andrew Exp $ +# $RedRiver: Entry.pm,v 1.15 2010/01/10 01:45:52 andrew Exp $ use warnings; use strict; @@ -17,51 +17,66 @@ my %tags_of; my %priority_of; my %completion_status_of; + my %known_tags_of; - my %tags = ( - context => q{@}, - project => q{+}, - ); - # XXX Should the completion (x) be case sensitive? - my $priority_completion_regex = qr/ + my $priority_completion_regex = qr{ ^ \s* - (?i: (x) \s+)? - (?i:\( ([A-Z]) \) \s+)? - /xms; + (?i: (x) \s*)? + (?i:\( ([A-Z]) \) \s*)? + }xms; - for my $tag ( keys %tags ) { - ## no critic strict - no strict 'refs'; # Violates use strict, but allows code generation - ## use critic + sub new { + my ( $class, $options ) = @_; - *{ $tag . 's' } = sub { - my ($self) = @_; - return $self->_tags($tag); - }; + my $self = bless anon_scalar(), $class; + my $ident = ident($self); - *{ 'in_' . $tag } = sub { - my ( $self, $item ) = @_; - return $self->_is_in( $tag . 's', $item ); + if ( !ref $options ) { + $options = { text => $options }; + } + elsif ( ref $options ne 'HASH' ) { + croak 'Invalid parameter passed!'; + } + + $known_tags_of{$ident} = { + context => q{@}, + project => q{+}, }; - } - sub replace { _update_entry(@_) } - sub depri { _set_priority( @_, '' ) } - sub pri { _set_priority(@_) } + if ( exists $options->{tags} && ref $options->{tags} eq 'HASH' ) { + foreach my $k ( keys %{ $options->{tags} } ) { + $known_tags_of{$ident}{$k} = $options->{tags}->{$k}; + } + } - sub new { - my ( $class, $text ) = @_; + for my $tag ( keys %{ $known_tags_of{$ident} } ) { + ## no critic strict + no strict + 'refs'; # Violates use strict, but allows code generation + ## use critic - my $self = bless anon_scalar(), $class; - my $ident = ident($self); + if ( !$self->can( $tag . 's' ) ) { + *{ $tag . 's' } = sub { + my ($self) = @_; + return $self->_tags($tag); + }; + } - $self->_update_entry($text); + if ( !$self->can( 'in_' . $tag ) ) { + *{ 'in_' . $tag } = sub { + my ( $self, $item ) = @_; + return $self->_is_in( $tag . 's', $item ); + }; + } + } + $self->replace( $options->{text} ); + return $self; } - sub _update_entry { + sub replace { my ( $self, $text ) = @_; my $ident = ident($self); @@ -69,10 +84,10 @@ $text_of{$ident} = $text; - foreach my $tag ( keys %tags ) { - my $symbol = quotemeta $tags{$tag}; + foreach my $tag ( keys %{ $known_tags_of{$ident} } ) { + my $symbol = quotemeta $known_tags_of{$ident}{$tag}; $tags_of{$ident}{$tag} = { map { $_ => q{} } - $text =~ / (?:^|\s) $symbol (\S+)/gxms }; + $text =~ / (?:^|\s) $symbol (\S*)/gxms }; } ( $completion_status_of{$ident}, $priority_of{$ident} ) = $text =~ / $priority_completion_regex /xms; @@ -100,7 +115,9 @@ return $text_of{$ident}; } - sub _set_priority { + sub depri { my ($self) = @_; return $self->pri(q{}) } + + sub pri { my ( $self, $new_pri ) = @_; my $ident = ident($self); @@ -140,15 +157,17 @@ push @new, $addition; } - return $self->_update_entry( join q{ }, @new, $new ); + return $self->replace( join q{ }, @new, $new ); } sub append { my ( $self, $addition ) = @_; - return $self->_update_entry( join q{ }, $self->text, $addition ); + return $self->replace( join q{ }, $self->text, $addition ); } - sub do { + ## no critic 'homonym' + sub do { # This is what it is called in todo.sh + ## use critic my ($self) = @_; my $ident = ident($self); @@ -174,137 +193,212 @@ =head1 NAME -Text::Todo::Entry - [One line description of module's purpose here] +Text::Todo::Entry - An object for manipulating an entry on a Text::Todo list =head1 VERSION -This document describes Text::Todo::Entry version 0.0.1 +Since the $VERSION can't be automatically included, +here is the RCS Id instead, you'll have to look up $VERSION. + $Id: Entry.pm,v 1.16 2010/01/10 22:49:53 andrew Exp $ + =head1 SYNOPSIS use Text::Todo::Entry; -=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. - - + my $entry = Text::Todo::Entry->new('text of entry'); + + $entry->append('+project'); + + if ($entry->in_project('project') && ! $entry->priority) { + print $entry->text, "\n"; + } + + =head1 DESCRIPTION -=for author to fill in: - Write a full description of the module and its features here. - Use subsections (=head2, =head3) as appropriate. +This module creates entries in a Text::Todo list. +It allows you to retrieve information about them and modify them. +For more information see L + =head1 INTERFACE -=for author to fill in: - 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 new +Creates an entry that can be manipulated. + + my $entry = Text::Todo::Entry->new([ + 'text of entry' | { + [ text => 'text of entry' ,] + [ tags => { additional_arg => 'identfier' }, ] + } ]); + +If you don't pass any text, creates a blank entry. + +See tags below for a description of additional tags. + =head2 text +Returns the text of the entry. + + print $entry->text, "\n"; + +=head2 pri + +Sets the priority of an entry. If the priority is set to an empty string, +clears the priority. + + $entry->pri('B'); + +Acceptible entries are an empty string, A-Z or a-z. Anything else will cause +an error. + +=head2 depri + +A convenience function that unsets priority by calling pri(''). + + $entry->depri; + =head2 priority -=head2 contexts +Returns the priority of an entry which may be an empty string if it is -=head2 in_context + my $priority = $entry->priority; -=head2 projects +=head2 tags -=head2 in_project +Each tag type generates two accessor functions {tag}s and in_{tag}. -=head2 replace +Current tags are context (@) and project (+). -=head2 prepend +When creating a new object you can pass in new tags to recognize. -=head2 append + my $entry = Text::Todo::Entry->new({ + text => 'do something DUE:2011-01-01', + tags => { due_date => 'DUE:' } + }); -=head2 do + my @due_dates = $entry->due_dates; -=head2 done +then @due_dates eq ( '2011-01-01' ); -=head2 pri +and you could also: -=head2 depri + if ($entry->in_due_date('2011-01-01')) { + # do something + } -=head1 DIAGNOSTICS -=for author to fill in: - List every single error and warning message that the module can - generate (even the ones that will "never happen"), with a full - explanation of each problem, one or more likely causes, and any - suggested remedies. +=over +=item {tag}s + + @tags = $entry->{tag}s; + +=item in_{tag} + +returns true if $entry is in the tag, false if not. + + if ($entry->in_{tag}('tag')) { + # do something + } + +=back + +=head3 context + +These are matched as a word beginning with @. + =over -=item C<< Error message here, perhaps with %s placeholders >> +=item contexts -[Description of error here] +=item in_context -=item C<< Another error message here >> +=back -[Description of error here] +=head3 project -[Et cetera, et cetera] +This is matched as a word beginning with +. +=over + +=item projects + +=item in_project + =back +=head2 replace +Replaces the text of an entry with completely new text. Useful if there has +been manual modification of the entry or just a new direction. + + $entry->replace('replacment text'); + +=head2 prepend + +Attaches text (with a trailing space) to the beginning of an entry. Puts it +after the done() "x" and the priority() letter. + + $entry->prepend('NEED HELP'); + +=head2 append + +Adds text to the end of an entry. +Useful for adding tags, or just additional information. + + $entry->append('@specific_store'); + +=head2 do + +Marks an entry as completed. + + $entry->do; + +Does this by prepending an 'x' to the beginning of the entry. + +=head2 done + +Returns true if an entry is marked complete and false if not. + + if (!$entry->done) { + # remind me to do it + } + + +=head1 DIAGNOSTICS + =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::Entry requires no configuration files or environment variables. -=head1 DEPENDENCIES +=head1 DEPENDENCIES -=for author to fill in: - A list of all the other modules that this module relies upon, - including any restrictions on versions, and an indication whether - the module is part of the standard Perl distribution, part of the - module's distribution, or must be installed separately. ] +Class::Std::Utils +List::Util +version -None. - =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. =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. + +Known limitations: + +Sometimes leading whitespace may get screwed up when making changes. It +doesn't seem to be particularly a problem, but if you use whitespace to indent +entries for some reason it could be. Please report any bugs or feature requests to C, or through the web interface at