My daily driver for writing in markdown is Vim. That’s how I usually write updates on my blogs. That’s also how I prepare document for Caspershire Atlas (converted from markdown to dokuwiki format, thanks to pandoc
).
The only thing about writing markdown in terminal is that I can’t really see the preview of the product. With either Atom or VS Code, previewing document is easier because they both have built-in basic markdown viewer. So, can I come up with a solution?
I could, and I did.
Enter, a modular setup that depends on pandoc
, entr
, and browser-sync
.
brief introduction
But why? Why not just use VS Code or Atom or Sublime Text?
Well, why not. I like experimenting, and that’s how I ended up in grad school (spoiler alert: not half as fun as you would think).
So, here is the idea. Whenever changes being made on a markdown file, the program entr
detects it, and tells pandoc
to compile it into a HTML file, styled according a CSS, and hardcoded the output into an index.html
.
The second part is the browser-sync
, which is a HTTP server, spins a local HTTP server (localhost, port 9000) and live-reloads the browser every time it sees changes in the index.html
file.
The pandoc
part was adapted from my previous attempt with pandoc
. The CSS file I am currently using is also available here (the github.css
). I learned how to use live-reload from a Medium blog post written by Scott Vinkle.
installation
sudo apt install pandoc
sudo apt install entr
sudo npm -g install browser-sync
I know some people are bothered by the sudo npm
and they prefer to not use it with sudo. Fun fact: I am too lazy to make npm
invocation sudo
-less.
the initial setup: bash aliases
Since the pandoc
and the browser-sync
commands can be run single-line-ly, the simplest implementation would be shell aliases, which makes invoking commands less of a marathon for my fingers.
Because my shell session runs on fish
, here is how the aliases look like:
# run browser-sync with reload command
alias reload='browser-sync start --server --files index.html --no-notify --no-open --port 9000'
# run pandoc with pen command
function pen
find . | entr pandoc $argv[1] --smart --self-contained --css=/home/aixnr/.pandoc/github.css --highlight-style=haddock --output="index.html"
end
Note that if the shell session runs on bash
(so vanilla) or zsh
(a step towards being a rebel), the function declaration is going to look a little different.
Also note that I put the github.css
inside the directory ~/.pandoc/github.css
, where ~/
is the shortform for /home/aixnr
, where aixnr
is the username. I heard that it is always a good thing to hard-link things in script.
It works. Sort of.
I now can open a terminal session, run tmux
first, then invoke pen document-name.md
on one pane, then reload
on another pane. Oh, before I decided to go with reload
and pen
aliases, I ran a quick check to make sure no available binaries with the same name. This can be easily done by running which pen
or which reload
. If terminal returns nothing, then binaries with the aforementioned names do not exist.
This setup works, except, too many steps involved.
final product
Of course, a bash
script. I call this panda.sh
, because I was reminded by Azusagawa Kaede.
#!/bin/bash
# ------------------------------------
# A dead simple bash script by @aixnr
# Run 2 programs in parallel
# 1) pandoc with entr
# 2) browser-sync for live-reload
# ------------------------------------
find . | entr pandoc "$1" --smart \
--self-contained \
--css=/home/aixnr/.pandoc/github.css \
--highlight-style=haddock \
--output="index.html" &
browser-sync start --server \
--files index.html \
--no-notify \
--no-open \
--port 9000
Now, I can just run ./panda.sh document-name.md
and it works!
By the way, having more LOC (lines of code) is not necessarily bad. In fact, it is better to make it much more readable.
And, without a doubt, the next logical step was to put panda.sh
in $PATH
for global invocation. You don’t want to cast a magic spell that only works in a specific locale. You want to make it global!
extra note
I tried inotifywait
. I personally think that entr
is simpler, but I am open to learn how to properly unleash the power of inotify-tools
in the near future. It looks much more programmable to me.
Let me know on Twitter (@aixnr) if there is actually a much more obvious way to do this. Nevertheless, I am quite happy with the result.