/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-08-01 19:54:49 UTC
  • Revision ID: tim@ed.am-20120801195449-fcyrejq9aazxa5l5
detect extra arguments and extend --help message

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