In the last post, I implemented the config parsing portion of the CLI. In this part, I will tackle implementing the
stage
command to publish the CLI MVP version and fix a few bugs I’ve noticed early on.
By the way, I am writing this on Obsidian and am currently testing the look of the post on the local version of the website. So, writing this article will be a good session for finding new bugs and new improvement areas!
”Status” Update
I initially planned a list
command to show me the current state of my writing. When I started implementing it, I
noticed that the status
could have been a better name choice for what I wanted to show the user.
When we run the status
command, it shows this information:
A high-level version of the command is pretty predictable; it prints out the initial message, creates a writing list to show, and if that operation is successful, it prints the list
To keep the relevant information, I created a Writing
struct that holds all the necessary information. The path
,
title
and is_draft
are primarily used to show the information.
publish_date
is optional because I don’t always think of a date when I add an idea as a Writing to my vault. When I
start to work on it, I add a temporary one to keep myself accountable.
Implementation of Stage Command
The core functionality of the tool is the stage
command. There are certainly a couple of improvements we can make. But
I am happy with this initial implementation. Let’s go over the things we do in this command:
- We create a list to show to the user
- We let users select from the draft writings
- We then look for any asset related to this writing
- If there are, we transfer them to the target directory.
- We remove any undefined value from the frontmatter
- We add a
coverImage
section to the frontmatter if we add a header image file. - We convert any image added with Wikilink format to standard Markdown format.
Command function looks quite imperative in terms of the tasks we need to accomplish:
Selecting from drafts is done using the dialoguer
crate. After choosing a draft and getting a related asset list of that writing, we call the
update_writing_content_and_transfer
function. This function formats both the front matter and the content of the
writing. Frontmatter formatting options were not part of the initial implementation, but adding them was easy, so I
implemented them with an option to disable them from the config.
For example, add_cover_image
checks whether we have a header image in our asset list and if we have, it adds them to
the frontMatter. the format for the header image is <assetPrefix>-header
.
In the last part, since we tackled the frontmatter and content separately, we need to merge them. At this point, I decided to create a result file at the target location. This helped to make the happy path of this command idempotent.
Conclusion
It feels nice to write using this tool. It removes any friction of transferring a writing to my website for local testing. It was also an excellent excuse to try Rust for the first time. Even though it has a steep learning curve, defining errors out of existence is much easier than the other languages I worked with.
In the future, I might refactor the overall implementation and add testing to the project. I also consider adding
--continuous
flag to monitor the writing and update the version in the target folder on the fly.
References: