ACME-2026
view release on metacpan or search on metacpan
lib/ACME/2026.pm view on Meta::CPAN
due => '2026-10-01',
notes => [ { note => 'Signed up', at => '2026-02-10T09:00:00Z' } ],
created_at => '2026-01-01T12:00:00Z',
updated_at => '2026-02-10T09:00:00Z',
}
Status values are C<todo>, C<done>, or C<skipped>. Dates are ISO 8601 strings
(C<YYYY-MM-DD> or C<YYYY-MM-DDTHH:MM:SSZ>).
=head1 FUNCTIONS
=head2 plan_new
my $plan = plan_new(%opts);
Creates a new plan hashref. Supported options:
title - plan title (default: 2026)
storage - JSON path used by plan_save and autosave
autosave - boolean, save after mutating operations
=head2 plan_load
my $plan = plan_load($path, %opts);
Loads a JSON file from C<$path>. The plan is normalized to ensure required
fields exist. You can override C<title> or C<autosave> with C<%opts>.
=head2 plan_save
plan_save($plan);
plan_save($plan, $path);
Writes the plan as JSON. Uses C<$plan-E<gt>{storage}> if no path is provided.
=head2 add_item
my $id = add_item($plan, $title, %opts);
Adds an item and returns its id. Supported options:
list, tags (arrayref or string), priority, due, note
=head2 update_item
my $item = update_item($plan, $id, %attrs);
Updates a few fields in place: C<title>, C<list>, C<tags>, C<priority>, C<due>.
Use C<add_note> or the status helpers for notes and status changes.
=head2 delete_item
my $item = delete_item($plan, $id);
Removes an item and returns it.
=head2 get_item
my $item = get_item($plan, $id);
Returns the item or C<undef> if it does not exist.
=head2 add_note
add_note($plan, $id, $note);
Appends a note with a timestamp.
=head2 complete_item
complete_item($plan, $id, %opts);
Sets the status to C<done>. If C<note> is supplied, it is added.
=head2 skip_item
skip_item($plan, $id, %opts);
Sets the status to C<skipped>. If C<note> is supplied, it is added.
=head2 reopen_item
reopen_item($plan, $id, %opts);
Sets the status back to C<todo>. If C<note> is supplied, it is added.
=head2 items
my @items = items($plan, %filters);
Filters items with any of:
status, list, tag, tags, priority, min_priority, max_priority,
due_before, due_after, sort
For C<tag> or C<tags>, any matching tag is enough. C<sort> supports:
C<due>, C<priority>, C<created>, C<updated>, or C<title>. Prefix with C<->
for descending order.
=head2 stats
my $stats = stats($plan, %filters);
Returns a hashref with C<total>, C<todo>, C<done>, C<skipped>, and
C<complete_pct>.
=cut
sub plan_new {
my %opts = _normalize_opts(@_);
my $now = _now();
my $plan = {
title => defined $opts{title} ? $opts{title} : '2026',
items => [],
next_id => 1,
created_at => $now,
updated_at => $now,
storage => $opts{storage},
autosave => $opts{autosave} ? 1 : 0,
};
( run in 1.007 second using v1.01-cache-2.11-cpan-d80b1682f3f )