Contents

Gum for better shell scripts

Blogging

One of the many reasons I don’t blog regularily is the fact that it is not easy for me to do some necesary preparation tasks:

  • cd into content directory
  • create a folder
  • decide what laguage I want to use (en or pl)
  • create a file and add frontmatter or
  • use hugo new <path> which is better as it prepopulates frontmatter
  • update the frontmatter with description
  • use my tool to check what are the tags I used to assign to my posts so that I can reuse them (check go-lista-tagow(pl))

These tasks are tiny but very effective in growing in my mind as “stuff” I need to do first. In order to make hard things easy and build better habits I decided I need to minimize this friction and created a bash script that does this for me, asking questions as I go. And this bash script should be fun to run and use.

Gum

I thought gum from charmbracelet would be a good choice.

Instllation

I just installed the latest version with go install:

1
go install github.com/charmbracelet/gum@latest

Usage

I used several features in my script:

  • gum input for the title
1
title=$(gum input --prompt.foreground "#04B575" --prompt "Title: ")
  • gum choose for selecting the language and the tags (piped from my tag tool)
1
2
lang=$(gum choose "en" "pl")
tags=$("$blogroot"/tools/tags -p $blogroot --only-names | gum choose --limit 4)

I had some fun with converting a string with space-separated tags into a string of quoted coma-separated tags:

1
tagssplit=$(for i in "$tags"; do echo $i; done | awk '{for(i=1;i<=NF;i++) printf "\"%s\"%s", $i, (i==NF?"":",")}')

Effect

The effect is quite satisfactory :) Here is my blog.sh script for the curious:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# prepare filename 
blogroot="$BLOGROOT"
postsdirectory="$blogroot/content/posts"

# ask for title
title=$(gum input --prompt.foreground "#04B575" --prompt "Title: ")

# choose language
lang=$(gum choose "en" "pl")

# generate directory name for blog entry
date=$(date -I)
titlenospace=$(echo "$title"|tr ' ' '_')
entrydirname="$postsdirectory"/"$date"_"$titlenospace"

# generate full name based on language
fname="index.md"
[ "$lang" == "en" ] &&  fname="index.en.md"
[ "$lang" == "pl" ] &&  fname="index.md"
fullname="$entrydirname"/"$fname"

# allow to edit filename
edited=$(gum input  --prompt.foreground "#04B575" --prompt "Your blog filename: " --placeholder "$fullname" --value="$fullname")

# extract tags, allow to choose max 4
tags=$("$blogroot"/tools/tags -p $blogroot --only-names | gum choose --limit 4)
echo "tags: " $tags

# prepare textual tags comma separated
tagssplit=$(for i in "$tags"; do echo $i; done | awk '{for(i=1;i<=NF;i++) printf "\"%s\"%s", $i, (i==NF?"":",")}')
echo "tagssplit: " "$tagssplit"

# ask for description
description=$(gum input --prompt "Description: " --prompt.foreground "#04B575")
echo "description: " "$description"

# prepare content
# add support to series = ["Dart"] (tool/tag option extension is needed)

# full date for frontmatter
datetime=$(date "+%Y-%m-%d %H:%M")

# write frontmatter to temp file
for i in "+++" "title = \"$title\"" "date = \"$datetime\"" "tags = [$tagssplit]" "featuredImagePreview=\"image.png\"" "featuredImage=\"image.png\"" "description=\"$description\"" "+++"; do echo $i; done > /tmp/foo

# confirm and go create it!
echo "Will create file: " $edited
gum confirm && mkdir -p $(dirname "$edited") && touch "$edited" && echo $edited && (cat /tmp/foo > $edited) || echo "No files created"

VHS

One more idea: to show you how this script behaves, I’m using VHS program:

1
go install github.com/charmbracelet/vhs@latest

I just use the recording feature by running vhs record > cassette.tape and entering all commands.

Ehem, … well, it did not work.

Asciinema

So I installed asciinema from ubuntu package. I used asciinema to rpoduce .cast file:

1
asciinema rec blog.cast

I also compiled from sources a .cast to .gif encoder/generator called agg (installation instructions) using cargo:

1
cargo install --git https://github.com/asciinema/agg

and used it with

1
agg --speed 3  blog.cast blog.gif

which produced this beauty: