ACME-2026
view release on metacpan or search on metacpan
},
"name" : "ACME-2026",
"no_index" : {
"directory" : [
"t",
"inc"
]
},
"prereqs" : {
"build" : {
"requires" : {
"ExtUtils::MakeMaker" : "0"
}
},
"configure" : {
"requires" : {
"ExtUtils::MakeMaker" : "0"
}
},
"runtime" : {
"requires" : {
"JSON::PP" : "0",
"perl" : "5.008003"
}
},
"test" : {
"requires" : {
"Test::More" : "0"
}
}
},
"release_status" : "stable",
"version" : "0.01",
"x_serialization_backend" : "JSON::PP version 4.16"
}
---
abstract: 'Checklists for glorious 2026 goals'
author:
- 'Will Willis <wwillis@cpan.org>'
build_requires:
ExtUtils::MakeMaker: '0'
Test::More: '0'
configure_requires:
ExtUtils::MakeMaker: '0'
dynamic_config: 1
generated_by: 'ExtUtils::MakeMaker version 7.70, CPAN::Meta::Converter version 2.150010'
license: artistic_2
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
version: '1.4'
name: ACME-2026
no_index:
directory:
- t
- inc
requires:
JSON::PP: '0'
perl: '5.008003'
version: '0.01'
x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
Makefile.PL view on Meta::CPAN
},
PREREQ_PM => {
'JSON::PP' => '0',
},
dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
clean => { FILES => 'ACME-2026-*' },
);
# Compatibility with old versions of ExtUtils::MakeMaker
unless (eval { ExtUtils::MakeMaker->VERSION('6.64'); 1 }) {
my $test_requires = delete $WriteMakefileArgs{TEST_REQUIRES} || {};
@{$WriteMakefileArgs{PREREQ_PM}}{keys %$test_requires} = values %$test_requires;
}
unless (eval { ExtUtils::MakeMaker->VERSION('6.55_03'); 1 }) {
my $build_requires = delete $WriteMakefileArgs{BUILD_REQUIRES} || {};
@{$WriteMakefileArgs{PREREQ_PM}}{keys %$build_requires} = values %$build_requires;
}
delete $WriteMakefileArgs{CONFIGURE_REQUIRES}
unless eval { ExtUtils::MakeMaker->VERSION('6.52'); 1 };
delete $WriteMakefileArgs{MIN_PERL_VERSION}
unless eval { ExtUtils::MakeMaker->VERSION('6.48'); 1 };
delete $WriteMakefileArgs{LICENSE}
unless eval { ExtUtils::MakeMaker->VERSION('6.31'); 1 };
WriteMakefile(%WriteMakefileArgs);
lib/ACME/2026.pm view on Meta::CPAN
priority => 2,
);
complete_item($plan, $id, note => 'Signed up for NYC');
my @open = items($plan, status => 'todo', list => 'Health', sort => 'due');
plan_save($plan);
=head1 DESCRIPTION
ACME::2026 is a tiny functional API for keeping 2026 checklists. It stores
plans as plain Perl hashrefs and can persist them to JSON.
=head1 DATA MODEL
Plan hashref:
{
title => '2026',
items => [ ... ],
next_id => 1,
lib/ACME/2026.pm view on Meta::CPAN
updated_at => $now,
storage => $opts{storage},
autosave => $opts{autosave} ? 1 : 0,
};
return $plan;
}
sub plan_load {
my ($path, %opts) = @_;
croak 'plan_load requires a path' unless defined $path && length $path;
my $json = _read_file($path);
my $data = eval { JSON::PP->new->decode($json) };
croak "Failed to decode JSON from $path: $@" if $@;
_normalize_plan($data);
$data->{storage} = $path;
$data->{title} = $opts{title} if exists $opts{title};
$data->{autosave} = $opts{autosave} ? 1 : 0 if exists $opts{autosave};
return $data;
}
sub plan_save {
my ($plan, $path) = @_;
_ensure_plan($plan);
$path ||= $plan->{storage};
croak 'plan_save requires a path or plan storage' unless defined $path && length $path;
_normalize_plan($plan);
my $encoder = JSON::PP->new->canonical(1)->pretty(1);
my $json = $encoder->encode($plan);
_write_file_atomic($path, $json);
return 1;
}
lib/ACME/2026.pm view on Meta::CPAN
my ($title, %opts);
if (@args % 2 == 1) {
$title = shift @args;
%opts = @args;
} else {
%opts = @args;
$title = $opts{title};
}
croak 'add_item requires a title' unless defined $title && length $title;
_reject_unknown('add_item', \%opts, qw(title list tags tag priority due note));
my $now = _now();
my $item = {
id => $plan->{next_id}++,
title => $title,
status => 'todo',
list => defined $opts{list} ? $opts{list} : 'General',
tags => _normalize_tags($opts{tags}, $opts{tag}),
priority => defined $opts{priority} ? $opts{priority} : 3,
lib/ACME/2026.pm view on Meta::CPAN
sub get_item {
my ($plan, $id) = @_;
_ensure_plan($plan);
return _find_item($plan, $id);
}
sub add_note {
my ($plan, $id, $note) = @_;
_ensure_plan($plan);
croak 'add_note requires a note' unless defined $note && length $note;
my $item = _find_item($plan, $id);
croak "No item with id $id" unless $item;
_add_note($plan, $item, $note);
_maybe_autosave($plan);
return $item;
}
lib/ACME/2026.pm view on Meta::CPAN
}
=head1 AUTHOR
Will Willis <wwillis@cpan.org>
=head1 BUGS
Please report any bugs or feature requests to C<bug-acme-2026 at rt.cpan.org>, or through
the web interface at L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=ACME-2026>. I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.
=head1 SUPPORT
You can find documentation for this module with the perldoc command.
perldoc ACME::2026
You can also look for information at:
=over 4
script/acme2026 view on Meta::CPAN
'list|l=s' => \$list,
'tag|t=s@' => \@tags,
'priority|p=i' => \$priority,
'due|d=s' => \$due,
'note|n=s' => \$note,
'help|h' => \$help,
) or usage('Invalid options for add');
usage() if $help;
my $title = shift @ARGV;
usage('add requires a title') unless defined $title && length $title;
my $plan = load_plan($file);
my %opts;
$opts{list} = $list if defined $list;
$opts{priority} = $priority if defined $priority;
$opts{due} = $due if defined $due;
$opts{note} = $note if defined $note;
$opts{tags} = \@tags if @tags;
my $id = add_item($plan, $title, %opts);
script/acme2026 view on Meta::CPAN
my ($note, $help);
GetOptionsFromArray(
\@ARGV,
'file|f=s' => \$file,
'note|n=s' => \$note,
'help|h' => \$help,
) or usage('Invalid options for complete');
usage() if $help;
my $id = shift @ARGV;
usage('complete requires an ID') unless defined $id && $id =~ /^\d+$/;
die "Plan file not found: $file\n" unless -e $file;
my $plan = plan_load($file);
complete_item($plan, $id, (defined $note ? (note => $note) : ()));
plan_save($plan, $file);
print "Completed [$id]\n";
exit 0;
}
if ($cmd eq 'list') {
( run in 0.697 second using v1.01-cache-2.11-cpan-0a27d97929d )