view release on metacpan or search on metacpan
bash_completion.d/pft view on Meta::CPAN
_pft_init()
{
local alt="$(
perl -CO -MPFT::Conf=bash_completion_autogen -wE 'say bash_completion_autogen'
)"
COMPREPLY=($(compgen -W "$alt" -- "${COMP_WORDS[COMP_CWORD]}"))
}
_pft_edit()
{
local cur="${COMP_WORDS[COMP_CWORD]}"
local common_opts='-t --author --select --back --resume
--year --month --day --help'
local alt
binmode STDOUT, ':encoding(console_out)';
binmode STDERR, ':encoding(console_out)';
$0 = basename $0;
my $subcmd = shift @ARGV;
unless (defined $subcmd) {
print STDERR "Usage: $0 <command> [<args>]\n",
"Usage: $0 --help\n";
exit 1;
} elsif ($subcmd =~ /^(?:version|-v|--version)$/) {
say STDERR $App::PFT::VersionString;
exit 0
} elsif ($subcmd =~ /^(?:help|-h|--help)$/) {
@ARGV and do {
print STDERR "Did you mean `$0 $ARGV[0] --help`?\n";
exit 1
};
pod2usage
-exitval => 1,
-verbose => 2,
-input => pod_where({-inc => 1}, __PACKAGE__)
bin/pft-clean view on Meta::CPAN
'verbose|v' => \$verbose,
'help|h' => sub {
pod2usage
-exitval => 1,
-verbose => 2,
-input => App::PFT::help_of 'clean',
}
) or exit 1;
my $tree = eval{ PFT::Tree->new } || do {
say STDERR $@ =~ s/ at.*$//rs;
exit 1
};
File::Path::rmtree
encode(locale_fs => $tree->dir_build),
{ verbose => $verbose }
;
bin/pft-edit view on Meta::CPAN
},
) or exit 1;
$opts{B} = 1 if !$opts{M} &&
grep defined, $opts{back}, map $datespec{$_}, qw(y m d);
do {
my @sel = grep $opts{$_}, qw(B M T P);
if (@sel != 1) {
local $, = ' -';
say STDERR 'Select exactly one mode: -B -M -T -P';
exit 2
}
};
my $tree = eval{ PFT::Tree->new } || do {
say STDERR $@ =~ s/ at.*$//rs;
exit 3
};
my $conf = eval{ $tree->conf } || do {
say STDERR 'Configuration error: ', $@ =~ s/ at.*$//rs;
exit 4
};
my($entry, $hdr);
# The following block defines $entry as the entry we are going to edit.
# In some of the cases also $hdr will be defined with the corresponding header.
eval {
if (defined $opts{back}) {
my @entries;
bin/pft-edit view on Meta::CPAN
}
if (@entries == 1) {
$entry = $entries[0];
}
elsif (exists $opts{select}) {
$entry = $entries[$opts{select}];
die 'invalid index ', $opts{select} unless defined $entry;
}
else {
say STDERR 'Multiple entries:';
for (my $idx = 0; $idx < @entries; $idx ++) {
my $hdr = $entries[$idx]->header;
say STDERR sprintf("%d: %s",
$idx,
$hdr ? $hdr->title : $_->name
)
}
die 'disambiguate by providing --select=<index>'
}
$hdr = eval{ $entry->header }; # Might be malformed.
} elsif ($opts{T}) {
die 'mandatory title' unless @ARGV;
$hdr = PFT::Header->new(
bin/pft-edit view on Meta::CPAN
$hdr = PFT::Header->new(
author => $conf->{site}{author},
date => PFT::Date->from_spec(%datespec)->derive(d => undef),
)
} elsif ($opts{B}) {
$hdr = PFT::Header->new(
title => join(' ', @ARGV) || 'Today',
author => $conf->{site}{author},
tags => $opts{tags} || [],
date => eval{ PFT::Date->from_spec(%datespec) } || do {
say STDERR 'Invalid date: ', $@ =~ s/ at.*$//rs;
},
)
} elsif ($opts{P}) {
die 'mandatory title' unless @ARGV;
$hdr = PFT::Header->new(
title => join(' ', @ARGV),
author => $conf->{site}{author},
tags => $opts{tags} || [],
)
} else { die "unhandled case? This is a bug" }
$entry = $tree->content->new_entry($hdr)
}
1; # can be 1 only if there was no error.
}
or $@ && do {
say STDERR 'Editing entry: ', $@ =~ s/at .*$//rs;
exit 6
};
sub edit_file {
my $path = $entry->path;
my $editor = $opts{editor}
|| $conf->{system}{editor}
|| $ENV{EDITOR}
|| do {
say STDERR "Cannot infer editor. Try setting env EDITOR or to";
say STDERR "define it in configuration file (system -> editor)";
exit 5
};
if ($editor =~ s/(?<!%)%s/$path/g) {
system($editor)
}
else {
system($editor, $path)
}
}
bin/pft-edit view on Meta::CPAN
eval {
if ($opts{stdin} or $opts{append}) {
feed_file
}
else {
edit_file
}
if ($entry->exists) {
if ($entry->void) {
say STDERR "Removing empty entry at ", $entry->path;
$entry->unlink;
}
else {
$entry->make_consistent;
}
}
} or $@ && do {
say STDERR "After editing: ", $@ =~ s/at .*$//sr;
exit 7
}
bin/pft-gen-rss view on Meta::CPAN
GetOptions(
'help|h!' => sub {
pod2usage
-exitval => 1,
-verbose => 2,
-input => App::PFT::help_of 'gen-rss',
},
) or exit 1;
my $tree = eval{ PFT::Tree->new } || do {
say STDERR $@ =~ s/ at.*$//rs;
exit 2
};
my $conf = eval{ $tree->conf } || do {
say STDERR 'Configuration error: ', $@ =~ s/ at.*$//rs;
exit 3;
};
my $digest = Digest::MD5->new;
my $site_title = $conf->{site}{title};
my $site_url = $conf->{site}{url};
my $feed_path = $conf->{site}{feed}{path} || "feed.rss";
my $feed_url = "$site_url/$feed_path";
my $encoding = $conf->{site}{encoding};
bin/pft-gen-rss view on Meta::CPAN
$pubDate = do {
my($y, $m, $d) = @{$node->date};
strftime("%a, %d %b %Y %H:%M:%S %z", 0, 0, 0, $d, $m, $y - 1900)
};
my $content = escape_html $node->html(\&node_to_href);
if ($first) {
$first = 0;
say "<lastBuildDate>$pubDate</lastBuildDate>"
}
say '<item>',
' <title>', $node->title, '</title>',
' <guid isPermaLink="false">', $guid, '</guid>',
' <pubDate>', $pubDate, '</pubDate>',
' <link>', node_to_href($node), '</link>',
' <description>', $content, '</description>',
'</item>'
}
print <<END;
</channel>
bin/pft-grab view on Meta::CPAN
'rename|r=s' => \$opts{rename},
'help|h' => sub {
pod2usage
-exitval => 1,
-verbose => 2,
-input => App::PFT::help_of 'grab',
}
) or exit 1;
@ARGV or do {
say STDERR 'Any file?';
exit 1;
};
@ARGV > 1 and $opts{rename} and do {
say STDERR '--rename is not allowed with multiple files';
exit 1;
};
my $content = eval{ PFT::Tree->new->content } or do {
say STDERR $@ =~ s/ at.*$//rs;
exit 1
};
my $dst_base = do {
my $o = $opts{dst};
$o eq 'a' ? $content->dir_attachments :
$o eq 'p' ? $content->dir_pics :
die;
};
bin/pft-grab view on Meta::CPAN
ITEM: for my $orig_path (@ARGV) {
my $uri = URI->new($orig_path);
my $fn = basename $uri->path . ($uri->query || '');
my $dst_path = catfile($dst_dir, $opts{rename} || $fn);
if ($uri->has_recognized_scheme) {
my $status = LWP::Simple::getstore($uri->as_string, $dst_path);
if ($status < 200 || $status >= 300) {
say STDERR 'Failed to retrieve ', $uri->as_iri, ': ', $status;
next ITEM;
}
}
else {
File::Copy::copy($orig_path, $dst_path) or do {
say STDERR "Copy failed: $!";
exit 2
}
}
my $relative = abs2rel($dst_path, $dst_base);
say STDOUT
$opts{dst} eq 'a' ? "[$fn]: :attach:$relative" :
$opts{dst} eq 'p' ? "" :
die;
}
bin/pft-init view on Meta::CPAN
this manual page corresponds to an equally named setting in the C<pft.yaml>
file.
=cut
# NOTE: Documentation continues with auto-generated options from PFT::Conf
# at the end of this file (from "=head1 OPTIONS" to the subsequent
# "# END # AUTOGEN" comment).
#
# Generate again if needed with:
#
# perl -CO -MPFT::Conf=pod_autogen -wE 'say pod_autogen'
#
use strict;
use warnings;
use utf8;
use v5.16;
use feature 'say';
use PFT::Conf;
use PFT::Tree;
bin/pft-init view on Meta::CPAN
'help|h!' => sub {
pod2usage
-exitval => 0,
-verbose => 2,
-input => App::PFT::help_of 'init',
},
) or exit 1;
if (my $root = PFT::Conf::locate) {
say STDERR 'Configuration exists: ', $root;
exit 1;
}
my $conf = PFT::Conf->new_getopt(\%conf_opts);
$conf->save_to(my $root = Cwd::cwd);
my $tree = PFT::Tree->new($root, {create => 1});
my $home = $tree->content->new_entry(PFT::Header->new(
title => $conf->{site}{home},
author => $conf->{site}{author},
bin/pft-init view on Meta::CPAN
'*',
);
foreach (glob encode(locale_fs => $glob)) {
my $outfn = File::Spec->catfile(
encode(locale_fs => $tree->dir_templates),
basename($_)
);
open my $in, '< :encoding(UTF-8)', $_ or do {
say STDERR 'Cannot open ', decode(locale_fs => $_), ": $!";
exit 1;
};
open my $out, '> :encoding(locale_fs)', $outfn or do {
say STDERR 'Cannot open ', decode(locale_fs => $outfn), ": $!";
exit 1;
};
print $out (<$in>);
close $in;
close $out;
};
=head1 CONFIGURATION OPTIONS
=head1 SEE ALSO
L<pft(1)>
=cut
use strict;
use warnings;
use feature qw/say state/;
use Encode::Locale qw/$ENCODING_LOCALE/;
use App::PFT;
use PFT::Tree;
use Pod::Usage;
use Getopt::Long;
Getopt::Long::Configure qw/bundling/;
my %opts = (
},
) or exit 1;
my %classes = (
pages => \&list_pages,
blog => \&list_blog,
tags => \&list_tags,
);
my $tree = eval{ PFT::Tree->new } || do {
say STDERR $@ =~ s/ at.*$//rs;
exit 3
};
my $content = PFT::Tree->new->content;
my $cls = shift;
if (defined $cls and my $handle = $classes{$cls}) {
# The selected handle is used to list the specific class of content objects.
say &{$opts{pretty}} for $handle->()
}
else {
say STDERR "Usage: $App::PFT::Name <class> [options]";
say STDERR "Available classes:";
say STDERR " * $_" for keys %classes;
exit 1;
}
sub pretty_parse {
my $fmt = shift;
my $align = qr/-?\d*/;
sub {
my $out = $fmt;
bin/pft-make view on Meta::CPAN
L<pft(1)>, L<pft-gen-rss(1)>, L<pft-init(1)>
=cut
use strict;
use warnings;
use utf8;
use v5.16;
use feature qw/say state/;
use Carp;
use Digest::MD5;
use Encode::Locale;
use Encode;
use Template::Alloy;
use File::Spec;
use File::Basename qw/dirname basename/;
use File::Path qw/make_path/;
bin/pft-make view on Meta::CPAN
GetOptions(
'help|h!' => sub {
pod2usage
-exitval => 1,
-verbose => 2,
-input => App::PFT::help_of 'make',
},
) or exit 1;
my $tree = eval{ PFT::Tree->new } || do {
say STDERR $@ =~ s/ at.*$//rs;
exit 2
};
my $conf = eval{ $tree->conf } || do {
say STDERR 'Configuration error: ', $@ =~ s/ at.*$//rs;
exit 3;
};
my $template = Template::Alloy->new(
INCLUDE_PATH => $tree->dir_templates,
ENCODING => $conf->{site}{encoding},
);
my $dir_build = $tree->dir_build;
my $map = $tree->content_map;
bin/pft-make view on Meta::CPAN
rename $temp => $path;
}
sub compile_entry {
my($node, $content) = @_;
my $hdr = $node->header;
my $first = 1;
foreach ($node->symbols_unres) {
if ($first) {
say STDERR "Unresolved links in $node:"
}
my($symbol, $reason) = @$_;
say STDERR "- link: $symbol";
say STDERR " reason: $reason";
undef $first;
}
my $is_home;
if (!$node->virtual && $hdr->slug eq $home_node_slug) {
die "There should be no doubles" if defined $home_node;
$home_node = $node;
$is_home ++;
}
bin/pft-pub view on Meta::CPAN
Getopt::Long::Configure 'bundling';
my %methods = (
'rsync+ssh' => \&rsync_ssh,
'install' => \&install,
);
GetOptions(
'list-required-conf' => sub {
for my $mname (sort keys %methods) {
say STDOUT '--publish-method="'. $mname, '" requires configuration:';
say STDOUT "\t--publish-$_" foreach $methods{$mname}->();
}
exit 0;
},
'help|h' => sub {
pod2usage
-exitval => 1,
-verbose => 2,
-input => App::PFT::help_of 'pub',
}
) or exit 1;
my $tree = eval{ PFT::Tree->new } || do {
say STDERR $@ =~ s/ at.*$//rs;
exit 3
};
my $conf = eval{ $tree->conf } || do {
say STDERR 'Configuration error: ', $@ =~ s/ at.*$//rs;
exit 4
};
my $method = $methods{$conf->{publish}{method}} || do {
say STDERR 'Unknown method ', $conf->{publish}{method};
exit 5;
};
$method->($tree);
exit 0;
sub check {
foreach (@_) {
unless(defined $conf->{publish}{$_}) {
say STDERR 'Cannot use publish.', $_,
': missing publish.', $_, ' in ',
$PFT::Conf::CONF_NAME;
exit 6
}
}
}
sub rsync_ssh {
my $tree = shift;
defined $tree || return qw/user host path/;
check qw/user host path/;
my $src = File::Spec->catfile($tree->dir_build, '');
my $publish = $conf->{publish};
my $dst = "$publish->{user}\@$publish->{host}:$publish->{path}";
my $port = $publish->{port} || 22;
local $, = "\n\t";
say STDERR 'Sending with RSync', "from $src", "to $dst";
system('rsync',
'-e', "ssh -p $port",
'--recursive',
'--verbose',
'--copy-links',
'--times',
'--delete',
'--human-readable',
'--progress',
bin/pft-show view on Meta::CPAN
use Pod::Usage;
use File::Spec;
use Getopt::Long;
Getopt::Long::Configure ("bundling");
use PFT::Tree;
my $tree = eval{ PFT::Tree->new } || do {
say STDERR $@ =~ s/ at.*$//rs;
exit 3
};
my $conf = eval{ $tree->conf } || do {
say STDERR 'Configuration error: ', $@ =~ s/ at.*$//rs;
exit 4
};
my $browser = $conf->{system}{browser} || $ENV{BROWSER};
my $verbose = 0;
GetOptions(
'browser=s' => \$browser,
'help|h' => sub {
pod2usage
-exitval => 1,
-verbose => 2,
-input => App::PFT::help_of 'show',
}
) or exit 1;
my $index = File::Spec->catfile($tree->dir_build, 'index.html');
unless ($index) {
say STDERR 'Need to build first, use pft make';
exit 1;
}
if ($browser =~ s/(?<!%)%s/$index/g) {
system($browser)
} else {
system($browser, $index)
}
lib/App/PFT/Util.pm view on Meta::CPAN
use File::Spec::Functions qw/updir catfile catdir rootdir/;
use File::Basename qw/dirname/;
use Cwd qw/abs_path cwd/;
sub ln {
my($from, $to, $verbose) = @_;
my $ok;
-e $to && remove_tree $to, {verbose => $verbose};
make_path dirname $to;
$verbose and say STDERR "Linking $from to $to";
$ok = link($from, $to);
$ok and return 1;
$verbose and say STDERR "Could not hardlink: $!. Symlinking";
$ok = eval { symlink($from, $to) };
$ok and return 1;
$verbose and say STDERR "Could not symlink: $@$!. Copying";
remove_tree $to, {verbose => $verbose};
$ok = dircopy $from, $to;
$ok and return 1;
$verbose and say STDERR "Everything failed";
return '';
}
1;