App-Todo
view release on metacpan or search on metacpan
bin/todo.pl view on Meta::CPAN
$args{owner} ||= "me";
do_login() or die("Bad username/password -- edit $CONFFILE and try again.");
%commands = (
list => \&list_tasks,
ls => \&list_tasks,
add => \&add_task,
do => \&do_task,
done => \&do_task,
del => \&del_task,
rm => \&del_task,
edit => \&edit_task,
tag => \&tag_task,
unaccepted => sub {list_tasks($unaccepted_query)},
accept => \&accept_task,
decline => \&decline_task,
assign => \&assign_task,
requests => sub {list_tasks($requests_query)},
hide => \&hide_task,
comment => \&comment_task,
dl => \&download_textfile,
download => \&download_textfile,
ul => \&upload_textfile,
upload => \&upload_textfile,
bd => \&braindump,
braindump => \&braindump,
editdump => \&editdump,
feedback => \&feedback,
);
$command = shift @ARGV || "list";
$commands{$command} or pod2usage(-message => "Unknown command: $command", -exitval => 2);
$commands{$command}->();
}
=begin comment
=head1 CONFIG FILE
These methods deal with loading the config file, and populating it
with selections read from the terminal on our first run.
=cut
sub setup_config {
check_config_perms() unless($^O eq 'MSWin32');
load_config();
check_config();
}
sub check_config_perms {
return unless -e $CONFFILE;
my @stat = stat($CONFFILE);
my $mode = $stat[2];
if($mode & S_IRGRP || $mode & S_IROTH) {
warn("Config file $CONFFILE is readable by someone other than you, fixing.");
chmod 0600, $CONFFILE;
}
}
sub load_config {
return unless(-e $CONFFILE);
%config = %{LoadFile($CONFFILE) || {}};
my $sid = $config{sid};
if($sid) {
my $uri = URI->new($config{site});
$ua->cookie_jar->set_cookie(0, 'JIFTY_SID_HIVEMINDER',
$sid, '/', $uri->host, $uri->port,
0, 0, undef, 1);
}
if($config{site}) {
# Somehow, localhost gets normalized to localhost.localdomain,
# and messes up HTTP::Cookies when we try to set cookies on
# localhost, since it doesn't send them to
# localhost.localdomain.
$config{site} =~ s/localhost/127.0.0.1/;
}
}
sub check_config {
new_config() unless $config{email};
}
sub new_config {
print <<"END_WELCOME";
Welcome to todo.pl! before we get started, please enter your
Hiveminder username and password so we can access your tasklist.
This information will be stored in $CONFFILE,
should you ever need to change it.
END_WELCOME
$config{site} ||= 'http://hiveminder.com';
$config{color} ||= 'on';
while (1) {
local $| = 1; # Flush buffers immediately
print "First, what's your email address? ";
$config{email} = <stdin>;
chomp($config{email});
use Term::ReadKey;
print "And your password? ";
ReadMode('noecho');
$config{password} = <stdin>;
chomp($config{password});
ReadMode('restore');
print "\n";
last if do_login();
print "That combination doesn't seem to be correct. Try again?\n";
}
save_config();
}
sub save_config {
DumpFile($CONFFILE, \%config);
chmod 0600, $CONFFILE;
}
sub version {
print "This is hiveminder.com's todo.pl version $VERSION\n";
}
=head1 TASKS
Methods related to manipulating tasks -- the meat of the script.
=cut
sub list_tasks {
my $query = shift || $default_query;
if( scalar @ARGV ){
$query = join '/', @ARGV;
}
#substitute actual query if this is a named search.
if( defined $config{named_searches}->{$query} ){
$query = $config{named_searches}->{$query};
$query =~ s!\s+!/!g;
}
my $tag;
$query .= "/tag/$tag" while $tag = shift @{$args{tag}};
for my $key (qw(group priority due)) {
$query .= "/$key/$args{$key}" if $args{$key};
}
$query .= "/owner/$args{owner}";
my $tasks = download_tasks($query);
if (@$tasks == 0)
{
print "You have no matching tasks.\n";
return;
}
for my $t (@$tasks) {
printf "#%4s ", $locator->encode($t->{id});
print colored('(' . priority_to_string($t->{priority}) . ')',
priority_to_color($t->{priority})), ' '
if $t->{priority} != 3;
print colored($t->{summary}, priority_to_color($t->{priority}));
print ' ', colored("(Due " . $t->{due} . ")",
(overdue($t->{due}) ? 'magenta' : 'dark'))
if $t->{due};
if ($t->{tags}) {
print color('reset'), ' ', color('dark');
print '[' . $t->{tags} . ']';
}
( run in 0.824 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )