Dotfiles, utilities, and other apparatus.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

196 lines
3.6 KiB

  1. #!/usr/bin/env perl
  2. =pod
  3. =head1 NAME
  4. notes-pages - work with pages within my notes
  5. =head1 SYNOPSIS
  6. Currently this is vimwiki-dependent.
  7. # List pages
  8. notes pages
  9. # All pages with a date of July 18th, 2022:
  10. notes pages --date 2022-07-18
  11. # Set output format:
  12. notes pages --format [vimwiki, tsv, location, full, name]
  13. # All pages with a date:
  14. notes pages --with-date
  15. # All pages without a date:
  16. notes pages --no-date
  17. # Print this help:
  18. notes pages --help
  19. # Debug queries
  20. notes pages --debug
  21. =head1 AUTHOR
  22. Brennen Bearnes
  23. =cut
  24. use warnings;
  25. use strict;
  26. use 5.10.0;
  27. use Cwd;
  28. use Data::Dumper;
  29. use DBI;
  30. use File::Basename;
  31. use File::Spec;
  32. use Getopt::Long;
  33. use Pod::Usage;
  34. use SQL::Abstract;
  35. use Sys::Hostname;
  36. # Display formats:
  37. my %FORMATS = (
  38. vimwiki => sub {
  39. my ($data) = @_;
  40. my $timestamp = '';
  41. if (defined $data->{timestamp}) {
  42. $timestamp = $data->{timestamp} . " ";
  43. }
  44. return ' - '
  45. . $timestamp
  46. . '[[/' . $data->{page} . '|'
  47. . $data->{title}
  48. . "]]\n";
  49. },
  50. tsv => sub {
  51. my ($data) = @_;
  52. my $timestamp = '(null)';
  53. if (defined $data->{timestamp}) {
  54. $timestamp = $data->{timestamp};
  55. }
  56. return (join "\t", ($timestamp, $data->{page}, $data->{title})) . "\n";
  57. },
  58. # vim location list
  59. location => sub {
  60. my ($data) = @_;
  61. my $result = "$ENV{HOME}/notes/vimwiki/$data->{page}.wiki";
  62. if ($data->{title}) {
  63. $result .= ":1:$data->{title}";
  64. } else {
  65. $result .= print ":1:$data->{page}"
  66. }
  67. return $result . "\n";
  68. },
  69. # Bare names of wiki pages (no extension):
  70. name => sub {
  71. my ($data) = @_;
  72. return $data->{page} . "\n";
  73. },
  74. # Fulltext of vimwiki pages:
  75. full => sub {
  76. my ($data) = @_;
  77. my $result = '';
  78. my $pagepath = "$ENV{HOME}/notes/vimwiki/$data->{page}.wiki";
  79. $result .= "%% $pagepath {{{\n\n";
  80. $result .= file_get_contents($pagepath);
  81. $result .= "\n%% }}}\n\n";
  82. },
  83. );
  84. # Handle options, including help generated from the POD above.
  85. my $debug = 0;
  86. my $with_date = 0;
  87. my $date;
  88. my $file;
  89. my $no_date;
  90. my $format = 'location';
  91. GetOptions(
  92. 'debug' => \$debug,
  93. 'date=s' => \$date,
  94. 'format=s' => \$format,
  95. 'with-date' => \$with_date,
  96. 'no-date' => \$no_date,
  97. 'help' => sub { pod2usage(0) },
  98. ) or pod2usage(2);
  99. my %where = ();
  100. # Get only links from pages that have a datetime:
  101. if ($with_date) {
  102. # NOT NULL:
  103. $where{'pages.datetime'} = { '!=', undef };
  104. }
  105. # Get only links from pages that lack a datetime:
  106. if ($no_date) {
  107. # IS NULL:
  108. $where{'pages.datetime'} = undef;
  109. }
  110. # Get only links from pages that have a given specific datetime:
  111. if ($date) {
  112. $where{'date'} = $date;
  113. }
  114. my $dbfile = $ENV{HOME} . "/notes/metadata.db";
  115. my $dbh = DBI->connect("dbi:SQLite:dbname=$dbfile", "", "");
  116. my $sql = SQL::Abstract->new;
  117. my ($query, @bind) = $sql->select(
  118. 'pages',
  119. # timestamp will be null if datetime is
  120. "*,
  121. DATETIME(datetime, 'localtime') AS timestamp,
  122. DATE(datetime, 'localtime') AS date",
  123. \%where,
  124. {-asc => [ 'date', 'page' ] }
  125. );
  126. if ($debug) {
  127. say STDERR $query;
  128. say STDERR Dumper(%where);
  129. }
  130. my $sth = $dbh->prepare($query);
  131. $sth->execute(@bind);
  132. while (my $data = $sth->fetchrow_hashref())
  133. {
  134. if ($debug) {
  135. print STDERR Dumper($data);
  136. }
  137. print $FORMATS{$format}->($data);
  138. }
  139. $sth->execute();
  140. # PHP-style file-content grabbing:
  141. sub file_get_contents {
  142. my ($file) = @_;
  143. open my $fh, '<', $file
  144. or die "Couldn't open $file: $!\n";
  145. my $contents;
  146. {
  147. # line separator:
  148. local $/ = undef;
  149. $contents = <$fh>;
  150. }
  151. close $fh or die "Couldn't close $file: $!";
  152. return $contents;
  153. }
  154. 1;