Just make it work

Working on projects, there are adhoc tasks that we need to run to complete a piece of work.

One place to describe these tasks is in the README. Then people wanting to try out the task, can just copy and paste the relevant command into a terminal.

Over time, people might create aliases, shortcuts or even simple shell scripts for these. I am in the shell script and/or alias camp and had tried using make previously, but could not get it to work in a satisfactory manner.

But then I came across just which is a handy way to save and run project-specific commands. Inspired by make, it allows one to specify recipes for these commands in a justfile. Each recipe has

  • a description,
  • a name and
  • the commands to run.

Here is a simple justfile with two simple tasks.

# Hello the world in 2025
 hello:
   echo hello world

# What is special about 2025
 check-2025:
   @echo "45² = 2025"
   @echo "(1³ + 2³ + 3³ + 4³ + 5³ + 6³ + 7³ + 8³ + 9³ ) = 2025"
   @echo "(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9)² = 2025"
                

Running just --list will show the recipes that can be run:

$ just --list
 Available recipes:
     hello      # Hello the world in 2025
     check-2025 # What is special about 2025
                

Then running just check-2025 will run the recipe:

$ just check-2025
 5²  = 2025
 (1³ + 2³ + 3³ + 4³ + 5³ + 6³ + 7³ + 8³ + 9³ ) = 2025
 (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9)² = 2025
                

By default, running just without any parameters will run the first recipe:

$ just
 echo hello world
 hello world
                

However just provides a way of specifying the default recipe to run. So a common practice is to make the default recipe list the available tasks.

@_default:
   just --list --unsorted

# Hello the world in 2025
 hello:
   echo hello world

# What is special about 2025
 check-2025:
   @echo "45² = 2025"
   @echo "(0³+ 1³ + 2³ + 3³ + 4³ + 5³ + 6³ + 7³ + 8³ + 9³ ) = 2025"
   @echo "(0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9)² = 2025"
                

And running just now shows what can be done.

$ just
 Available recipes:
     hello      # Hello the world in 2025
     check-2025 # What is special about 2025

                

Some of the great things about the project are that it is cross-platform, is actively maintained and has pretty good documentation.

Back again, ready for 2025

Once again, it is time to give this a go. I partake in a photography group, 52frames.com, where the idea is to use the camera and make a photo each week. It does not have to be a masterpiece. Rather the idea is to get the creative juices flowing i.e. look, see, feel, use the camera and then post process and publish.

To keep one motivated, it is encouraged to keep a streak going. Indeed, Yosef has been doing this since 2011.

So, with that practice working, I thought that I would try the same thing here. A fresh post a week and an attempt to get a streak going.

Working with lists of items in the Shell

Another useful idiom for command-line junkies to learn is

list-of-something | do-something-with-each-item
                

This can be expressed in a number of different ways. My go-to way is the following:

list-of-something | while read f;do do-something-with-each-item $f;done;
                

The real beauty is this can be built up incrementally, testing out the commands until one has got it right.

For example, to confirm the syntax of a the do-something-with-each-item, I prefix it with an echo to see what command is going to be run i.e.

list-of-something | while read f;do echo do-something-with-each-item $f;done;
                

If the list-of-something is very large or to confirm that I have the right subset of the list, I add some filters i.e.

list-of-something | grep something | head | while read f;do echo do-something-with-each-item $f;done;
                

The benefit of this incremental/iterative way of building up a command is that it is quick – up-arrow, edit the command and enter to try again.

The keystrokes to master and memorise are

while read f;do $f;done;
                

These are then embellished by adding a list-of-something | before the while, and an echo do-something-with-item before the $f.

Frequency counts in a Shell

For command-line junkies, a useful idiom to learn is

  list-of-something | sort | uniq -c | sort -nr
                

which will give a frequency count of list-of-something sorted in descending order.

e.g. to show the frequency count of the 4-starting-letters of words

  cat /usr/share/dict/words |\
     cut -c 1-4 |\
     sort | uniq -c | sort -nr |\
     head
                

which will show something like

  2043 over
  1334 unde
  1323 inte
  1078 anti
  1000 supe
   951 semi
   731 unco
   700 poly
   648 para
   618 peri
                

The classic story about this relates to Doug McIlroy and Donald Knuth More Shell, Less Egg

Vim – Capturing Output from Commands

One of the most useful things about Vim is its command-line mode. Using comamnd-line mode one can run external commands and capture the output and apply it to the buffer.

