bzr branch
http://bzr.ed.am/todo
1
by edam
init |
1 |
#!/usr/bin/perl |
2 |
||
6
by edam
rewrite file parsing to cache the last line and only display it when we know the current line is not a section heading "underline" line. |
3 |
use feature "state"; |
4 |
||
1
by edam
init |
5 |
use strict; |
6 |
use warnings; |
|
7 |
use Getopt::Long; |
|
8 |
use File::Basename; |
|
9 |
||
10 |
# get app name |
|
11 |
my $app_name = basename( $0 ); |
|
12 |
||
13 |
# option defaults |
|
14 |
my $todo_dir = "~/.todo"; |
|
15 |
my $display_all = 0; |
|
2
by edam
added default todo file content and changed main todo section name to "TODO" |
16 |
my $display_section = "TODO"; |
1
by edam
init |
17 |
my $display_headers = 0; |
18 |
my $mode_edit = 0; |
|
19 |
my $mode_help = 0; |
|
20 |
my $mode_version = 0; |
|
21 |
||
22 |
# parse command line opts |
|
23 |
Getopt::Long::Configure( 'gnu_getopt' ); |
|
24 |
if( !GetOptions( |
|
25 |
'a|all' => \$display_all, |
|
26 |
'e|edit' => \$mode_edit, |
|
27 |
'h|headers' => \$display_headers, |
|
7
by edam
made section selection case insensitive and added short option (-s) for it |
28 |
's|section=s' => \$display_section, |
1
by edam
init |
29 |
'help' => \$mode_help, |
30 |
'version' => \$mode_version, |
|
31 |
) ) { |
|
32 |
print "Try `$app_name --help' for more information.\n"; |
|
33 |
exit( 1 ); |
|
34 |
} |
|
35 |
||
36 |
# help mode |
|
37 |
if( $mode_help ) { |
|
38 |
print "todo - display your todo file\n\n". |
|
4
by edam
fixed spaces |
39 |
"Usage: $app_name [OPTIONS]\n\n". |
40 |
"Options:\n". |
|
41 |
" -a, --all display all sections\n". |
|
42 |
" -e, --edit edit your todo file\n". |
|
43 |
" -h, --headers show setion headers\n". |
|
7
by edam
made section selection case insensitive and added short option (-s) for it |
44 |
" -s, --section=SECTION display this named section\n". |
4
by edam
fixed spaces |
45 |
" --help display this help and exit\n". |
46 |
" --version output version information and exit\n"; |
|
1
by edam
init |
47 |
exit( 0 ); |
48 |
} |
|
49 |
||
50 |
# version mode |
|
51 |
if( $mode_version ) { |
|
3
by edam
fixed version info and error about failing to start the editor |
52 |
print "todo 1.0\n". |
4
by edam
fixed spaces |
53 |
"Copyright (C) 2011 Tim Marston.\n". |
54 |
"http://ed.am/software/todo\n"; |
|
1
by edam
init |
55 |
exit( 0 ); |
56 |
} |
|
57 |
||
58 |
#_______________________________________________________________________________ |
|
59 |
||
60 |
||
61 |
# check we have bazaar installed |
|
62 |
my $output = `which bzr`; |
|
63 |
chomp $output; |
|
64 |
$output eq "" and die "Bazaar is not installed"; |
|
65 |
||
66 |
# glob todo directory |
|
67 |
$todo_dir = glob( $todo_dir ); |
|
68 |
( -f $todo_dir ) and die "$todo_dir exists and is a file"; |
|
69 |
||
70 |
# edit mode |
|
71 |
if( $mode_edit ) |
|
72 |
{ |
|
73 |
# create the todo directory, as necessary |
|
4
by edam
fixed spaces |
74 |
if( ! -d $todo_dir ) { |
75 |
mkdir $todo_dir or die "couldn't create todo directory"; |
|
76 |
`bzr init --no-aliases -q "$todo_dir"`; |
|
77 |
$? == 0 or die "couldn't init bzr repo"; |
|
78 |
} |
|
79 |
||
80 |
# create a default todo file, as necessary |
|
81 |
if( ! -f "$todo_dir/todo" ) { |
|
82 |
open FILE, ">$todo_dir/todo" or die "couldn't create default todo file"; |
|
83 |
my $content = <<"EOT"; |
|
2
by edam
added default todo file content and changed main todo section name to "TODO" |
84 |
<!-- This file uses Markdown syntax. For more info about Markdown |
85 |
syntax, see http://daringfireball.net/projects/markdown/syntax. |
|
86 |
||
87 |
There should be a main H1 header called "TODO" for the main todo |
|
88 |
list section (one has been added for you below). You can also add |
|
89 |
as many more sections as you like for other lists. And feel free |
|
90 |
to delete this comment! --> |
|
91 |
||
92 |
TODO |
|
93 |
==== |
|
94 |
||
95 |
* make a list of things to do |
|
96 |
||
97 |
EOT |
|
98 |
print FILE $content or die "couldn't write default todo file"; |
|
4
by edam
fixed spaces |
99 |
close FILE; |
100 |
`bzr add --no-aliases -q "$todo_dir/todo"`; |
|
101 |
$? == 0 or die "couldn't add todo file to bzr repo"; |
|
102 |
} |
|
1
by edam
init |
103 |
|
104 |
# determine editor from environment, default to "emacs -nw" |
|
105 |
my $editor = $ENV{ 'EDITOR' }; |
|
106 |
defined $editor or $editor = 'emacs -nw'; |
|
107 |
my @exec_array = split( / +/, $editor ); |
|
108 |
push( @exec_array, "$todo_dir/todo" ); |
|
109 |
||
4
by edam
fixed spaces |
110 |
# detect emacs and try to use markdown-mode |
111 |
$exec_array[ 0 ] eq "emacs" and |
|
112 |
push( @exec_array, '--funcall=markdown-mode' ); |
|
1
by edam
init |
113 |
|
114 |
# edit todo file |
|
115 |
system( @exec_array ); |
|
4
by edam
fixed spaces |
116 |
$? == 0 or |
117 |
die "can't start editor, check EDITOR envionment variable"; |
|
118 |
||
119 |
# check for changes and commit it |
|
120 |
$output = `bzr status --no-aliases "$todo_dir/todo"`; |
|
121 |
$? == 0 or die "couldn't check bzr rerpo status"; |
|
122 |
chomp $output; |
|
123 |
if( $output ne "" ) { |
|
124 |
`bzr commit --no-aliases -q -m - "$todo_dir/todo"`; |
|
125 |
$? == 0 or die "couldn't commit to bzr repo"; |
|
126 |
} |
|
127 |
||
128 |
# after editing, exit |
|
129 |
exit |
|
1
by edam
init |
130 |
} |
131 |
||
6
by edam
rewrite file parsing to cache the last line and only display it when we know the current line is not a section heading "underline" line. |
132 |
# function to display a line |
133 |
sub display_line |
|
134 |
{ |
|
135 |
my ( $line, $section ) = @_; |
|
136 |
state $old_section = ''; |
|
137 |
||
138 |
# detect section change |
|
139 |
if( $section ne $old_section ) { |
|
140 |
$old_section = $section; |
|
141 |
||
142 |
# display section heading |
|
143 |
if( $display_headers || $display_all ) { |
|
144 |
print "$section\n". |
|
145 |
( "=" x length( $section ) )."\n"; |
|
146 |
} |
|
147 |
} |
|
148 |
||
149 |
# replace tabs with 4 spaces |
|
150 |
$line =~ s/\t/ /g; |
|
151 |
||
152 |
# display the line |
|
153 |
print $line; |
|
154 |
} |
|
155 |
||
156 |
||
1
by edam
init |
157 |
# scan through file |
6
by edam
rewrite file parsing to cache the last line and only display it when we know the current line is not a section heading "underline" line. |
158 |
my $candidate_section = ''; |
1
by edam
init |
159 |
my $section = ''; |
6
by edam
rewrite file parsing to cache the last line and only display it when we know the current line is not a section heading "underline" line. |
160 |
my $last_line = ''; |
1
by edam
init |
161 |
open FILE, "<$todo_dir/todo" or die "can't open todo file"; |
6
by edam
rewrite file parsing to cache the last line and only display it when we know the current line is not a section heading "underline" line. |
162 |
while( <FILE> ) |
163 |
{ |
|
1
by edam
init |
164 |
# detect the line after section headings, and thus sections |
6
by edam
rewrite file parsing to cache the last line and only display it when we know the current line is not a section heading "underline" line. |
165 |
if( /^[-=]{2,}/ && $candidate_section ne '' ) { |
166 |
$section = $candidate_section; |
|
167 |
$candidate_section = ''; |
|
168 |
$last_line = ''; |
|
169 |
next; |
|
1
by edam
init |
170 |
} |
6
by edam
rewrite file parsing to cache the last line and only display it when we know the current line is not a section heading "underline" line. |
171 |
|
1
by edam
init |
172 |
# detect section headings |
6
by edam
rewrite file parsing to cache the last line and only display it when we know the current line is not a section heading "underline" line. |
173 |
if( /^[-_\.A-Za-z0-9 ]+$/ ) { |
174 |
$candidate_section = $_; |
|
175 |
chomp $candidate_section; |
|
176 |
} |
|
1
by edam
init |
177 |
else { |
6
by edam
rewrite file parsing to cache the last line and only display it when we know the current line is not a section heading "underline" line. |
178 |
$candidate_section = ''; |
179 |
} |
|
180 |
||
181 |
# display last line |
|
182 |
display_line( $last_line, $section ) if( $last_line ne '' ); |
|
183 |
||
184 |
# display line |
|
7
by edam
made section selection case insensitive and added short option (-s) for it |
185 |
if( ( lc( $section ) eq lc( $display_section ) ) || |
6
by edam
rewrite file parsing to cache the last line and only display it when we know the current line is not a section heading "underline" line. |
186 |
( $section && $display_all ) ) |
187 |
{ |
|
188 |
$last_line = $_; |
|
1
by edam
init |
189 |
} |
6
by edam
rewrite file parsing to cache the last line and only display it when we know the current line is not a section heading "underline" line. |
190 |
else { |
191 |
$last_line = ''; |
|
192 |
} |
|
1
by edam
init |
193 |
} |
6
by edam
rewrite file parsing to cache the last line and only display it when we know the current line is not a section heading "underline" line. |
194 |
display_line( $last_line, $section ) if( $last_line ne '' ); |