We like quick answers to important questions
How many text formatting languages have I used for my Hugo site? For that matter, how many content files were written in each?
Mostly Markdown, with a fair chunk of reStructuredText and a little bit of Asciidoctor. Oh and one HTML source file, originally an Org-Jekyll experiment.
Okay that’s it. That’s the post, everyone. Time to go home!
Breaking it down
It helps me to understand the pieces I smash together in my one-liners. Read along if you like, or move on to more interesting topics. I don’t judge.
First off: why?
The Hugo static site generator supports multiple content formats. I use a few of them, which complicates my occasional urge to rebuild the whole site with something else.
If I know how my content formats are distributed, it will help me understand how much work I have cut out for me in The Eventual Inevitable Rebuild.
hugo list
Hugo’s list commands print a CSV list of your site’s content files. The content listed depends on which subcommand you use:
list all
- Everything! Well, except section indexes.
list draft
- Content with
draft: true
list expired
- Content with
expiryDate
in the past list future
- Content with
date
in the future
What does that output look like?
I could feed that to any language with a nice library for handling CSV files — which is most of them. Heck, I could feed it to Excel!
Now that I think to look, there’s the Awesome CSV list of tools and resources.
But no. Today I handed it off to the first tool that came to mind.
raku -e
Look, we’ve all been stuck at home for a bit. I need a break from Python. How about Perl’s sister language, Raku?
bag(…).say
bag
uses its arguments to create a Bag — basically, a set that gives each member a “weight” based on integer values. say
prints the gist
of the Bag, telling me what I need to know. The highest level view of this one-liner is “make a Bag and give me a general idea what it looks like.”
lines[1..*].map({ … })
Now I need to create that bag from hugo list all
. lines
called as
a routine creates a list of lines from $*ARGFILES
, which currently holds the piped output from my Hugo invocation. I don’t need the header line, so I use a
Range to slice the remaining lines.
map
applies a block to each of those lines, returning a new list to create our Bag. What’s going on in that map?
.split(",")[0].IO.extension
That leading dot? It’s an item context view of the topic variable handed to the block by map
. Yes, for folks who don’t feel like clicking: topic variable is Raku’s name for $_
, an easily abused blessing of Perl languages.
So the line of comma-delimited values is split
into values. Each line from Hugo’s CSV gets split
into a list of values, but I only care about the first one. The first value is the path to the content file itself.
Coercing that to an IO::Path object lets me ask for an extension
.
The block returns that extension, so when map
is all done it has a list of file extensions:
During initialization, the Bag counts how many times each extension appears in the list. Since the result of that tally is all I care about, I print it out.
Alternate versions
While I was learning more about my impulsive little invocation, I wondered about other ways to get the same information from Raku.
A bit more Perlish
All those method dots bother you? No problem. We can use them like plain old subroutines too. Course, we have to reach for $*SPEC
. This lower-level IO::Spec object understands file extensions on our platform.
Using Text::CSV
I know what to expect from Hugo’s CSV output, but what if I didn’t? I’d feed the standard input handle $*IN
to H. Merijn Brand’s Text::CSV module.
Though if I was being this careful, I’d probably also move away from a one-liner. But that takes us a long ways away from my original goal of getting a quick answer to an idle question.
Well, I satisfied my curiosity and understood a little more Raku. That was fun!
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