The external command is able to take text from the buffer, process it and replace the text.

Find checksum of lines of text

 :1,4 ! md5
 :% ! md5
                

Reformat JSON using jq

  :% ! jq .
                

One can also run an external command and have its output added to the current buffer.

Get list of files and insert into current buffer

  :. ! ls -latr
                

Capture output of a `curl` command and insert it into the current buffer

For example if one wants to insert the output from a curl command at the current line, one can do something like the following

  :. ! curl -s https://codeismandatory.com/about.html
  :. ! curl -s https://loripsum.net/api/1/plaintext
                

For more information, see the Vim help :he filter and :he :.

Back Again in 2019…

Time to get this show on the road again.

The to-write list is brimming with ideas. And I have a process that should work. But it is a matter of finding the time and commitment to put pen to paper and see what happens.

Reading the following two posts got me motivated again.

And of course then is Brian Harmer’s “Wysiwygpurple's Blog” where he talks about putting your hands on the keyboard and doing something. If I could do the something similar with my photography, that would be unreal.

But let’s get technology on the way first…

Good Teaching

Over the years I have come to appreciate the difference a good teacher makes. A good teacher is someone whose teaching affects the way you think and one you remember for life.

Recently, I had to create a mashup of photos and video. Previously for this type of task I used iMovie 9.0.9 (or was it iMovie ’11). Anyway I fired up the latest version of iMovie and, ughh, the interface had changed once again and become super simple, hiding or removing some useful functionality. I was too hassled to try and ‘discover’ it.

So I went and bought big brother Final Cut Pro X. Mainly because I already had bought some books on special and had a premium subscription to lynda.com

So I did the right thing and started working through the Final Cut Pro X 10.2 Essential Training with Ashley Kennedy . And this is the course that has inspired me to write about “Good Teaching”.

The thing about teaching a complex course is

  • the teacher has to have a thorough understanding of the material so that they can provide context, then drill down into the detail and then jump back out to an overview to provide context.

  • the course has be presented in a structured manner so that we can see over the overview and get to the actual detail quickly.

Not only does this course cover the details of Final Cut Pro X, but the way that Ashley does it is amazing. She works on two different video presentations, Chocolat and Letterpress. The primary aim of the course is to teach you how to use Final Cut Pro X. However the way she works on these two videos not only shows you how to use Final Cut Pro X, but also gives some insights in how to produce a video.

From coming up with a storyline, organising supporting material and then assembling the pieces together to provide final impact.

To cap it off, the actual video of the course is also fantastically done. If you want to get going quickly, Chapter 2: FCP X QuickStart provides this quick overview showing how one can get a video produced.

As a keyboard junkie, another hightlight for me was the extensive emphasis on keyboard shortcuts. Whenever, an action was done, the keyboard shortcut was mentioned and a flyout would show what key was being used.

The course is well structured and the transcript is also provided in the web version.

Vim – Running Commands on Matching Lines

Over the years I have used many editors. There was VM/CMS Xedit, Burroughs CANDE, ISPF/PDF editor, the IBM E, E2, E3 series of editors which influenced SlickEdit somewhat. There was a brief foray into PC editors including MultiEdit and the Borland C IDE. On OS X, I have used TextMate, SlickEdit, Sublime and now Vim.

One of the most amazing features in Vim is its command-line mode and bears similarity to that found in ISPF/PDF Editor, Xedit, SlickEdit and E series of editors. Instead of manipulating the content directly, one can issue commands to do the dirty work.

In particular the global command is really useful.

For example. given the poem below, assume that one wants to apply a change on all lines containing the word ‘was’, say uppercase the entire line

  Mary had a little lamb,
  His fleece was white as snow,
  And everywhere that Mary went,
  The lamb was sure to go.

  He followed her to school one day,
  Which was against the rule,
  It made the children laugh and play
  To see a lamb at school.
                

One could enter the following

 :g/\<was\>/ norm 0gU$
                

and end up with the following.

  Mary had a little lamb,
  HIS FLEECE WAS WHITE AS SNOW,
  And everywhere that Mary went,
  THE LAMB WAS SURE TO GO.

  He followed her to school one day,
  WHICH WAS AGAINST THE RULE,
  It made the children laugh and play
  To see a lamb at school.
                

Basically this can be read as “For every line that contains the word was (g:/\<was\>/, execute a series of normal mode commans (norm) i.e. go to the beginning of the line (0) and then upper case to the end of the line (gU$)”.