- Published on
Streamlining blogging using neovim
- Authors
- Name
- Luke Wood
Streamlining blogging using neovim
Recently, I've gotten into using neovim & other unix utilities to minimize friction across all of the things I regularly do. One thing I've always wanted to more of, but have always been to lazy to actually do, is blogging! In particular, I found that the friction of creating a new blog post was high enough to prevent me from wanting to do it. Often times I only have a few paragraphs that I'd like to write up, and it just doesn't feel worth it spending 10 minutes creating a new post.
Today I finally decided to remove this friction by writing a custom neovim plugin. The goal of this plugin is to allow me to switch from coding to blog writing in an instant, with absolutely zero friction. My hope is that this will make the cost of writing a blog post low enough that I do it much more often. At the time of writing, I haven't published a blog post in almost 2 years - ouch.
Neovim plugin overview
I'll spare you the details, but neovim plugins can mostly be thought of as single files of lua
that modify your neovim environment in some way. In this case, I think it would be really nice to be able to run :Blog
, enter a title, and be able to immediately start writing. By doing this all from my editor hopefully I can prevent myself from exiting what programmers often call "flow state" and be able to immediately jot down whatever it is that I'm hoping to share.
So, here's how I decided to tackle this. First, I created a file call blog.lua
:
# blog.lua
local M = {}
I know my filesystem structure, so I just hard coded a target directory for these posts:
local function get_root()
local home = os.getenv('HOME')
return home .. '/workspace/lukewood.github.io/data/blog'
end
Next, I needed a way to go from "Title" to "filename":
local function convert_title_to_filename(title)
local filename = title:lower()
filename = filename:gsub('[^%w%s]', '')
filename = filename:gsub('%s+', '-')
filename = filename:gsub('%-+', '-')
filename = filename:gsub('^%-+', ''):gsub('%-+$', '')
return filename .. '.mdx'
end
I strung together some neovim commands to read input after the command is run, create a buffer with the correct filepath assigned to it, template out my blog post, and focus the buffer:
function M.create_file_with_template()
local root_dir = get_root()
local title = vim.fn.input('Enter Title: ')
local filename = convert_title_to_filename(title)
if title == '' then
print('No filename provided. Aborting.')
return
end
local full_path = root_dir .. '/' .. filename
vim.cmd('enew')
vim.api.nvim_buf_set_name(0, full_path)
local current_date = os.date("%Y-%m-%d")
local template = {
"---",
"title: " .. title,
"date: " .. current_date,
"tags: []",
"summary: TODO",
"---",
"# " .. title,
}
vim.api.nvim_buf_set_lines(0, 0, -1, false, template)
end
and finally I bound it to a neovim command:
vim.api.nvim_create_user_command('Blog', M.create_file_with_template, {})
and voila - that's the entire plugin.
Demo
Here's the plugin in action:
Remaining friction
I'm pretty happy with this workflow for blogging - in fact without the plugin I never would've taken the time to write this post. One thing I really wanted to show off was how this all looks in the terminal. I used asciinema, which is nice - but I'd really like to be able to easily attach screen recordings to my blog posts. Unfortunately, recording, compressing and hosting videos is pretty annoying.
Looks like I'll have to tackle that another day...