Collecting my attempts to improve at tech, art, and life

CLI Journaling in Joplin with Raku

Tags: shell joplin raku-lang second-brain tools

Series: Journaling in Joplin With Raku

attachments/img/2021/cover-2021-05-21.png
the formatted output of my journal-reading one-liner

Let’s write a couple one-liners so I can journal in Joplin from the command line!

But why?

Journaling is great. Now I’m not talking about big name Bujo bullet journaling process. I mean getting a thought down quick before I lose it. Even better if I can get that thought down in a place where I can find it later.

I know there are loads of great journaling applications. And lots of great applications that support journaling generally. But I love my command line. Too many distractions in those apps.

Command line options exist. I could use one of the bazillion command line journaling tools. Okay. Maybe not a bazillion. A couple dozen, at least.

Those apps and tools are yet another interface, another set of rules. I already have Joplin handy. Besides desktop, mobile, and terminal applications, Joplin has a CLI. And an API, but I suspect I’ll get to that later.

With uncharacteristic restraint, today I choose to get better at the tools I have rather than installing a new one.

Adding a journal entry

joplin use Journal && joplin edit $(date --iso=minute)

GNU Date — from GNU Coreutils — gets us consistent timestamps, which simplify searching and filtering. --iso produces an ISO 8601 timestamp. Very handy. By default it prints the YYYY-MM-DD version of today’s date, but you can opt for more granularity.

$ date --iso=minute
2021-05-20T08:26-07:00

I plan to make frequent small notes, so minute feels like a good choice.

[!NOTE] use Journal? Yes, this came up. Had the Joplin terminal app open in one terminal while I added a journal entry in another terminal. Terminal app did some sort of state maintenance thing. Next thing I know I’m adding journal entries to “Nerd Notes.”

Since it doesn’t exist, joplin will ask for confirmation before creating it.

$ joplin use Journal && joplin edit $(date --iso=minute)
Note does not exist: "2021-05-20T08:26-07:00". Create it? (Y/n)

I’m okay with the confirmation request for now. That way I have fewer moments of accidentally creating entries.

Editing a journal entry

What about more of a diary?

Leave minute off the --iso argument if you prefer a tidy collection of daily pages to my big stack of notes.

joplin edit $(date --iso)

Now you’ll be editing the single entry for today’s date.

Reading journal entries

The best review path will be via the Joplin app itself. That way you can tag and edit.

But – if you just want a quick view of recent thoughts? That is something we can do from the command line.

This next bit gets a little fancy.

joplin use Journal \
  && raku -e '
    for qx{ joplin ls }.lines.sort {
      qqx{ joplin cat $_ }.subst(
        /^(<[\dT:\-]>+)/, { "# $0" }
      ).say
    }' \
  | python -m rich.markdown -

Let me stall for a second.

Pretty print with Rich

We already talked about joplin use Journal. Rich Markdown formats Markdown — Joplin’s default format — for rich display in a terminal. It can even run as a standalone application. I take advantage of that here to get a pretty view of my Joplin entries:

╔══════════════════════════════════════════════════════════════════════════════╗
║                            2021-05-20T08:26-07:00                            ║
╚══════════════════════════════════════════════════════════════════════════════╝


Getting an idea for a CLI journaling tool using Joplin as the backend

The logic would look something like this:

┌──────────────────────────────────────────────────────────────────────────────┐
 joplin use Journal                                                           
 joplin edit $(date --iso)                                                    
 # append "## $(date --iso=minute)"                                           
└──────────────────────────────────────────────────────────────────────────────┘

That's it, basically. There could be more functionality, such as reviewing the
log.

╔══════════════════════════════════════════════════════════════════════════════╗
║                            2021-05-21T09:00-07:00                            ║
╚══════════════════════════════════════════════════════════════════════════════╝

Alarm 07:00, stayed in bed as long as I could. Thanks to the dogs, that was 15
minutes. Oh well.

