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