/todo

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