Got the Raspberry Pi 4 set up with Raspbian, and the 500GB external drive
attached. Thinking about package managers. I know Homebrew but I could maybe try
Nix. There's a post about using Nix on Debian.

╔══════════════════════════════════════════════════════════════════════════════╗
║                          2021-05-21T14:01:00-07:00                           ║
╚══════════════════════════════════════════════════════════════════════════════╝

Resuming productivity, or something like it.

╔══════════════════════════════════════════════════════════════════════════════╗
║                          2021-05-21T20:20:00-07:00                           ║
╚══════════════════════════════════════════════════════════════════════════════╝

I keep forgetting -sel clip when using xclip. Without that it doesn't go into
the easy copy buffer.

┌──────────────────────────────────────────────────────────────────────────────┐
 $ my-command | xclip -sel clip                                               
└──────────────────────────────────────────────────────────────────────────────┘

You can also use Glow if you want a standalone Markdown pretty printer. It works. Rich is already part of my toolkit, so I’ll keep using it.

Am I ready to explain myself?

Okay, I think I’ve stalled enough. That middle bit. That’s Raku.

for qx{ joplin ls }.lines.sort {
  qqx{ joplin cat $_ }.subst(
    /^(<[\dT:\-]>+)/,
    { "# $0" }
  ).say
}

I don’t often do one-liners. We’ll have to break it down into tiny pieces.

First, we need a sorted list of journal entries.

qx{ joplin ls }  # ask `joplin` to print note titles, saving the output
  .lines         # Split that output into lines, one per note
  .sort          # Sort those lines by note title

Things get unpredictable if I don’t sort notes myself. Joplin tends to sort notes by last activity. Thank goodness for ISO 8601, which is easily sorted:

2021-05-20T08:26-07:00
2021-05-21T09:00-07:00
2021-05-21T14:01-07:00
2021-05-21T20:20-07:00

Next, we need to do something with each of those note titles.

for qx{ joplin ls }.lines.sort { ... }

Well? The content of each note is important.

qqx{ joplin cat $_ }

qqx interpolates variables before asking the system to run your command. The variable being interpolated is our old friend $_, this time around standing in for whichever of those sorted lines we reached.

2021-05-20T08:26-07:00

Getting an idea for a CLI journaling tool using Joplin as the backend

The logic would look something like this:

```bash
joplin use Journal
joplin edit $(date --iso)
# append "## $(date --iso=minute)"
```

That's it, basically. There could be more functionality, such as reviewing
the log.

I want to print this out in the terminal. I need to massage it a little first. Even though the file is Markdown, the first line is the note’s unformatted title. It makes quick one-line notes easier.

But it also means if I want that first line to look significant, I need to do something with this:

2021-05-20T08:26-07:00

The most obvious fix to me? Turn it into a level one Markdown header.

# 2021-05-20T08:26-07:00

That’s a single .subst transformation.

qqx{ joplin cat $_ }.subst(  # in printed note
  /^(<[\dT:\-]>+)/,          # find the first line that looks like a timestamp
  { "# $0" }                 # and turn it into a Markdown header
)

Okay, I got a little lazy with the regular expression. But my brain was in one-liner mode. For a full script I’d probably spell it out more clearly.

The last step is to display the transformed note contents.

qqx{ joplin cat $_ }.subst(...).say

Or ask them to display themselves. However you want to think of it.

This whole thing would be rather clunky as a shell alias. I could add it as a function to my .bashrc.

jread() {
  joplin use Journal \
    && raku -e '
      qqx{joplin cat $_}.subst(/^(<[\dT:\-]>+)/, { "# $0" }).say for qx{ joplin ls }.lines.sort
    ' \
    | python -m rich.markdown -
}

Then again, maybe not. This should probably be a script. Check back in a few days.

[!NOTE] Oooh a cliffhanger! I have a working script already. What I don’t have much of is unallocated time. But hopefully yes! Soon. I did some cool stuff with multi MAIN in Raku that I’m desperate to show off.


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-01