1
#!/usr/bin/env perl
2
3
# lite2do, a lightweight text-based todo manager
4
# Copyright (C) 2008, 2009 Jaromir Hradilek
5
6
# This program is free software;  you can redistribute it  and/or modify it
7
# under the  terms of the  GNU General Public License  as published  by the
8
# Free Software Foundation; version 3 of the License.
9
# 
10
# This  program is  distributed  in the  hope that  it will be useful,  but
11
# WITHOUT ANY WARRANTY;  without even the implied warranty of  MERCHANTABI-
12
# LITY  or  FITNESS FOR A PARTICULAR PURPOSE.  See  the  GNU General Public
13
# License for more details.
14
# 
15
# You should have received a copy of the  GNU General Public License  along
16
# with this program. If not, see <http://www.gnu.org/licenses/>.
17
18
use strict;
19
use warnings;
20
use locale;
21
use File::Copy;
22
use File::Basename;
23
use File::Spec::Functions;
24
use Term::ANSIColor;
25
use Getopt::Long;
26
27
# General script information:
28
use constant NAME    => basename($0, '.pl');             # Script name.
29
use constant VERSION => '1.1.1';                         # Script version.
30
31
# General script settings:
32
our $HOMEDIR   = $ENV{HOME} || $ENV{USERPROFILE} || '.'; # Home directory.
33
our $savefile  = catfile($HOMEDIR, '.lite2do');          # Save file name.
34
our $backext   = '.bak';                                 # Backup suffix.
35
our $verbose   = 1;                                      # Verbosity level.
36
our $coloured  = 0;                                      # Set up colours.
37
38
# Colours settings:
39
our $done      = 'green';                                # Finished tasks.
40
our $undone    = '';                                     # Undone tasks.
41
42
# Allowed colours:
43
my  %valid     = map { $_, 1 } qw( black green yellow magenta red blue
44
                                   cyan  white );
