20221117-as_a_matter_of_course.md (9030B)
1 This web log as been through a few iterations. First I used [Jekyll](https://jekyllrb.com/){target="_blank" rel="noreferrer"} on [Github Pages](https://pages.github.com/){target="_blank" rel="noreferrer"}, then I switched to [Hugo](https://gohugo.io/){target="_blank" rel="noreferrer"} using a docker container and [Gitlab's CI/CD](https://docs.gitlab.com/ee/ci/){target="_blank" rel="noreferrer"} pipeline, then finally the current setup. 2 3 I moved away from the docker container as the build started failing then I was hitting too many issues trying to get it working. In an effort to simplify everything I thought, why couldn't I write my entries in markdown then use [pandoc](https://pandoc.org/){target="_blank" rel="noreferrer"} to convert them to HTML? 4 ``` 5 pandoc -f markdown -t html -o new_entry.html new_entry.md 6 ``` 7 8 Sounds so easy. 9 10 The main script, [pyratelog.sh](https://git.pyratebeard.net/pyratelog/file/pyratelog.sh.html){target="_blank" rel="noreferrer"} does all the heavy lifting. When a new entry is published the script does some prep then runs `pandoc` to convert the markdown file to html. I use a template file so my markdown only has to be the main body of content. This is how the command looks in my script 11 12 ``` 13 pandoc -s \ 14 --template=./entry_template.html \ 15 --metadata title="${input_title}" \ 16 -f markdown \ 17 -t html \ 18 -o entry/${input}.html \ 19 entry/${input}.md 20 ``` 21 22 The `pyratelog.sh` script also sets the link on the main page as well as adding the entry to my _rss.xml_ file. 23 24 In order for the script to know when a new entry has been published I use `inotifywait` to watch for files in the _entry/_ directory 25 ``` 26 inotifywait -m -e create -e moved_to /var/www/html/entry/ | xargs -L 1 /var/www/html/pyratelog.sh 27 ``` 28 29 Over time I have included three more scripts to improve my writing workflow, [draft](https://git.pyratebeard.net/pyratelog/file/scripts/draft.html){target="_blank" rel="noreferrer"}, [preview](https://git.pyratebeard.net/pyratelog/file/scripts/preview.html){target="_blank" rel="noreferrer"}, and [publish](https://git.pyratebeard.net/pyratelog/file/scripts/publish.html). 30 31 ### clapperboard 32 The `draft` script will checkout a new or existing branch based on the name I pass it, the name will be the title of the entry. 33 ``` 34 # use arg as title and set entry file path 35 TITLE=$1 36 ENTRY="entry/${TITLE}.md" 37 38 # checkout the correct branch 39 git branch | grep ${TITLE} && \ 40 git checkout -q ${TITLE} || \ 41 $(git checkout -q main && git checkout -q -b ${TITLE}) 42 ``` 43 44 It will then open up a new or the existing file with that same name in `vim`. 45 ``` 46 # if entry file does not exist yet touch it 47 [ -f "${ENTRY}" ] || touch "${ENTRY}" 48 49 # open entry file in favourite editor 50 vim "${ENTRY}" 51 ``` 52 53 Now I let my creative juices flow to produce more enjoyable content for you. 54 55 Once I have finished and close `vim`, the `draft` script continues by adding then committing the changes to `git` 56 ``` 57 # when vim closes add and commit the changes 58 # if there are any 59 git status | grep "${ENTRY}" || exit 0 60 git add "${ENTRY}" 61 git commit -S -m "${TITLE}" 62 ``` 63 64 ### advanced screening 65 The `preview` script was written as sometimes I like to see what the entry looks like in the browser, especially when I put pictures in. It is useful to read through in the browser as well, I have caught a number of spelling mistakes along with poorly worded sentences that way. 66 67 To do this the script creates a temporary directory, copies the entry in question, the template file for `pandoc`, and my custom CSS 68 ``` 69 # use arg as title and set entry file path 70 TITLE=$1 71 ENTRY="entry/${TITLE}.md" 72 73 # create a tmp dir 74 mkdir demo 75 76 # copy entry file, entry_template and css 77 # to temp dir 78 cp ${ENTRY} demo/index.md 79 cp entry_template.html style.css demo/ 80 81 # small change to entry_template for stylesheet 82 sed -i 's%\.\./%%' demo/entry_template.html 83 ``` 84 85 The same `pandoc` command is used to generate the HTML 86 ``` 87 # generate html file 88 pandoc -s \ 89 --template=demo/entry_template.html \ 90 --metadata title="demolog" \ 91 -f markdown \ 92 -t html \ 93 -o demo/index.html \ 94 demo/index.md 95 ``` 96 97 Using `busybox` the script starts a simple web server then waits for me to finish reviewing before killing the process and tidying up the temporary directory 98 ``` 99 # start web server and capture pid for later 100 busybox httpd -f -h ./demo -p 8080 & 101 busypid=$! 102 103 # open demo ENTRY file in browser 104 xdg-open http://localhost:8080 105 106 # wait until ready to stop web server 107 echo press any key to cancel 108 read -n 1 109 110 # kill the web server and remove temp dir 111 kill ${busypid} 112 rm -rf demo/ 113 ``` 114 115 Unfortunately this script didn't work on my phone while using [Termux](https://f-droid.org/en/packages/com.termux/){target="_blank" rel="noreferrer"} because `pandoc` is not available to install. As a workaround I started using [AnLinux](https://github.com/EXALAB/AnLinux-App){target="_blank" rel="noreferrer"} to give me a full Linux distro to work in. 116 117 ### it's a wrap 118 Finally I can run the `publish` script to send my entry out into the world. This is the simplest of the three scripts. It will rename the entry to prefix the date then merge the branch into the main branch before pushing to my git server 119 ``` 120 # use arg as title and set entry file path 121 # set published file path with date 122 TITLE=$1 123 ENTRY="entry/${TITLE}.md" 124 PUBLISH="entry/$(date +%Y%m%d)-${TITLE}.md" 125 126 # checkout the correct branch 127 git branch | grep ${TITLE} && \ 128 git checkout ${TITLE} || \ 129 git checkout -b ${TITLE} 130 131 # rename entry to set date 132 git mv "${ENTRY}" "${PUBLISH}" 133 134 # commit the rename as published 135 git commit -S -m "publish ${TITLE}" 136 137 # checkout main branch and merge published entry 138 git checkout main 139 git merge "${TITLE}" 140 141 # push new entry 142 git push 143 ``` 144 145 In my [last entry](20221111-what_the_hook.html){target="_blank" rel="noreferrer"} I spoke about using [git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks){target="_blank" rel="noreferrer"} on my git server to keep my wiki up to date. I use the same `post-receive` hook for my web log. 146 ``` 147 #!/bin/sh 148 ssh logserver "cd /var/www/html ; git pull" 149 ``` 150 151 The only thing I have to do after hitting publish is [toot about it](https://harbour.cafe/@pyratebeard){target="_blank" rel="noreferrer"}. I will be adding in an auto toot in the `publish` script soon, similar to my [weeklymusictoot](20221005-weeklymusictoot.html){target="_blank" rel="noreferrer"}, to save me having to even do that little job. 152 153 ### behind the scenes 154 Now because I [seem to like](20220124-make_believe.html){target="_blank" rel="noreferrer"} using Makefiles for running things I had a go at one for the `draft`, `preview`, and `publish` scripts. 155 156 It got a bit complicated with the arguments, but I was able to make it work, even setting it so that if I am already on the correct branch I don't have to pass any arguments 157 ``` 158 #TITLE := $(shell git branch --show-current) 159 RND := "" 160 # https://stackoverflow.com/a/14061796 161 # If the first argument is "draft" 162 ifeq (draft,$(firstword $(MAKECMDGOALS))) 163 # use the rest as arguments for "draft" 164 ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) 165 # ...and turn them into do-nothing targets 166 $(eval $(ARGS):;@:) 167 else 168 ifeq (preview,$(firstword $(MAKECMDGOALS))) 169 ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) 170 $(eval $(ARGS):;@:) 171 else 172 ifeq (publish,$(firstword $(MAKECMDGOALS))) 173 ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) 174 $(eval $(ARGS):;@:) 175 endif 176 endif 177 endif 178 179 ifeq ($(ARGS), ) 180 ARGS := $(shell git branch --show-current) 181 endif 182 183 prog: # ... 184 # ... 185 186 .PHONY: draft preview publish 187 188 draft : prog 189 scripts/draft $(ARGS) $(RND) 190 191 preview : prog 192 scripts/preview $(ARGS) 193 194 publish : prog 195 scripts/publish $(ARGS) $(RND) 196 ``` 197 198 As an example, to start a new entry I incant 199 ``` 200 make draft as_a_matter_of_course 201 ``` 202 203 An empty buffer is opened in `vim` so I can start writing. After some time I decide I need a break so I save and exit `vim`. When I come back I know I am already on the *as_a_matter_of_course* branch so I can incant 204 ``` 205 make draft 206 ``` 207 208 Once the entry is finished I save and exit `vim` then incant 209 ``` 210 make preview 211 ``` 212 213 After reviewing the finished piece I can incant 214 ``` 215 make publish 216 ``` 217 218 These three scripts have sped up my writing process as well as making it even easier to switch between drafts if I have more than one entry in the works at a time. 219 220 One issue that I have had to overcome, it's a big one, is that I need to think of the title before I start the draft. A few of my previous entries have had working titles right up until the moment they are published. I have thought about adding in a step to the publish script to change the title before it goes out, but for now I will force myself to think harder about the titles. 221 222 There are still some tweaks and improvements I want to look into but I have been happy with this process since I created it, adding in the additional scripts has helped a lot. It has certainly sped up my workflow and I haven't had any issues with the automated publishing, long may it last.