/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: 2011-09-30 10:20:26 UTC
  • Revision ID: edam@waxworlds.org-20110930102026-8kbh15ufm67eit0k
init

Show diffs side-by-side

added added

removed removed

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