45
46
# Command line options:
47
my ($command, $response);
48
49
# Signal handlers:
50
$SIG{__WARN__} = sub {
51
  print STDERR NAME . ": " . (shift);
52
};
53
54
# Display given message and immediately terminate the script:
55
sub exit_with_error {
56
  my $message       = shift || 'An unspecified error has occurred.';
57
  my $return_value  = shift || 1;
58
59
  print STDERR NAME . ": $message\n";
60
  exit $return_value;
61
}
62
63
# Display script help:
64
sub display_help {
65
  my $command = shift || '';
66
  my $NAME    = NAME;
67
68
  # Parse command and display appropriate usage information:
69
  if ($command =~ /^(list|ls)$/) {
70
    print "Displays items in the task list.\n";
71
    print "Usage: $NAME list [\@GROUP|%ID] [TEXT...]\n";
72
  }
73
  elsif ($command =~ /^add$/) {
74
    print "Adds new item to the task list.\n";
75
    print "Usage: $NAME add [\@GROUP] TEXT...\n";
76
  }
77
  elsif ($command =~ /^(change|mv)$/) {
78
    print "Changes selected item in the task list.\n";
79
    print "Usage: $NAME change ID \@GROUP|TEXT...\n";
80
  }
81
  elsif ($command =~ /^(finish|fn)$/) {
82
    print "Finishes selected item in the task list.\n";
83
    print "Usage: $NAME finish ID\n";
84
  }
85
  elsif ($command =~ /^(revive|re)$/) {
86
    print "Revives selected item in the task list.\n";
87
    print "Usage: $NAME revive ID\n";
88
  }
89
  elsif ($command =~ /^(remove|rm)$/) {
90
    print "Removes selected item from the task list.\n";
91
    print "Usage: $NAME remove ID\n";
92
  }
93
  elsif ($command =~ /^(undo|ud)$/) {
94
    print "Reverts last action.\n";
95
    print "Usage: $NAME undo\n";
96
  }
97
  elsif ($command =~ /^(groups|gr)$/) {
98
    print "Displays groups in the task list.\n";
99
    print "Usage: $NAME groups\n";
100
  }
101
  elsif ($command =~ /^version$/) {
102
    print "Displays version information.\n";
103
    print "Usage: $NAME version\n";
104
  }
105
  elsif ($command =~ /^help$/) {
106
    print "Displays usage information.\n";
107
    print "Usage: $NAME help [COMMAND]\n";
108
  }
109
  else {
110
    print << "END_HELP";
111
Usage: $NAME [OPTION...] COMMAND [ARGUMENT...]
112
113
Commands:
114
  list [\@GROUP|%ID] [TEXT] display items in the task list
115
  add  [\@GROUP] TEXT       add new item to the task list
116
  change ID \@GROUP|TEXT    change item in the task list
117
  finish ID                finish item in the task list
118
  revive ID                revive item in the task list
119
  remove ID                remove item from the task list
120
  undo                     revert last action
121
  groups                   display groups in the task list
122
  help [COMMAND]           display usage information
123
  version                  display version information
124
125
Options:
126
  -c, --color, --colour    use coloured output; turned off by default
127
  -s, --savefile FILE      use selected file instead of default ~/.lite2do
128
  -f, --finished COLOUR    use selected colour for finished tasks; suppor-
129
                           ted options are: black, green, yellow, magenta,
130
                           red, blue, cyan, and white
131
  -u, --unfinished COLOUR  use selected colour for unfinished tasks
132
  -q, --quiet              avoid displaying unnecessary messages
133
  -h, --help               display this help and exit
134
  -v, --version            display version information and exit
135
END_HELP
136
  }
137
138
  # Return success:
139
  return 1;
140
}
141
142
# Display script version:
143
sub display_version {
144
  my ($NAME, $VERSION) = (NAME, VERSION);
145
146
  # Print message to the STDOUT:
147
  print << "END_VERSION";
148
$NAME $VERSION
149
150
Copyright (C) 2008, 2009 Jaromir Hradilek
151
This program is free software; see the source for copying conditions. It is
152
distributed in the hope  that it will be useful,  but WITHOUT ANY WARRANTY;
153
without even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PAR-
154
TICULAR PURPOSE.
155
END_VERSION
156
157
  # Return success:
158
  return 1;
159
}
160
161
# Load selected data from the save file:
162
sub load_selection {
163
  my ($selected, $rest, $id, $group, $task) = @_;
164
165
  # Escape reserved characters:
166
  $group =~ s/([\\\^\.\$\|\(\)\[\]\*\+\?\{\}])/\\$1/g if $group;
167
  $task  =~ s/([\\\^\.\$\|\(\)\[\]\*\+\?\{\}])/\\$1/g if $task;
168
169
  # Remove colons if any:
170
  $group =~ s/://g if $group;
171
172
  # Use default pattern when none is provided:
173
  $id    ||= '\d+';
174
  $group ||= '[^:]*';
175
  $task  ||= '';
176
177
  # Open the save file for reading:
178
  if (open(SAVEFILE, "$savefile")) {
179
    # Process each line:
180
    while (my $line = <SAVEFILE>) {
181
      # Check whether the line matches given pattern:
182
      if ($line =~ /^$group:[^:]*:[1-5]:[ft]:.*$task.*:$id$/i) {
183
        # Add the line to selected tasks:
184
        push(@$selected, $line);
185
      }
186
      else {
187
        # Add the line to unselected tasks:
188
        push(@$rest, $line);
189
      }
190
    }
191
192
    # Close the save file:
193
    close(SAVEFILE);
194
  }
195
196
  # Return success:
197
  return 1;
198
}
199
200
# Save given data to the save file:
201
sub save_data {
202
  my $data = shift || die 'Missing argument';
203
204
  # Backup the save file:
205
  copy($savefile, "$savefile$backext") if (-r $savefile);
206
207
  # Open the save file for writing:
208
  if (open(SAVEFILE, ">$savefile")) {
209
    # Write data to the save file:
210
    foreach my $line (@$data) {
211
      print SAVEFILE $line;
212
    }
213
214
    # Close the save file:
215
    close(SAVEFILE);
216
  }
217
  else {
218
    # Report failure and exit:
219
    exit_with_error("Unable to write to `$savefile'.", 13);
220
  }
221
222
  # Return success:
223
  return 1;
224
}
225
226
# Add given data to the end of the save file:
227
sub add_data {
228
  my $data = shift || die 'Missing argument';
229
230
  # Backup the save file:
231
  copy($savefile, "$savefile$backext") if (-r $savefile);
232
233
  # Open the save file for appending:
234
  if (open(SAVEFILE, ">>$savefile")) {
235
    # Write data to the save file:
236
    foreach my $line (@$data) {
237
      print SAVEFILE $line;
238
    }
239
240
    # Close the save file:
241
    close(SAVEFILE);
242
  }
243
  else {
244
    # Report failure and exit:
245
    exit_with_error("Unable to write to `$savefile'.", 13);
246
  }
247
248
  # Return success:
249
  return 1;
250
}
251
252
# Get hash of all groups:
253
sub get_groups {
254
  my %groups = ();
255
256
  # Open the save file for reading:
257
  if (open(SAVEFILE, "$savefile")) {
258
    # Build the list of used groups:
259
    while (my $line = <SAVEFILE>) {
260
      # Parse the task record:
261
      if ($line =~ /^([^:]*):/) {
262
        my $group = lc($1);
263
264
        # Check whether the group is already added:
265
        if ($groups{$group}) {
266
          # Increment the counter:
267
          $groups{$group} += 1;
268
        }
269
        else {
270
          # Initialize the counter:
271
          $groups{$group}  = 1;
272
        }
273
      }
274
    }
275
276
    # Close the save file:
277
    close(SAVEFILE);
278
  }
279
280
  # Return the result:
281
  return %groups;
282
}
283
284
# Choose first available ID:
285
sub choose_id {
286
  my @used   = ();
287
  my $chosen = 1;
288
289
  # Open the save file for reading:
290
  if (open(SAVEFILE, "$savefile")) {
291
    # Build the list of used IDs:
292
    while (my $line = <SAVEFILE>) {
293
      push(@used, int($1)) if ($line =~ /:(\d+)$/);
294
    }
295
296
    # Close the save file:
297
    close(SAVEFILE);
298
299
    # Find first unused ID:
300
    foreach my $id (sort {$a <=> $b} @used) {
301
      $chosen++ if ($chosen == $id);
302
    }
303
  }
304
305
  # Return the result:
306
  return $chosen;
307
}
308
309
# Fix the group name:
310
sub fix_group {
311
  my $group = shift || die 'Missing argument';
312
313
  # Check whether it contains forbidden characters:
314
  if ($group =~ /:/) {
315
    # Display warning:
316
    print STDERR "Colon is not allowed in the group name. Removing.\n";
317
318
    # Remove forbidden characters:
319
    $group =~ s/://g;
320
  }
321
322
  # Check the group name length:
323
  if (length($group) > 10) {
324
    # Display warning:
325
    print STDERR "Group name too long. Stripping.\n";
326
327
    # Strip it to the maximal allowed length:
328
    $group = substr($group, 0, 10);
329
  }
330
331
  # Make sure the result is not empty:
332
  unless ($group) {
333
    # Display warning:
334
    print STDERR "Group name is empty. Using the default group instead.\n";
335
336
    # Use default group instead:
337
    $group = 'general';
338
  }
339
340
  # Return the result:
341
  return $group;
342
}
343
344
# List items in the task list:
345
sub list_tasks {
346
  my ($group, $task, $id) = @_;
347
  my (@selected, $state);
348
349
  # Load matching tasks:
350
  load_selection(\@selected, undef, $id, $group, $task);
351
352
  # Check whether the list is not empty:
353
  if (@selected) {
354
    # Process each task:
355
    foreach my $line (sort @selected) {
356
      # Parse the task record:
357
      $line   =~ /^([^:]*):[^:]*:[1-5]:([ft]):(.*):(\d+)$/;
358
      $state  = ($2 eq 'f') ? '-' : 'f';
359
      
360
      # Check whether to use coloured output:
361
      if ($coloured) {
362
        # Decide which colour to use:
363
        my $colour = ($2 eq 'f') ? $undone : $done;
364
365
        # Print the task entry:
366
        print colored (sprintf("%2d. ", $4), "bold"),
367
              colored ("\@$1 ",              "bold $colour"),
368
              colored ("[$state]",           "bold"),
369
              colored (": $3",               "$colour"),
370
              "\n";
371
      }
372
      else {
373
        # Print the task entry:
374
        printf "%2d. @%s [%s]: %s\n", $4, $1, $state, $3;
375
      }
376
    }
377
  }
378
  else {
379
    # Report empty list:
380
    print "No matching task found.\n" if $verbose;
381
  }
382
383
  # Return success:
384
  return 1;
385
}
386
387
# List groups in the task list:
388
sub list_groups {
389
  # Get list of all groups:
390
  my %groups = get_groups();
391
392
  # Make sure the task list is not empty:
393
  if (scalar(keys %groups)) {
394
    # Display the list of groups:
395
    print join(', ', map { "$_ (" . $groups{$_} . ")" }
396
                     sort keys(%groups)), "\n";
397
  }
398
  else {
399
    # Report empty list:
400
    print "No matching task found.\n" if $verbose;
401
  }
402
403
  # Return success:
404
  return 1;
405
}
406
407
# Add new item to the task list:
408
sub add_task {
409
  my $task  = shift || die 'Missing argument';
410
  my $group = shift || 'general';
411
  my $id    = choose_id();
412
413
  # Create the task record:
414
  my @data  = (fix_group($group) . ":anytime:3:f:$task:$id\n");
415
416
  # Add data to the end of the save file:
417
  add_data(\@data);
418
419
  # Report success:
420
  print "Task has been successfully added with id $id.\n" if $verbose;
421
422
  # Return success:
423
  return 1;
424
}
425
426
# Change selected item in the task list:
427
sub change_task {
428
  my $id    = shift || die 'Missing argument';
429
  my $text  = shift || die 'Missing argument';
430
  my $group = shift || 0;
431
  my (@selected, @rest);
432
433
  # Load tasks:
434
  load_selection(\@selected, \@rest, $id);
435
436
  # Check whether the list is not empty:
437
  if (@selected) {
438
    # Parse the task record:
439
    pop(@selected) =~ /^([^:]*):([^:]*):([1-5]):([ft]):(.*):\d+$/;
440
441
    # Decide which part to edit:
442
    unless ($group) {
443
      # Update the task record:
444
      push(@rest, "$1:$2:$3:$4:$text:$id\n");
445
    }
446
    else {
447
      # Update the group record:
448
      push(@rest, fix_group($text) . ":$2:$3:$4:$5:$id\n");
449
    }
450
451
    # Store data to the save file:
452
    save_data(\@rest);
453
454
    # Report success:
455
    print "Task has been successfully changed.\n" if $verbose;
456
  }
457
  else {
458
    # Report empty list:
459
    print "No matching task found.\n" if $verbose;
460
  }
461
462
  # Return success:
463
  return 1;
464
}
465
466
# Mark selected item in the task list as finished:
467
sub finish_task {
468
  my $id = shift || die 'Missing argument';
469
  my (@selected, @rest);
470
471
  # Load tasks:
472
  load_selection(\@selected, \@rest, $id);
473
474
  # Check whether the list is not empty:
475
  if (@selected) {
476
    # Parse the task record:
477
    pop(@selected) =~ /^([^:]*):([^:]*):([1-5]):[ft]:(.*):\d+$/;
478
479
    # Update the task record:
480
    push(@rest, "$1:$2:$3:t:$4:$id\n");
481
482
    # Store data to the save file:
483
    save_data(\@rest);
484
485
    # Report success:
486
    print "Task has been finished.\n" if $verbose;
487
  }
488
  else {
489
    # Report empty list:
490
    print "No matching task found.\n" if $verbose;
491
  }
492
493
  # Return success:
494
  return 1;
495
}
496
497
# Mark selected item in the task list as unfinished:
498
sub revive_task {
499
  my $id = shift || die 'Missing argument';
500
  my (@selected, @rest);
501
502
  # Load tasks:
503
  load_selection(\@selected, \@rest, $id);
504
505
  # Check whether the list is not empty:
506
  if (@selected) {
507
    # Parse the task record:
508
    pop(@selected) =~ /^([^:]*):([^:]*):([1-5]):[ft]:(.*):\d+$/;
509
510
    # Update the task record:
511
    push(@rest, "$1:$2:$3:f:$4:$id\n");
512
513
    # Store data to the task list:
514
    save_data(\@rest);
515
516
    # Report success:
517
    print "Task has been revived.\n" if $verbose;
518
  }
519
  else {
520
    # Report empty list:
521
    print "No matching task found.\n" if $verbose;
522
  }
523
524
  # Return success:
525
  return 1;
526
}
527
528
# Remove selected item from the task list:
529
sub remove_task {
530
  my $id = shift || die 'Missing argument';
531
  my (@selected, @rest);
532
533
  # Load tasks:
534
  load_selection(\@selected, \@rest, $id);
535
536
  # Check whether the list is not empty:
537
  if (@selected) {
538
    # Store data to the save file:
539
    save_data(\@rest);
540
541
    # Report success:
542
    print "Task has been successfully removed.\n" if $verbose;
543
  }
544
  else {
545
    # Report empty list:
546
    print "No matching task found.\n" if $verbose;
547
  }
548
549
  # Return success:
550
  return 1;
551
}
552
553
# Revert last action:
554
sub revert_last_action {
555
  # Try to restore data from tha backup:
556
  if (move("$savefile$backext", $savefile)) {
557
    # Report success:
558
    print "Last action has been successfully reverted.\n" if $verbose;
559
  }
560
  else {
561
    # Report failure:
562
    print "Already at oldest change.\n" if $verbose;
563
  }
564
565
  # Return success:
566
  return 1;
567
}
568
569
# Set up the option parser:
570
Getopt::Long::Configure('no_auto_abbrev', 'no_ignore_case', 'bundling');
571
572
# Parse command line options:
573
GetOptions(
574
  # General options:
575
  'help|h'         => sub { display_help();    exit 0 },
576
  'version|v'      => sub { display_version(); exit 0 },
577
578
  # Additional options:
579
  'verbose|V'      => sub { $verbose  = 1 },
580
  'quiet|q'        => sub { $verbose  = 0 },
581
  'colour|color|c' => sub { $coloured = 1 },
582
  'plain|p'        => sub { $coloured = 0 },
583
  'savefile|s=s'   => \$savefile,
584
  'finished|f=s'   => \$done,
585
  'unfinished|u=s' => \$undone,
586
);
587
588
# Check whether the supplied colour is valid:
589
unless ((!$done || $valid{$done}) && (!$undone || $valid{$undone})) {
590
  exit_with_error("Invalid colour option.\n" .
591
                  "Try `--help' for more information.", 22);
592
}
593
594
# Get command line arguments:
595
$command = join(' ', @ARGV);
596
597
# Parse command:
598
if    ($command =~ /^(|list|ls)\s*$/) {
599
  # List all items in the task list:
600
  list_tasks();
601
}
602
elsif ($command =~ /^(list|ls)\s+@(\S+)\s*(\S.*|)$/) {
603
  # List items in the selected group, optionally matching the pattern:
604
  list_tasks($2, $3);
605
}
606
elsif ($command =~ /^(list|ls)\s+%(\d+)/) {
607
  # List item with selected ID:
608
  list_tasks(undef, undef, $2);
609
}
610
elsif ($command =~ /^(list|ls)\s+([^@^%\s].*)$/) {
611
  # List items matching the pattern:
612
  list_tasks(undef, $2);
613
}
614
elsif ($command =~ /^add\s+@(\S+)\s+(\S.*)/) {
615
  # Add new item to the task list, belonging to the selected group:
616
  add_task($2, $1);
617
}
618
elsif ($command =~ /^add\s+([^@\s].*)/) {
619
  # Add new item to the task list, belonging to the default group:
620
  add_task($1);
621
}
622
elsif ($command =~ /^(change|mv)\s+%?(\d+)\s+@(\S+)\s*$/) {
623
  # Change group the selected item in the task list belongs to:
624
  change_task($2, $3, 1);
625
}
626
elsif ($command =~ /^(change|mv)\s+%?(\d+)\s+([^@\s].*)/) {
627
  # Change selected item in the task list:
628
  change_task($2, $3);
629
}
630
elsif ($command =~ /^(finish|fn)\s+%?(\d+)/) {
631
  # Mark selected item in the task list as finished:
632
  finish_task($2);
633
}
634
elsif ($command =~ /^(revive|re)\s+%?(\d+)/) {
635
  # Mark selected item in the task list as unfinished:
636
  revive_task($2);
637
}
638
elsif ($command =~ /^(remove|rm)\s+%?(\d+)/) {
639
  # Remove selected item from the task list:
640
  remove_task($2);
641
}
642
elsif ($command =~ /^(undo|ud)\s*$/) {
643
  # Revert last action:
644
  revert_last_action();
645
}
646
elsif ($command =~ /^(groups|gr)\s*$/) {
647
  # Display groups in the task list:
648
  list_groups();
649
}
650
elsif ($command =~ /^version\s*$/) {
651
  # Display version information:
652
  display_version();
653
}
654
elsif ($command =~ /^help\s*$/) {
655
  # Display list of all supported commands and command-line options:
656
  display_help();
657
}
658
elsif ($command =~ /^help\s+(\S+)/) {
659
  # Display information on a specific command:
660
  display_help($1);
661
}
662
else  {
663
  # Report invalid command:
664
  exit_with_error("Invalid command or argument.\n" .
665
                  "Try `--help' for more information.", 22);
666
}
667
668
# Return success:
669
exit 0;
670
671
__END__
672
673
=head1 NAME
674
675
lite2do - a lightweight text-based todo manager
676
677
=head1 SYNOPSIS
678
679
B<lite2do> [I<option>...] I<command> [I<argument>...]
680
681
B<lite2do> B<-h> | B<-v>
682
683
=head1 DESCRIPTION
684
685
B<lite2do> is a lightweight command-line todo manager written in Perl.
686
Being based on w2do and fully compatible with its save file format, it
687
tries to provide much simpler alternative for those who do not appreciate
688
nor require w2do's complexity.
689
690
=head1 COMMANDS
691
692
=over
693
694
=item B<list> [@I<group>] [I<text>...]
695
696
=item B<ls> [@I<group>] [I<text>...]
697
698
Display items in the task list. All tasks are listed by default, but
699
desired subset can be easily selected giving a I<group> name, I<text>
700
pattern, or combination of both.
701
702
=item B<list> %I<id>
703
704
=item B<ls> %I<id>
705
706
Display task with selected I<id>.
707
708
=item B<add> [@I<group>] I<text>...
709
710
Add new item to the task list.
711
712
=item B<change> I<id> I<text>...
713
714
=item B<mv> I<id> I<text>...
715
716
Change item with selected I<id> in the task list.
717
718
=item B<change> I<id> @I<group>
719
720
=item B<mv> I<id> @I<group>
721
722
Change I<group> the item with selected I<id> belongs to.
723
724
=item B<finish> I<id>
725
726
=item B<fn> I<id>
727
728
Mark item with selected I<id> as finished.
729
730
=item B<revive> I<id>
731
732
=item B<re> I<id>
733
734
Mark item with selected I<id> as unfinished.
735
736
=item B<remove> I<id>
737
738
=item B<rm> I<id>
739
740
Remove item with selected I<id> from the task list.
741
742
=item B<undo>
743
744
=item B<ud>
745
746
Revert last action. When invoked, the data are restored from the backup
747
file (i.e. I<~/.lite2do.bak> by default), which is deleted at the same
748
time.
749
750
=item B<groups>
751
752
=item B<gr>
753
754
Display list of groups in the task list along with the number of tasks
755
belonging to them.
756
757
=item B<help> [I<command>]
758
759
Display usage information. By default, list of all supported commands and
760
command-line options is displayed. If the I<command> is supplied, further
761
information on its usage are displayed instead.
762
763
=item B<version>
764
765
Display version information.
766
767
=back
768
769
=head1 OPTIONS
770
771
=over
772
773
=item B<-s> I<file>, B<--savefile> I<file>
774
775
Use selected I<file> instead of the default I<~/.lite2do> as a save file.
776
777
=item B<-c>, B<--colour>, B<--color>
778
779
Use coloured output.
780
781
=item B<-p>, B<--plain>
782
783
Use plain-text output; this is the default behaviour, as most users do not
784
usually fancy having bright colours in their terminal.
785
786
=item B<-f> I<colour>, B<--finished> I<colour>
787
788
Use selected I<colour> for finished tasks; available options are: B<black>,
789
B<red>, B<green>, B<yellow>, B<blue>, B<magenta>, B<cyan> and B<white>.
790
791
=item B<-u> I<colour>, B<--unfinished> I<colour>
792
793
Use selected I<colour> for unfinished tasks; available options are:
794
B<black>, B<red>, B<green>, B<yellow>, B<blue>, B<magenta>, B<cyan> and
795
B<white>.
796
797
=item B<-q>, B<--quiet>
798
799
Avoid displaying messages that are not necessary.
800
801
=item B<-V>, B<--verbose>
802
803
Display all messages; this is the default behaviour.
804
805
=item B<-h>, B<--help>
806
807
Display help message and exit.
808
809
=item B<-v>, B<--version>
810
811
Display version information and exit.
812
813
=back
814
815
=head1 FILES
816
817
=over
818
819
=item I<~/.lite2do>
820
821
Default save file.
822
823
=item I<~/.lite2do.bak>
824
825
Default backup file.
826
827
=back
828
829
=head1 SEE ALSO
830
831
B<w2do>(1), B<w2html>(1), B<w2text>(1), B<perl>(1).
832
833
=head1 BUGS
834
835
To report bugs or even send patches, you can either add new issue to the
836
project bugtracker at <http://code.google.com/p/w2do/issues/>, visit the
837
discussion group at <http://groups.google.com/group/w2do/>, or you can
838
contact the author directly via e-mail.
839
840
=head1 AUTHOR
841
842
Written by Jaromir Hradilek <jhradilek@gmail.com>.
843
844
Permission is granted to copy, distribute and/or modify this document under
845
the terms of the GNU Free Documentation License, Version 1.3 or any later
846
version published by the Free Software Foundation; with no Invariant
847
Sections, no Front-Cover Texts, and no Back-Cover Texts.
848
849
A copy of the license is included as a file called FDL in the main
850
directory of the lite2do source package.
851
852
=head1 COPYRIGHT
853
854
Copyright (C) 2008, 2009 Jaromir Hradilek
855
856
This program is free software; see the source for copying conditions. It is
857
distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
858
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
859
PARTICULAR PURPOSE.
860
861
=cut