clk

A very opinionated framework to ease the creation of command line interfaces

View on GitHub

wrapping the music player

Let’s imagine you want to use clk to control your musicplayer. Chances are there already exists some command line tool to do so and that you want to wrap it into clk to take advantages of aliases, parameters and flows.

On that case, you most likely will want to create a simple alias on top of exec.

For the sake of this example, let’s use this fake music control program and call it ‘mpc’.

if test "$1" = history
then
    printf '%s\n' Kind-of-Blue Bitches-Brew Kind-of-Blue Blue-Train Bitches-Brew
    exit 0
fi
echo "Running mpc with: $*"

Then, to use this program as a clk command, we could simply create an alias like this.

clk alias set music.play exec -- mpc play --random --use-speakers --replaygain
New global alias for music.play: exec mpc play --random --use-speakers --replaygain

Then, we can simple call this command.

clk music play MyAlbum
Running mpc with: play --random --use-speakers --replaygain MyAlbum

parameters and completion

We get the benefit of parameters, flow etc.

clk music play --repeat --set-parameter global
clk music play MyAlbum
New global parameters for music.play: --repeat
Running mpc with: play --random --use-speakers --replaygain --repeat MyAlbum

Of course, --set-parameter provides completion for the profile name. Here, only global is available since we don’t have a project.

clk music play --set-parameter g<TAB>
global

when one command is not enough

Chances are that, after some time, we realize that this command should be a little more complicated than wrapping a single executable. For instance, we could want to start some music server, then play some music.

We could do this with a more complicated alias.

clk alias set music.play exec mpc start-server , exec -- mpc play --random --use-speakers --replaygain
clk music play MyAlbum
Removing global alias of music.play: exec mpc play --random --use-speakers --replaygain
New global alias for music.play: exec mpc start-server , exec mpc play --random --use-speakers --replaygain
Running mpc with: start-server
Running mpc with: play --random --use-speakers --replaygain --repeat MyAlbum

As aliases grow, you may need to take a look at what it does to avoid getting lost.

You can call the alias command to do so.

clk alias show music.play
music.play exec mpc start-server, exec mpc play --random --use-speakers --replaygain

Note that showing the help of the command also gives that information.

clk music play --help|head -10
Usage: clk music play [OPTIONS] [COMMAND]...

  Alias for: exec mpc start-server , exec mpc play --random --use-speakers --replaygain

  The current parameters set for this command are: --repeat

  Edit this alias by running `clk alias edit music.play`
  Or adjust this command `clk alias set music.play exec mpc start-server , exec mpc play --random --use-speakers
  --replaygain`

Let’s take that first advice and add the step that waits for the server.

clk alias edit music.play

Your editor opens on the commands, one per line. Leave this in it.

exec mpc start-server
exec mpc wait-for-server
exec mpc play --random --use-speakers --replaygain
clk music play MyAlbum
Running mpc with: start-server
Running mpc with: wait-for-server
Running mpc with: play --random --use-speakers --replaygain --repeat MyAlbum

falling back to a real command

Even doing so, you may at some point want more control about what you are doing, like really waiting for the music server rather than asking it to, and you will have to fall back in a real command. Replacing this alias with a shell command is straightforward:

clk command create bash --replace-alias music.play
Erasing music.play alias from global settings

This command tries hard to have the same behavior as its original alias.

clk music play MyAlbum
Running mpc with: start-server
Running mpc with: wait-for-server
Running mpc with: play --random --use-speakers --replaygain --repeat MyAlbum

Now, we can change its content to do whatever complicated flow we like.

You can simply run clk command edit music.play and it will be open in the editor mentioned in the EDITOR environment variable.

If instead, you want to get the path of the command to open it yourself, you can simply ask for it.

clk command which music.play
./clk-root/bin/music.play

Note that it is also shown in the help of the command.

clk music play --help|head -10
Usage: clk music play [OPTIONS] [ARGS]...

  Description Converted from the alias music.play

  The current parameters set for this command are: --repeat

  Edit this external command by running `clk command edit music.play`
  Or edit ./clk-root/bin/music.play directly.

Positional arguments:

saying what the command takes

That command passes the whole line to mpc. Say what it really takes.

A:album:str:The album to play
F:--repeat:Keep playing it
args=()
if clk_true repeat
then
    args+=(--repeat)
fi
clk exec mpc start-server
clk exec mpc wait-for-server
clk exec mpc play --random --use-speakers --replaygain "${args[@]}" "$(clk_value album)"
clk music play Kind-of-Blue
Running mpc with: start-server
Running mpc with: wait-for-server
Running mpc with: play --random --use-speakers --replaygain --repeat Kind-of-Blue

playing it loud

Loud as well is two steps, so an alias again.

clk alias set music.loud exec mpc volume 100 , music play
clk music loud Kind-of-Blue
New global alias for music.loud: exec mpc volume 100 , music play
Running mpc with: volume 100
Running mpc with: start-server
Running mpc with: wait-for-server
Running mpc with: play --random --use-speakers --replaygain --repeat Kind-of-Blue

Tidying up, I unset music.pause, which I renamed long ago, and clk answers with the aliases I do have.

clk alias unset music.pause 2>&1
Usage: clk alias unset [OPTIONS] [ALIASES]...
error: Invalid value for '[ALIASES]...': invalid choice: music.pause. (choose from music.loud)

That one grows in its turn, and the album follows it into the command.

clk command create bash --replace-alias music.loud
clk music loud Bitches-Brew
Erasing music.loud alias from global settings
Running mpc with: volume 100
Running mpc with: start-server
Running mpc with: wait-for-server
Running mpc with: play --random --use-speakers --replaygain --repeat Bitches-Brew

the albums I played lately

mpc history gives the albums in the order they played, the same ones over and over. I want to see each of them once, in that order, and clk_drop_duplicate does exactly that. It comes with the other helpers of _clk.sh, the ones your bash commands source.

clk command create bash music.recent --description "The albums I played lately" \
    --body 'clk exec mpc history | clk_drop_duplicate'
clk music recent
Kind-of-Blue
Bitches-Brew
Blue-Train

coming back to it after a while

Time passes, I upgrade clk. My settings were written in json back then, and I had dropped a script of mine in the bin, music.shuffle.py, that I called with clk music shuffle@py. There was a music.volume.py as well, beside a music.volume of its own.

The first clk I run writes the settings in json5. The @ is gone, so it renames my script too, and it tells me what it cannot fix.

clk music play Kind-of-Blue 2>&1
warning: Profile in ./clk-root is obsolete. It has the version 8 and current version is 9. Migration started.
warning: Renaming music.shuffle.py into music.shuffle, so that it answers to music shuffle
warning: music.volume.py keeps its suffix, music.volume is taken
warning: music.volume@py names a script with the @ of an older clk, and nothing answers to it anymore
warning: mixer.py uses DynamicConfigBase, which is gone: expose_class does the same
Running mpc with: start-server
Running mpc with: wait-for-server
Running mpc with: play --random --use-speakers --replaygain --repeat Kind-of-Blue

My parameters followed the new name.

clk music shuffle
clk parameter show music.shuffle
warning: The command 'music.shuffle' has no documentation
shuffling
music.shuffle --seed 42