From d170a2fccfa2a5e0e326515d83b720b122821fec Mon Sep 17 00:00:00 2001 From: Nathan McCarty Date: Sun, 9 Feb 2025 02:12:14 -0500 Subject: [PATCH] Series commands --- blog | 100 ++++++++++++++++++++++++++++++++++++++++++ lib/DB.rakumod | 18 +++++++- lib/DB/Series.rakumod | 2 +- 3 files changed, 118 insertions(+), 2 deletions(-) diff --git a/blog b/blog index 759f669..6784af9 100755 --- a/blog +++ b/blog @@ -3,6 +3,7 @@ use v6.e.PREVIEW; use DB; use DB::BlogMeta; +use DB::Series; use DB::MarkdownPost; use DB::IdrisPost; @@ -282,3 +283,102 @@ multi MAIN( } $db.write: $db-dir; } + +#| Create a new series +multi MAIN( + "series", + "new", + #| The path of the database file + IO::Path(Str) :$db-dir = $default-db-dir, +) { + my $db = read-db $db-dir; + say 'Series Title: '; + my $title = get; + say 'Series Description: '; + my $desc = get; + + my $series = Series.new: + title => $title, desc => $desc; + my $id = $db.insert-series: $series; + say 'Series inserted with id ', $id; + + $db.write: $db-dir; +} + + +#| Provide a table of series +multi MAIN( + "series", + "list", + #| The path of the database directory + IO::Path(Str) :$db-dir = $default-db-dir, + #| The number of items to show on a single page + Int :$per-page = 10; + #| The page number to show + Int :$page = 1; +) { + my $db = read-db $db-dir; + my @pages = + $db.series.sort(*.key).rotor($per-page, :partial); + my @page = @pages[$page - 1].flat; + my $table = Pretty::Table.new: + title => "Series (page $page/{@pages.elems})", + field-names => ["ID", "Title", "Desc"]; + for @page -> $pair { + my $id = $pair.key; + my $series = $pair.value; + # TODO: Terminal aware truncation + my $title = do if $series.title.chars > 40 { + "{$series.title.substr(0, 50)}..." + } else { + $series.title + }; + my $desc = do if $series.desc.chars > 40 { + "{$series.desc.substr(0, 50)}..." + } else { + $series.desc + }; + $table.add-row: [$id, $title, $desc]; + } + say $table; +} + +#| Display the contents of a series +multi MAIN( + "series", + "info", + #| The id of the series to display + Int $id, + #| The path of the database directory + IO::Path(Str) :$db-dir = $default-db-dir, +) { + my $db = read-db $db-dir; + my $series = $db.series{$id.Int}; + say 'Title: ', $series.title; + say 'Description:'; + for $series.desc.lines -> $line { + say ' ', $line; + } + say 'Posts:'; + for $series.post-ids -> $post-id { + my $post = $db.posts{$post-id}; + say ' * ', $post-id, ': ', $post.title; + } +} + +#| Add a post to a series +multi MAIN( + "series", + "add", + #| The id of the series to add to + Int $series-id, + #| The id of the post to add + Int $post-id, + #| The path of the database directory + IO::Path(Str) :$db-dir = $default-db-dir, +) { + my $db = read-db $db-dir; + my $series = $db.series{$series-id.Int}; + $series.post-ids.push: $post-id.Int; + $db.write: $db-dir; +} diff --git a/lib/DB.rakumod b/lib/DB.rakumod index d977061..042f1a9 100644 --- a/lib/DB.rakumod +++ b/lib/DB.rakumod @@ -40,6 +40,15 @@ class PostDB { } } + #| Get the next unused series ID + method next-series-id(--> Int) { + if %!series.elems > 0 { + %!series.keys.max + 1 + } else { + 0 + } + } + #| Insert a new post to the DB, returning its id method insert-post(PostTypes $post --> Int) { my $id = self.next-post-id; @@ -47,6 +56,13 @@ class PostDB { $id } + #| Insert a new series to the DB, returning its id + method insert-series(Series:D $series --> Int) { + my $id = self.next-series-id; + %!series{$id} = $series; + $id + } + #| Initialize a new database method init(BlogMeta:D $meta --> PostDB:D) { my %posts{Int} of PostTypes = %(); @@ -172,7 +188,7 @@ sub read-db(IO::Path:D $dir --> PostDB:D) is export { } } # Read series - my %series{Int} of PostTypes = %(); + my %series{Int} of Series:D = %(); # For backwards compatability, the series directory is optional. It will be # created on the next db operation, but we don't need it to read the site if $series-dir.e { diff --git a/lib/DB/Series.rakumod b/lib/DB/Series.rakumod index 2241215..4379cae 100644 --- a/lib/DB/Series.rakumod +++ b/lib/DB/Series.rakumod @@ -12,4 +12,4 @@ has Str:D $.title is required; has Str:D $.desc is required; #| The ids of the posts in the series, in series order -has Int:D @.post-ids = []; +has Int:D @.post-ids is rw = [];