[BACK]Return to dudelicious.pl CVS log [TXT][DIR] Up to [local] / todotxt / Text-Todo / bin

Annotation of todotxt/Text-Todo/bin/dudelicious.pl, Revision 1.16

1.8       andrew      1: #!/usr/bin/perl
1.1       andrew      2:
1.2       andrew      3: package Dudelicious;
                      4:
1.10      andrew      5: use 5.010;
1.6       andrew      6: use Data::Dumper;
1.4       andrew      7: use version; our $VERSION = qv('0.1.0');
                      8:
1.6       andrew      9: BEGIN {
                     10:     use FindBin;
                     11:     use lib "$FindBin::Bin/../lib";
1.8       andrew     12:     use lib "$FindBin::Bin/../mojo/lib";
1.6       andrew     13: }
1.2       andrew     14:
1.5       andrew     15: use Carp qw/ carp croak /;
1.6       andrew     16: use Digest::MD5 qw/ md5_hex /;
                     17: use Text::Todo;
1.5       andrew     18:
1.1       andrew     19: use Mojolicious::Lite;
1.6       andrew     20: use Mojo::JSON;
1.5       andrew     21:
                     22: app->home->parse( $ENV{DUDELICIOUS_HOME} ) if $ENV{DUDELICIOUS_HOME};
1.1       andrew     23:
1.6       andrew     24: plugin 'json_config' => {
                     25:     file    => 'dudelicious.conf',
                     26:     default => { todo_dir => $ENV{DUDELICIOUS_HOME} || '.', },
                     27: };
1.1       andrew     28:
1.10      andrew     29: app->renderer->add_helper(
                     30:     todo => sub {
1.12      andrew     31:         my ($self) = @_;
                     32:         state $todo = Text::Todo->new( $self->stash('config') );
                     33:
                     34:         my $file = $self->stash('file');
                     35:         if ($file) {
                     36:             $file =~ s/(?:\.txt)?$/\.txt/ixms;
                     37:             $todo->load($file);
                     38:         }
                     39:
1.10      andrew     40:         return $todo;
                     41:     }
                     42: );
                     43:
                     44: app->renderer->add_helper(
                     45:     get_list => sub {
1.12      andrew     46:         my ($self) = @_;
1.10      andrew     47:
                     48:         my $line = 1;
                     49:         return [
                     50:             map {
1.11      andrew     51:                 line     => $line++,
                     52:                     md5  => md5_hex( $_->text ),
                     53:                     text => $_->text,
                     54:                     done => $_->done,
1.10      andrew     55:             },
                     56:             $self->helper('todo')->list
                     57:         ];
                     58:     }
                     59: );
                     60:
1.5       andrew     61: get '/' => sub {
1.1       andrew     62:     my $self = shift;
1.5       andrew     63:
1.10      andrew     64:     my $dir = $self->helper('todo')->file('todo_dir');
1.5       andrew     65:     opendir my $dh, $dir or croak "Unable to opendir $dir: $!";
                     66:     my @files = grep {/\.te?xt$/ixms} readdir $dh;
                     67:     closedir $dh;
                     68:
                     69:     $self->render( files => \@files, layout => 'todotxt' );
                     70: } => 'index';
                     71:
1.9       andrew     72: get '/todotxt' => 'todotxt';
                     73:
1.5       andrew     74: get '/l/:file' => sub {
1.12      andrew     75:     my $self = shift;
                     76:
1.6       andrew     77:     my $format = $self->stash('format') || 'html';
1.5       andrew     78:
1.6       andrew     79:     if ( $format eq 'json' ) {
1.12      andrew     80:         $self->render_json( $self->helper('get_list') );
1.6       andrew     81:     }
                     82:     else {
1.12      andrew     83:         $self->render(
                     84:             list   => $self->helper('get_list'),
1.16    ! andrew     85:             tags   => $self->helper('todo')->known_tags,
1.12      andrew     86:             layout => 'todotxt'
                     87:         );
1.6       andrew     88:     }
1.5       andrew     89: } => 'list';
                     90:
