Annotation of todotxt/Text-Todo/bin/dudelicious.pl, Revision 1.12
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'),
! 85: layout => 'todotxt'
! 86: );
1.6 andrew 87: }
1.5 andrew 88: } => 'list';
89:
1.6 andrew 90: get '/l/:file/e/:line' => sub {
1.12 ! andrew 91: my $self = shift;
! 92:
1.6 andrew 93: my $format = $self->stash('format') || 'html';
1.12 ! andrew 94: my $entry = $self->helper('get_list')->[ $self->stash('line') - 1 ];
1.6 andrew 95:
96: if ( $format eq 'json' ) {
1.7 andrew 97: $self->render_json($entry);
1.6 andrew 98: }
99: else {
1.7 andrew 100: $self->render( entry => $entry, layout => 'todotxt' );
1.6 andrew 101: }
1.5 andrew 102: } => 'entry';
1.1 andrew 103:
1.12 ! andrew 104: get '/l/:file/t' => sub {
! 105: my $self = shift;
! 106:
! 107: my $format = $self->stash('format') || 'html';
! 108: my $tags = $self->helper('todo')->known_tags;
! 109:
! 110: if ( $format eq 'json' ) {
! 111: $self->render_json($tags);
! 112: }
! 113: else {
! 114: $self->render( tags => $tags, layout => 'todotxt' );
! 115: }
! 116: } => 'tags';
! 117:
1.11 andrew 118: app->start if !caller();
1.5 andrew 119:
1.12 ! andrew 120: 1;
1.1 andrew 121: __DATA__
122:
1.5 andrew 123: @@ list.txt.ep
1.6 andrew 124: % foreach my $entry (@{ $list }) {
125: %== include 'entry', entry => $entry;
1.5 andrew 126: % }
127:
128: @@ entry.txt.ep
1.6 andrew 129: <%= $entry->{text} %>
1.5 andrew 130:
1.12 ! andrew 131: @@ tags.txt.ep
! 132: % foreach my $tag (keys%{ $tags }) {
! 133: <%= $tag %>, <%= $tags->{$tag} %>
! 134: % }
! 135:
1.5 andrew 136: @@ layouts/todotxt.txt.ep
137: %= content
138:
1.1 andrew 139: @@ index.html.ep
1.5 andrew 140: % foreach my $file (@{ $files }) {
141: <%== $file %> <br />
142: % }
143:
144: @@ list.html.ep
145: <h1><%= $file %></h1>
146: <ol>
1.6 andrew 147: % foreach my $entry (@{ $list }) {
1.5 andrew 148: <li>
1.6 andrew 149: %= include 'entry', entry => $entry;
1.5 andrew 150: </li>
151: % }
152: </ol>
1.1 andrew 153:
1.5 andrew 154: @@ entry.html.ep
1.6 andrew 155: <%= $entry->{text} %>
1.5 andrew 156:
1.12 ! andrew 157: @@ tags.html.ep
! 158: % foreach my $tag (keys%{ $tags }) {
! 159: <%= $tag %> == <%= $tags->{$tag} %><br />
! 160: % }
! 161:
! 162:
1.5 andrew 163: @@ layouts/todotxt.html.ep
1.1 andrew 164: <!doctype html><html>
1.9 andrew 165: <head>
166: <title>Funky!</title>
167: <link rel="stylesheet" href="<%= url_for 'todotxt', format => 'css' %>">
168: </head>
1.1 andrew 169: <body><%== content %></body>
170: </html>
1.4 andrew 171:
1.9 andrew 172: @@ todotxt.css.ep
173: body {
174: background: LightGoldenRodYellow;
175: color: DarkSlateBlue;
176: }
177:
178: .inplaceeditor-saving {
179: background: url(images/saving.gif) bottom right no-repeat;
180: }
181:
182:
1.4 andrew 183: __END__
184:
185: =head1 NAME
186:
187: dudelicious - A Mojolicous interface to your todotxt files
188:
189: =head1 VERSION
190:
191: Since the $VERSION can't be automatically included,
192: here is the RCS Id instead, you'll have to look up $VERSION.
193:
1.12 ! andrew 194: $Id: dudelicious.pl,v 1.11 2010/05/01 20:26:17 andrew Exp $
1.4 andrew 195:
196: =head1 SYNOPSIS
197:
198: dudelicious daemon
199:
200: Then browse to http://localhost:3000/
201:
202: =head1 DESCRIPTION
203:
204: A Mojolicous web app for access to your todotxt files
205:
206: The modules are there to give more access to my todo.txt file from more
207: places. My goal is a web API for a web interface and then a WebOS version for
208: my Palm Pre.
209:
210: For more information see L<http://todotxt.com>
211:
212: =head1 USAGE
213:
214: See todo.pl -h
215:
216: =head1 OPTIONS
217:
218: See todo.pl -h
219:
220: =head1 REQUIRED ARGUMENTS
221:
222: See todo.pl -h
223:
224: =head1 CONFIGURATION AND ENVIRONMENT
225:
226: =head1 DIAGNOSTICS
227:
228: =head1 DEPENDENCIES
229:
230: Perl Modules:
231:
232: =over
233:
234: =item Text::Todo
235:
236: =item Mojolicous::Lite
237:
238: =item version
239:
240: =back
241:
242:
243: =head1 BUGS AND LIMITATIONS
244:
245: No bugs have been reported.
246:
247: =head1 AUTHOR
248:
249: Andrew Fresh C<< <andrew@cpan.org> >>
250:
251:
252: =head1 LICENSE AND COPYRIGHT
253:
254: Copyright (c) 2010, Andrew Fresh C<< <andrew@cpan.org> >>. All rights reserved.
255:
256: This module is free software; you can redistribute it and/or
257: modify it under the same terms as Perl itself. See L<perlartistic>.
258:
259:
260: =head1 DISCLAIMER OF WARRANTY
261:
262: BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
263: FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
264: OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
265: PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
266: EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
267: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
268: ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
269: YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
270: NECESSARY SERVICING, REPAIR, OR CORRECTION.
271:
272: IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
273: WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
274: REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
275: LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
276: OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
277: THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
278: RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
279: FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
280: SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
281: SUCH DAMAGES.
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>