App-PFT

 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

bin/pft  view on Meta::CPAN

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' ? "![$fn](:pic:$relative)" :
        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

bin/pft-ls  view on Meta::CPAN


=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 = (

bin/pft-ls  view on Meta::CPAN

    },
) 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;



( run in 2.143 seconds using v1.01-cache-2.11-cpan-d7a12ab2c7f )