Setting the scene
So yesterday I wrote a couple of online-liners for cli-journaling-in-joplin-with-raku, managing journal entries in the Joplin note-taking application with help from Raku.
I made one for writing:
I made one for reading:
They work. That’s great.
They don’t work great, though. Mainly the one-liner for reading. It dumps every journal entry, which is both overwhelming and slow. Overwhelming because I only want to see today’s journal entries most of the time. Slow because every one of those entries requires a separate call to joplin
. Joplin is lovely, but it expects to be used as a persistent application. The command line functionality is optimized for convenience. It is not optimized for being hammered repeatedly by an overenthusiastic command line script.
I can fix the overwhelming. I can’t properly fix the slow until I learn more about the Joplin API. At least I can make the experience less awful.
Make it less awful
Less hard-coding please
First things first. I might change the name of my journal notebook. You might want a daily diary rather than a giant stack of entries.
Focusing on daily journals? Set $entry-window
to "day"
.
Adding an entry
Raku’s DateTime classes provide the gist of what we got with GNU Date. truncated-to
rounds our current timestamp — now
— down to the minute.
It doesn’t print exactly the same as date
:
It wouldn’t take excessive effort to make them match, but I’m just not concerned about it at the moment.
Use a MAIN
sub
Well, we went and put the logic for adding an entry into a function. We want to call that function at some point, right?
We don’t need MAIN
yet. If present, it’s your Raku script’s official entry point. If not, you have a plain old script. You’re good either way. Having that entry point will make things easier to manage in a minute, though.
If we run this as-is, it adds a new entry.
Okay, fine. It works. So far it’s neither tidier nor more readable than the initial one-liner. But writing an entry was never the problem.
The problem was reading the entries.
Read all the entries?
Back in our one-liner, collecting entries and reading them got smushed together. They’re two distinct actions, though.
Right. Now we have subs for writing, and subs for reading. How do we want to get at them? Maybe a callback table with action keywords? Maybe a fancy module?
Nope! Well — we could. But we don’t need to. Raku has multi-dispatch!
Use multiple MAIN
subs!
We replace the initial MAIN
definition with these:
multi
tells Raku to expect multiple definitions for this sub. Without it, the compiler gets annoyed.
Multiple dispatch means a few things depending on which language you’re using — or which computer scientist you’re asking. Basically it lets you avoid having one giant glob of a function with all sorts of special logic. You do that by having a different version of the function for different situations.
Where I got surprised? Most of the tiny amount I’ve read out there for multiple dispatch talks about basing on types or pattern matching against variables. You could absolutely do that with Raku.
Thing is, we’re not doing anything with $action
. We read if the first command line argument is read
. We add if it’s add
. Raku is happy enough matching that first argument against literal strings. I assume other multi-dispatch languages can to the same, but nobody’s been uncouth enough to bring it up in polite company. It’s always “this type” and “that pattern” or “this enum.”
What happens if we try to run the script with no arguments? Well, if we didn’t remove that initial version of MAIN
we get a compiler error about redefining the sub. But once that’s out of the way, we no longer have a default path into the application!
No worries. Raku’s special handling of the entry point sub shows us the accepted usage.
And that’s where those #=
comments come in. They provide extra detail for the usage message displayed.
Let’s try them out. We’ll add
an entry and then make sure it shows up when we read
them.
Nice. Of course, at this point I’m being handed 142 lines of text, and it’s taking about 12 seconds to do it. All that work and we finally reached the full “overwhelming and slow” point we were at this morning.
Things are about to improve!
I just want today
I’ve been carefully using ISO 8601 format for my entries. That means I can filter to a specific date — or year, month, hour, etc — by constructing a date fragment and grabbing each entry that starts with the fragment.
Getting today’s entries then becomes a matter of extracting a yyyy-mm-dd
string from the ever-so-helpful DateTime.
2021-05-24
@b2gills mentioned that I could also use
Date.today
here!Why didn't you use Date.today?
— Brad Gilbert (@b2gills) May 25, 2021
If you had a coercive parameter, you wouldn't even need to do anything more than Date.today.
sub filtered-entries(Str(Date) $date-funnel) {…}
sub entries-for-today() {
filtered-entries Date.today
}
I haven’t messed with parameter coercion yet, but that looks like it will come in handy.
Need to touch up my reading MAIN
definition, though.
Does it work? Is it fast?
It works. It’s — it’s not fast by any means, but 3.8 seconds is much faster than 12. Again, there’s an API waiting for when I’m bored of abusing Joplin’s command line conveniences.
And maybe yesterday
Most of my deep dives into the journal will be from inside the Joplin app. A quick glance at yesterday’s notes could still be useful.
Of course a DateTime lets me ask for an earlier
DateTime.
For MAIN
I could add and match against a subcommand. I think instead I will adjust my top-level commands to reflect the most common cases.
And it works!
What about formatting?
Honestly? I’m not going to worry about it right now. Piping to Rich or Glow suffices when I want it pretty.
╔══════════════════════════════════════════════════════════════════════════════╗ ║ 2021-05-22T08:12:00-07:00 ║ ╚══════════════════════════════════════════════════════════════════════════════╝ Millie let me sleep in until 7:54. How gracious. Oh and last night's Joplin / Raku post got some legs. @liztormato even shared it on Reddit. That's cool. I always hope they like it when I post something about #RakuLang. ╔══════════════════════════════════════════════════════════════════════════════╗ ║ 2021-05-22T10:43:00-07:00 ║ ╚══════════════════════════════════════════════════════════════════════════════╝ My note script needs an option for "read yesterday's notes." ╔══════════════════════════════════════════════════════════════════════════════╗ ║ 2021-05-22T12:18:00-07:00 ║ ╚══════════════════════════════════════════════════════════════════════════════╝ Making sure that my Raku Joplin journaling script lets me add an entry. ╔══════════════════════════════════════════════════════════════════════════════╗ ║ 2021-05-22T12:55:00-07:00 ║ ╚══════════════════════════════════════════════════════════════════════════════╝ Raku Joplin journaling script, now with multi-dispatch! ╔══════════════════════════════════════════════════════════════════════════════╗ ║ 2021-05-22T14:05:00-07:00 ║ ╚══════════════════════════════════════════════════════════════════════════════╝ Guess I'm about ready to post the second Raku Joplin journaling post. Ah, the joys of hyperfocus. Better stretch my legs and get back to the official task list after.
The complete script
Backlinks
Got a comment? A question? More of a comment than a question?
Talk to me about this page on: mastodon
Added to vault 2024-01-15. Updated on 2024-02-02