1.6       andrew     91: get '/l/:file/e/:line' => sub {
1.12      andrew     92:     my $self = shift;
                     93:
1.6       andrew     94:     my $format = $self->stash('format') || 'html';
1.12      andrew     95:     my $entry = $self->helper('get_list')->[ $self->stash('line') - 1 ];
1.6       andrew     96:
                     97:     if ( $format eq 'json' ) {
1.7       andrew     98:         $self->render_json($entry);
1.6       andrew     99:     }
                    100:     else {
1.7       andrew    101:         $self->render( entry => $entry, layout => 'todotxt' );
1.6       andrew    102:     }
1.5       andrew    103: } => 'entry';
1.1       andrew    104:
1.12      andrew    105: get '/l/:file/t' => sub {
                    106:     my $self = shift;
                    107:
                    108:     my $format = $self->stash('format') || 'html';
                    109:
                    110:     if ( $format eq 'json' ) {
1.13      andrew    111:         $self->render_json( $self->helper('todo')->known_tags );
1.12      andrew    112:     }
                    113:     else {
1.13      andrew    114:         $self->render(
                    115:             tags   => $self->helper('todo')->known_tags,
                    116:             layout => 'todotxt'
                    117:         );
1.12      andrew    118:     }
                    119: } => 'tags';
                    120:
1.13      andrew    121: get '/l/:file/t/:tag' => sub {
                    122:     my $self = shift;
                    123:
                    124:     my $format = $self->stash('format') || 'html';
                    125:     my $items  = $self->helper('todo')->listtag( $self->stash('tag') );
                    126:
                    127:     if ( $format eq 'json' ) {
                    128:         $self->render_json($items);
                    129:     }
                    130:     else {
                    131:         $self->render( items => $items, layout => 'todotxt' );
                    132:     }
                    133: } => 'tag';
                    134:
1.11      andrew    135: app->start if !caller();
1.5       andrew    136:
1.12      andrew    137: 1;
1.1       andrew    138: __DATA__
                    139:
1.5       andrew    140: @@ list.txt.ep
1.6       andrew    141: % foreach my $entry (@{ $list }) {
                    142: %==  include 'entry', entry => $entry;
1.5       andrew    143: % }
                    144:
                    145: @@ entry.txt.ep
1.6       andrew    146: <%= $entry->{text} %>
1.5       andrew    147:
1.12      andrew    148: @@ tags.txt.ep
1.13      andrew    149: % foreach my $tag (keys %{ $tags }) {
1.15      andrew    150: <%= $tag %>: <%= $tags->{$tag} %>
1.12      andrew    151: % }
                    152:
1.13      andrew    153: @@ tag.txt.ep
1.15      andrew    154: # <%== $tag %>
1.13      andrew    155: % foreach my $item (@{ $items}) {
                    156: <%= $item %>
                    157: % }
                    158:
1.5       andrew    159: @@ layouts/todotxt.txt.ep
                    160: %= content
                    161:
1.1       andrew    162: @@ index.html.ep
1.5       andrew    163: % foreach my $file (@{ $files }) {
1.14      andrew    164: % my ($basename) = $file =~ /^(.*?)(?:\.[^\.]+)?$/xms;
1.16    ! andrew    165: <a href="<%= url_for 'list', format => '' %>/<%= $basename %>"><%= $file %></a><br />
1.5       andrew    166: % }
                    167:
                    168: @@ list.html.ep
                    169: <h1><%= $file %></h1>
1.16    ! andrew    170: % if ( $tags ) {
        !           171: %   foreach my $tag (keys%{ $tags }) {
        !           172: %= include 'tag_menu', tag => $tag
        !           173: <br />
        !           174: %   }
        !           175: % }
1.5       andrew    176: <ol>
1.6       andrew    177: % foreach my $entry (@{ $list }) {
1.5       andrew    178:     <li>
1.6       andrew    179: %=  include 'entry', entry => $entry;
1.5       andrew    180:     </li>
                    181: % }
                    182: </ol>
1.1       andrew    183:
1.5       andrew    184: @@ entry.html.ep
1.6       andrew    185: <%= $entry->{text} %>
1.5       andrew    186:
1.12      andrew    187: @@ tags.html.ep
                    188: % foreach my $tag (keys%{ $tags }) {
1.14      andrew    189: <a href="<%= url_for 'tag', format => '' %>/<%= $tag %>"><%= $tag %> == <%= $tags->{$tag} %></a><br />
1.12      andrew    190: % }
                    191:
1.13      andrew    192: @@ tag.html.ep
                    193: <h2><%= $tag %></h2>
