I had a sleepless morning and decided to flesh out a Howzit feature I’ve been meaning to get around to. In case you’ve missed it, Howzit is my “Markdown makefile” tool that allows you to keep track of project notes, specs, and scripts in a convenient Markdown file that can be searched and neatly displayed, and can contain directives to execute project-related commands conveniently.

As of version 2.1.0, you can now define and name positional variables when creating a topic in your build notes. For example:

# My Project

## First Topic (var1, var2)

@run(cp "${var1}" "${var2}")

Defining Named Variables

As you can see above, you define the names in parenthesis after the topic title, and can then refer to them using ${NAME}. Then you can call howzit -r First Topic -- "changelog.md" "wiki/changelog.md" (arguments are passed after --, everything before that is a topic search string). Stupid example as it would take longer to type that out than a simple copy command is worth, but it’s very handy in larger scripts.

Using With @include()

Variables can be passed between topics when using @include() directives by adding square brackets at the end of the include topic title. So if I were going to call the above example from within another topic, I would use @include(First Topic [file1, file2]). Arguments are separated by commas. You can also use variables within the square brackets, so if the parent topic had already defined a variable (or set it in front matter), you could use @include(First Topic [${myvar1}, ${myvar2}]).

This is a change in behavior. Before arguments were only positional, and if the command line contained one or more arguments, they would be $1, $2, etc. for every topic. This new method allows a parent topic to take specific arguments and provide them as needed to included subtopics in the order that the included topic requires.

A big thing that this allows is the creation of reusable topics that perform a specific function which can be included by multiple parent topics. Changing the parameters of the @include directive within the parent topic will change the behavior of the nested snippet.

Providing Default Values (Optional Arguments)

You can add default values to any variable, making it optional, with var_name:DEFAULT VALUE. This works when defining variables in topic titles, e.g. ## TITLE (var1:changelog.md), or in a placeholder, e.g. ${var1:changelog.md}. The value after the colon can contain spaces, but there should be no spaces around the colon.

By the way, if you define metadata at the top of a build note, you would usually access the values with the [%key_name] syntax. Metadata values also become available as variables with the ${key_name} syntax and are populated before any command line arguments, so if they have the same name as a variable, they’ll serve as fallbacks if no argument is given (but only when using the ${key_name} syntax; command line arguments have no effect on the [%key_name] template rendering).

I detailed all of this on the wiki as well. Enjoy!

If you’ve already installed, just use gem update howzit (or brew gem update howzit if you’re using Homebrew’s brew-gem). If you haven’t started yet, check the project page, or the Getting Started wiki page for installation instructions.