#!/usr/bin/env perl
|
|
|
|
=pod
|
|
|
|
=head1 NAME
|
|
|
|
notes-links - work with links within my notes
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
Currently this is vimwiki-dependent.
|
|
|
|
# List pages linking to foo:
|
|
notes links --target foo
|
|
|
|
# Pages linking to foo.wiki:
|
|
notes links --file ./foo.wiki
|
|
|
|
# Pages with a date (i.e. logs and diaries) linking to foo:
|
|
notes links --with-date --target foo
|
|
|
|
# Links in foo (experimental, probably broken):
|
|
notes links --source foo
|
|
|
|
# Format (defaults to location):
|
|
notes links --format target
|
|
|
|
=head1 OUTPUT FORMATS
|
|
|
|
B<--format> options include C<vimwiki>, C<tsv>, C<location>, C<target>,
|
|
C<full>, and C<name>.
|
|
|
|
Formats may be glitchy.
|
|
|
|
=head1 AUTHOR
|
|
|
|
Brennen Bearnes
|
|
|
|
=cut
|
|
|
|
use warnings;
|
|
use strict;
|
|
use 5.10.0;
|
|
|
|
use Cwd;
|
|
use Data::Dumper;
|
|
use DBI;
|
|
use File::Basename;
|
|
use File::Spec;
|
|
use Getopt::Long;
|
|
use Pod::Usage;
|
|
use SQL::Abstract;
|
|
use Sys::Hostname;
|
|
|
|
# Display formats:
|
|
my %FORMATS = (
|
|
vimwiki => sub {
|
|
my ($data) = @_;
|
|
my $timestamp = '';
|
|
if (defined $data->{timestamp}) {
|
|
$timestamp = $data->{timestamp} . " ";
|
|
}
|
|
|
|
return ' - '
|
|
. $timestamp
|
|
. '[[/' . $data->{page} . '|'
|
|
. $data->{title}
|
|
. "]]\n";
|
|
},
|
|
|
|
tsv => sub {
|
|
my ($data) = @_;
|
|
my $timestamp = '(null)';
|
|
if (defined $data->{timestamp}) {
|
|
$timestamp = $data->{timestamp};
|
|
}
|
|
return (join "\t", ($timestamp, $data->{page}, $data->{title})) . "\n";
|
|
},
|
|
|
|
# vim location list
|
|
#
|
|
# TODO: Note that the "1" here is, theoretically, a line number.
|
|
# Unfortunately, there's no obvious way to extract that from Pandoc's parsing
|
|
# of the original file, and thus no non-hacky way for notes-collect-metadata to
|
|
# store an approximate value in the database. We _could_ read the file
|
|
# line-by-line, or run grep, looking for the file's basename, but this is
|
|
# tricky to get right.
|
|
#
|
|
# If I keep using this long-term, I should solve this problem.
|
|
location => sub {
|
|
my ($data) = @_;
|
|
|
|
my $result = "$ENV{HOME}/notes/vimwiki/$data->{page}.wiki";
|
|
if ($data->{title}) {
|
|
$result .= ":1:$data->{title}";
|
|
} else {
|
|
$result .= print ":1:$data->{page}"
|
|
}
|
|
|
|
return $result . "\n";
|
|
},
|
|
|
|
# List of bare link _target_ names
|
|
target => sub {
|
|
my ($data) = @_;
|
|
return $data->{target} . "\n";
|
|
},
|
|
|
|
# Fulltext of vimwiki pages:
|
|
full => sub {
|
|
my ($data) = @_;
|
|
my $result = '';
|
|
my $pagepath = "$ENV{HOME}/notes/vimwiki/$data->{page}.wiki";
|
|
$result .= "%% $pagepath {{{\n\n";
|
|
$result .= file_get_contents($pagepath);
|
|
$result .= "\n%% }}}\n\n";
|
|
|
|
return $result;
|
|
},
|
|
|
|
# Bare names of wiki pages (no extension):
|
|
name => sub {
|
|
my ($data) = @_;
|
|
return $data->{page} . "\n";
|
|
},
|
|
);
|
|
|
|
# Handle options, including help generated from the POD above.
|
|
my $debug = 0;
|
|
my $with_date = 0;
|
|
my $target;
|
|
my $source;
|
|
my $file;
|
|
my $format = 'location';
|
|
GetOptions(
|
|
'debug' => \$debug,
|
|
'target=s' => \$target,
|
|
'file=s' => \$file,
|
|
'format=s' => \$format,
|
|
'with-date' => \$with_date,
|
|
'help' => sub { pod2usage(0) },
|
|
) or pod2usage(2);
|
|
|
|
if (defined $file)
|
|
{
|
|
my ($name, $path, $suffix) = fileparse($file, '.wiki');
|
|
|
|
# XXX: This is a dirty fucking hack - get rid of the leading path stuff, but
|
|
# keep subdirs within the vimwiki directory:
|
|
$path =~ s{^.*?notes/vimwiki/}{};
|
|
|
|
$target = $path . $name;
|
|
}
|
|
|
|
my %where = ();
|
|
|
|
# Require that the link point to a given page:
|
|
if (defined $target) {
|
|
$where{target} = $target;
|
|
}
|
|
|
|
# Get only links from pages that have a datetime:
|
|
if ($with_date) {
|
|
# NOT NULL:
|
|
$where{'pages.datetime'} = { '!=', undef };
|
|
}
|
|
|
|
my $dbfile = $ENV{HOME} . "/notes/metadata.db";
|
|
my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile", "", "");
|
|
|
|
my $sql = SQL::Abstract->new;
|
|
my ($query, @bind) = $sql->select(
|
|
'links JOIN pages ON links.page = pages.page',
|
|
# timestamp will be null if datetime is
|
|
"*, DATETIME(datetime, 'localtime') AS timestamp",
|
|
\%where,
|
|
{-desc => [ 'datetime', 'page' ] }
|
|
);
|
|
|
|
if ($debug) {
|
|
say STDERR $query;
|
|
say STDERR Dumper(%where);
|
|
}
|
|
|
|
my $sth = $dbh->prepare($query);
|
|
$sth->execute(@bind);
|
|
|
|
while (my $data = $sth->fetchrow_hashref())
|
|
{
|
|
if ($debug) {
|
|
print STDERR Dumper($data);
|
|
}
|
|
|
|
print $FORMATS{$format}->($data);
|
|
}
|
|
|
|
$sth->execute();
|
|
|
|
# PHP-style file-content grabbing:
|
|
sub file_get_contents {
|
|
my ($file) = @_;
|
|
|
|
open my $fh, '<', $file
|
|
or die "Couldn't open $file: $!\n";
|
|
|
|
my $contents;
|
|
{
|
|
# line separator:
|
|
local $/ = undef;
|
|
$contents = <$fh>;
|
|
}
|
|
|
|
close $fh or die "Couldn't close $file: $!";
|
|
return $contents;
|
|
}
|
|
|
|
1;
|