1.16    ! andrew    194: % foreach my $item (sort @{ $items }) {
1.13      andrew    195: <%= $item %><br />
                    196: % }
1.12      andrew    197:
1.16    ! andrew    198: @@ tag_menu.html.ep
        !           199: % my $items = todo()->listtag($tag);
        !           200: <%= $tag %>:
        !           201: <select>
        !           202: % foreach my $item (sort @{ $items }) {
        !           203:     <option><%= $item %></option>
        !           204: % }
        !           205: </select>
        !           206:
        !           207:
1.5       andrew    208: @@ layouts/todotxt.html.ep
1.1       andrew    209: <!doctype html><html>
1.9       andrew    210:     <head>
                    211:         <title>Funky!</title>
                    212:         <link rel="stylesheet" href="<%= url_for 'todotxt', format => 'css' %>">
                    213:     </head>
1.1       andrew    214:     <body><%== content %></body>
                    215: </html>
1.4       andrew    216:
1.9       andrew    217: @@ todotxt.css.ep
                    218: body {
                    219:         background: LightGoldenRodYellow;
                    220:         color: DarkSlateBlue;
                    221: }
                    222:
                    223: .inplaceeditor-saving {
                    224:         background: url(images/saving.gif) bottom right no-repeat;
                    225: }
                    226:
                    227:
1.4       andrew    228: __END__
                    229:
                    230: =head1 NAME
                    231:
                    232: dudelicious - A Mojolicous interface to your todotxt files
                    233:
                    234: =head1 VERSION
                    235:
                    236: Since the $VERSION can't be automatically included,
                    237: here is the RCS Id instead, you'll have to look up $VERSION.
                    238:
1.16    ! andrew    239:     $Id: dudelicious.pl,v 1.15 2010/05/05 01:43:03 andrew Exp $
1.4       andrew    240:
                    241: =head1 SYNOPSIS
                    242:
                    243:     dudelicious daemon
                    244:
                    245: Then browse to http://localhost:3000/
                    246:
                    247: =head1 DESCRIPTION
                    248:
                    249: A Mojolicous web app for access to your todotxt files
                    250:
                    251: The modules are there to give more access to my todo.txt file from more
                    252: places.  My goal is a web API for a web interface and then a WebOS version for
                    253: my Palm Pre.
                    254:
                    255: For more information see L<http://todotxt.com>
                    256:
                    257: =head1 USAGE
                    258:
                    259: See todo.pl -h
                    260:
                    261: =head1 OPTIONS
                    262:
                    263: See todo.pl -h
                    264:
                    265: =head1 REQUIRED ARGUMENTS
                    266:
                    267: See todo.pl -h
                    268:
                    269: =head1 CONFIGURATION AND ENVIRONMENT
                    270:
                    271: =head1 DIAGNOSTICS
                    272:
                    273: =head1 DEPENDENCIES
                    274:
                    275: Perl Modules:
                    276:
                    277: =over
                    278:
                    279: =item Text::Todo
                    280:
                    281: =item Mojolicous::Lite
                    282:
                    283: =item version
                    284:
                    285: =back
                    286:
                    287:
                    288: =head1 BUGS AND LIMITATIONS
                    289:
                    290: No bugs have been reported.
                    291:
                    292: =head1 AUTHOR
                    293:
                    294: Andrew Fresh  C<< <andrew@cpan.org> >>
                    295:
                    296:
                    297: =head1 LICENSE AND COPYRIGHT
                    298:
                    299: Copyright (c) 2010, Andrew Fresh C<< <andrew@cpan.org> >>. All rights reserved.
                    300:
                    301: This module is free software; you can redistribute it and/or
                    302: modify it under the same terms as Perl itself. See L<perlartistic>.
                    303:
                    304:
                    305: =head1 DISCLAIMER OF WARRANTY
                    306:
                    307: BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
                    308: FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
                    309: OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
                    310: PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
                    311: EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                    312: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
                    313: ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
                    314: YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
                    315: NECESSARY SERVICING, REPAIR, OR CORRECTION.
                    316:
                    317: IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
                    318: WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
                    319: REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
                    320: LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
                    321: OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
                    322: THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
                    323: RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
                    324: FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
                    325: SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
                    326: SUCH DAMAGES.

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