Taskwarrior::Kusarigama - plugin system for the Taskwarrior task manager
version 0.12.0
$ task-kusarigama add GitCommit Command::ButBefore Command::AndAfter
$ task-kusarigama install
# enjoy!
This module provides a plugin-based way to run hooks and custom commands for the cli-based task manager Taskwarrior.
Taskwarrior's main method of customization is via hooks
that are executed when the command is run, when it exits, and when
tasks are modified or added. (see https://taskwarrior.org/docs/hooks.html
for the official documentation) Taskwarrior::Kusarigama
leverages this
hook system to allow the creation of custom behaviors and commands.
First, you need to install hook scripts that will invoke Taskwarrior::Kusarigama
when task
is running. You can do that by either using the helper task-kusarigama
:
$ task-kusarigama install
Or dropping manually hook scripts in the ~/.task/hooks
directory. The scripts
should look like
#!/usr/bin/env perl
# script '~/.task/hooks/on-launch-kusarigama.pl'
use Taskwarrior::Kusarigama;
Taskwarrior::Kusarigama->new( raw_args => \@ARGV )
->run_event( 'launch' ); # change with 'add', 'modify', 'exit'
# for the different scripts
Then you need to tell the system with plugins to use,
either via task-kusarigama
$ task-kusarigama add Command::AndAfter
or directly via the Taskwarrior config command
$ task config kusarigama.plugins Command::AndAfter
The last step is to configure the different plugins. Read their
documentation to do it manually or, again, use task-kusarigama
.
$ task-kusarigama install
The inner workings of the plugin system are fairly simple.
The list of plugins we want to be active lives in the taskwarrior configuration under the key <kusarigama.plugins>. E.g.,
kusarigama.plugins=Renew,Command::ButBefore,Command::AndAfter,+FishCurrent
Plugin names prefixed with a plus sign are left alone (minus the '+'),
while the other ones get Taskwarrior::Kusarigama::Plugin::
prefixed to
them.
The Taskwarrior::Kusarigama system itself is invoked via the
scripts put in ~/.task/hooks
by task-kusarigama
. The scripts
detect in which stage they are called (launch, exit, add or modified),
and execute all plugins that consume the associated role (e.g.,
Taskwarrior::Kusarigama::Hook::OnLaunch), in the order they have been
configured.
For example, this plugin will runs on a four hook stages:
package Taskwarrior::Kusarigama::Plugin::PrintStage;
use 5.10.0;
use strict;
use warnings;
use Moo;
extends 'Taskwarrior::Kusarigama::Plugin';
with 'Taskwarrior::Kusarigama::Hook::OnLaunch',
'Taskwarrior::Kusarigama::Hook::OnAdd',
'Taskwarrior::Kusarigama::Hook::OnModify',
'Taskwarrior::Kusarigama::Hook::OnExit';
sub on_launch { say "launch stage: ", __PACKAGE__; }
sub on_add { say "add stage: ", __PACKAGE__; }
sub on_modify { say "modify stage: ", __PACKAGE__; }
sub on_exit { say "exit stage: ", __PACKAGE__; }
1;
Kusarigama defines a fifth hook role,
Taskwarrior::Kusarigama::Hook::OnCommand, to help creating
custom commands. This role does two things: when
task-kusarigama install
is run, it creates a dummy report
such that Taskwarrior will accept task my_custom_command
as a
valid invocation, and then it runs as part of the launch
stage and will run the plugin code if the associated command was used.
Taskwarrior allows the creation of User-Defined Attributes (UDAs). Plugins
can implement a custom_uda
attribute that holds a hashref of
new UDAs and their description. Those UDAs will then be fed to Taskwarrior's
config via task-kusarigama install
, and will thereafter be available like
any other task field.
For example, Taskwarrior::Kusarigama::Plugin::Renew uses UDAs to identify tasks that should create a new, follow-up instance of themselves upon completion:
package Taskwarrior::Kusarigama::Plugin::Renew;
use strict;
use warnings;
use Clone 'clone';
use List::AllUtils qw/ any /;
use Moo;
use MooseX::MungeHas;
extends 'Taskwarrior::Kusarigama::Hook';
with 'Taskwarrior::Kusarigama::Hook::OnExit';
use experimental 'postderef';
has custom_uda => sub{ +{
renew => 'creates a follow-up task upon closing',
rdue => 'next task due date',
rwait => 'next task wait period',
} };
sub on_exit {
my( $self, @tasks ) = @_;
return unless $self->command eq 'done';
my $renewed;
for my $task ( @tasks ) {
next unless any { $task->{$_} } qw/ renew rdue rwait /;
$renewed = 1;
my $new = clone($task);
delete $new->@{qw/ end modified entry status uuid /};
my $due = $new->{rdue};
$new->{due} = $self->calc($due) if $due;
my $wait = $new->{rwait};
$wait =~ s/due/$due/;
$new->{wait} = $self->calc($wait) if $wait;
$new->{status} = $wait ? 'waiting' : 'pending';
$self->import_task($new);
}
$self .= 'created follow-up tasks' if $renewed;
}
1;
Any plugin can abort the taskwarrior process by simply die
ing.
sub on_add {
my( $self, $task ) = @_;
die "need jira ticket for work tasks"
if $task->{project} eq 'work' and not $task->{jira};
}
-
http://techblog.babyl.ca/entry/taskwarrior
the original blog entry
Yanick Champoux yanick@cpan.org
This software is copyright (c) 2019, 2018, 2017 by Yanick Champoux.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.