/todo

To get this branch, use:
bzr branch http://bzr.ed.am/todo

« back to all changes in this revision

Viewing changes to todo

  • Committer: edam
  • Date: 2012-01-04 12:46:10 UTC
  • Revision ID: edam@waxworlds.org-20120104124610-nrrs6mv1btg390ni
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.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/perl
2
2
 
 
3
use feature "state";
 
4
 
3
5
use strict;
4
6
use warnings;
5
7
use Getopt::Long;
11
13
# option defaults
12
14
my $todo_dir = "~/.todo";
13
15
my $display_all = 0;
14
 
my $display_section = "IMMEDIATE";
 
16
my $display_section = "TODO";
15
17
my $display_headers = 0;
16
18
my $mode_edit = 0;
17
19
my $mode_help = 0;
34
36
# help mode
35
37
if( $mode_help ) {
36
38
    print "todo - display your todo file\n\n".
37
 
        "Usage: $app_name [OPTIONS]\n\n".
38
 
        "Options:\n".
39
 
        "  -a, --all              display all sections\n".
40
 
        "  -e, --edit             edit your todo file\n".
41
 
        "  -h, --headers          show setion headers\n".
42
 
        "  -s, --section=SECTION  display this named section\n".
43
 
        "      --help     display this help and exit\n".
44
 
        "      --version  output version information and exit\n";
 
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".
 
44
    "      --section=SECTION  display this named section\n".
 
45
    "      --help     display this help and exit\n".
 
46
    "      --version  output version information and exit\n";
45
47
    exit( 0 );
46
48
}
47
49
 
48
50
# version mode
49
51
if( $mode_version ) {
50
 
    print "todo 1.0\n" .
51
 
        "Copyright (C) 2011 Tim Marston.\n";
 
52
    print "todo 1.0\n".
 
53
        "Copyright (C) 2011 Tim Marston.\n".
 
54
        "http://ed.am/software/todo\n";
52
55
    exit( 0 );
53
56
}
54
57
 
68
71
if( $mode_edit )
69
72
{
70
73
    # create the todo directory, as necessary
71
 
        if( ! -d $todo_dir ) {
72
 
                mkdir $todo_dir or die "couldn't create todo directory";
73
 
                `bzr init --no-aliases -q "$todo_dir"`;
74
 
                $? == 0 or die "couldn't init bzr repo";
75
 
                `> "$todo_dir/todo"`;
76
 
                $? == 0 or die "couldn't create initial todo file";
77
 
                `bzr add --no-aliases -q "$todo_dir/todo"`;
78
 
                $? == 0 or die "couldn't add todo file to bzr repo";
79
 
        }
 
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";
 
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";
 
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
    }
80
103
 
81
104
    # determine editor from environment, default to "emacs -nw"
82
105
    my $editor = $ENV{ 'EDITOR' };
84
107
    my @exec_array = split( / +/, $editor );
85
108
    push( @exec_array, "$todo_dir/todo" );
86
109
 
87
 
        # detect emacs and try to use markdown-mode
88
 
        $exec_array[ 0 ] eq "emacs" and push( @exec_array, '--funcall=markdown-mode' );
 
110
    # detect emacs and try to use markdown-mode
 
111
    $exec_array[ 0 ] eq "emacs" and
 
112
        push( @exec_array, '--funcall=markdown-mode' );
89
113
 
90
114
    # edit todo file
91
115
    system( @exec_array );
92
 
        $? == 0 or die "unable to exec editor";
93
 
 
94
 
        # check for changes and commit it
95
 
        $output = `bzr status --no-aliases "$todo_dir/todo"`;
96
 
        $? == 0 or die "couldn't check bzr rerpo status";
97
 
        chomp $output;
98
 
        if( $output ne "" ) {
99
 
                `bzr commit --no-aliases -q -m - "$todo_dir/todo"`;
100
 
                $? == 0 or die "couldn't commit to bzr repo";
 
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
 
130
}
 
131
 
 
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
                }
101
147
        }
 
148
 
 
149
        # replace tabs with 4 spaces
 
150
        $line =~ s/\t/    /g;
102
151
        
103
 
        # exit
104
 
        exit
 
152
        # display the line
 
153
        print $line;
105
154
}
106
155
 
 
156
 
107
157
# scan through file
108
 
my $next_section = '';
 
158
my $candidate_section = '';
109
159
my $section = '';
110
 
my $old_section = '';
 
160
my $last_line = '';
111
161
open FILE, "<$todo_dir/todo" or die "can't open todo file";
112
 
while( <FILE> ) {
113
 
    my $display = 0;
114
 
 
 
162
while( <FILE> )
 
163
{
115
164
    # detect the line after section headings, and thus sections
116
 
    if( /^[-=]{2,}/ && $next_section ne '' ) {
117
 
                $section = $next_section;
118
 
                $next_section = '';
 
165
    if( /^[-=]{2,}/ && $candidate_section ne '' ) {
 
166
        $section = $candidate_section;
 
167
        $candidate_section = '';
 
168
                $last_line = '';
 
169
                next;
119
170
    }
 
171
 
120
172
    # detect section headings
121
 
    elsif( /^[A-Z]+$/ ) {
122
 
                $next_section = $_;
123
 
                chomp( $next_section );
124
 
    }
125
 
    # we have neither a section heading nor the line after
 
173
    if( /^[-_\.A-Za-z0-9 ]+$/ ) {
 
174
        $candidate_section = $_;
 
175
                chomp $candidate_section;
 
176
        }
126
177
    else {
127
 
                $next_section = '';
128
 
 
129
 
                # display line
130
 
                if( $section eq $display_section ||
131
 
                        $display_all )
132
 
                {
133
 
                        # detect section change
134
 
                        if( $section ne $old_section ) {
135
 
                                $old_section = $section;
136
 
                                
137
 
                                # display section heading
138
 
                                if( $display_headers ||
139
 
                                        $display_all )
140
 
                                {
141
 
                                        my $heading = 'TODO';
142
 
                                        $heading .= ' ('.lc( $section ).')' if $section ne "IMMEDIATE";
143
 
                                        print "$heading\n".
144
 
                                                ( "=" x length( $heading ) )."\n";
145
 
                                }
146
 
                        }
147
 
 
148
 
                        # replace tabs with 4 spaces
149
 
                        s/\t/    /g;
150
 
 
151
 
                        # display the line
152
 
                        print;
153
 
                }
 
178
        $candidate_section = '';
 
179
        }
 
180
 
 
181
        # display last line
 
182
        display_line( $last_line, $section ) if( $last_line ne '' );
 
183
 
 
184
    # display line
 
185
        if( ( $section eq $display_section ) ||
 
186
                ( $section && $display_all ) )
 
187
        {
 
188
                $last_line = $_;
154
189
    }
 
190
        else {
 
191
                $last_line = '';
 
192
        }
155
193
}
 
194
display_line( $last_line, $section ) if( $last_line ne '' );