# TL;DR

**pbj** is a command line tool to generate sensible tdd software
development projects from declarative templates written in TOML.

***Typescript*** and ***Python*** project templates are built in. Just
[install](#_installation) it and go.

`pbj generate -t python PROJECT_NAME`

`pbj generate -t typescript PROJECT_NAME`

See the [Templates](#_templates) section for details on customization
and [Origin](#_origin) for why this tool exists.

# Installation

**pbj** is avaialable on <https://crates.io>. Source is available on
it’s github page: <https://github.com/electric-hand/pbj>.

Simplest installation is via cargo.

    cargo install pbj

# Commands

Currently there is only one command: `generate`.

`generate`  

Generate a project. Aliased to `g`.

the command  
-   parses and loads a `template` by name — **pbj** looks for a file
    named `<<template>>.toml` in a known set of [configuration
    folders](#_configuration)

-   adds production dependencies

-   adds development dependencies (if supported by your
    language/tooling)

-   runs any post generation commands specified

-   generates source, test and config files as declared in the template

examples  
-   `pbj generate -t python PROJECT_NAME`

-   `pbj g PROJECT_NAME` — using config file

High on my list of todos is a command for template skeleton generation
and a command to initialize a config with defaults.

# Configuration

**pjb** looks for a `config.toml` file (used for setting default
arguments) and template files in the following locations in the
following order. First one found wins.

The config dirs are system dependent and provided by the
[dirs](https://docs.rs/dirs) crate)

-   `$HOME_DIR/.config/pbj` — Added manually for macos users in a mixed
    environment

-   [Local Config
    Dir](https://docs.rs/dirs/latest/dirs/fn.config_local_dir.html)

-   [System Config
    Dir](https://docs.rs/dirs/latest/dirs/fn.config_dir.html)

-   [Built-ins](https://github.com/electric-hand/pbj/tree/main/templates)

Templates are looked for and loaded from the `templates` subdirectory in
the above config locations.

## config.toml

A simple config file that specifies default arguments. Defaults and
example can be found
[here](https://github.com/electric-hand/pbj/blob/main/default_config.toml).

### `[template]`

The default template to use. Provides a default for the `-t` or
`--template` argument to the `generate` command.

### `[prefix_separator]`

The string to use for prefix separation. Used if you provide a prefix to
your project via the `-p` or `--prefix` argument to the `generate`
command. Defaults to `_`

example  
`pbj g -p 1234 many_moons` will generate a project directory
`1234_many_moons` with the [$PROJECT\_NAME](#_project_name) set to
`many_moons`.

### `[variant]`

The file variant to use. Provides a default for the `-v` or `--variant`
argument to the `generate` command.

# Templates

## Custom Templates

A starter template can be copy/pasted from the github [templates
folder](https://github.com/electric-hand/pbj/tree/main/templates) or one
can be manually authored with he format below.

## Sections

### `[language]`

binary  
the executable binary used to 'run' the language. This is tested to
exist and be on the path.

version  
the version of the language required. NOT USED.

name  
user friendly name of the template. NOT USED.

### `[project]`

dependencies  
A list of runtime "production" dependencies.

dev\_dependencies  
A list of runtime "development" dependencies.

### `[project.tool]`

binary  
The project tool used for initialization, dependency management and
running tests.

### `[project.tool.commands]`

initialize  
Command for the `project.tool` that initializes a new project using the
`project.tool.binary`

add\_dependency  
Command and arguments to add "production" dependencies.

add\_development\_dependency  
Command and arguments to add "development" dependencies.

run\_tests  
Command to run unit tests.

### `[[project.post.commands]]`

A set of arbitrary commands to execute after the project initialization.
Pretty much allows you do whatever you like.

command  
the command to run.

args  
list of arguments to pass to the command above.

### `[code.directories]`

source  
the (relative to root) project directory to put the source code files
generated by the `[[code.source]]` files.

test  
the (relative to root) project directory to put the source code files
generated by the `[[code.test]]` files.

### `[[code.source]]`

files generated relative to the `source` directory in the
`[code.directories]` table. Follows the [file format](#_file_format)

### `[[code.test]]`

files generated relative to the `source` directory in the
`[code.directories]` table. Follows the [file format](#_file_format)

### `[[config]]`

files generated relative to the root directory. Follows the [file
format](#_file_format)

### file format

file  
the path to generate the file to (can contain folders). The path is
relative. The directory the path starts from varies.

variant  
an optional key used to generate variations of the template. If
specified on the command line, will override files with the same `file`
path. Files without a variant specified have an implicit variant of
`default`.

contents  
the contents to write to the file

## Variables

There is a preprocessing pass on the TOML that does ultra basic variable
substitution.

### `$PROJECT_NAME`

Any use of this special variable will be replaced by the project name
provided on the command line.

# Random Bits

## Leetcode support

One of the drivers for building this tool was a desire to work on
algorithmic/interview problems locally.

The intention is to use the prefix argument and `leet` file variant to
do so.

Example  
`pbj generate -p 1293 -t python shortest_path` generates a project that
correlates to the problem number but does not include the prefix in any
of the generated code. The files lend themseles to the leetcode format.

# Origin

I needed to do a ton of little projects (mostly coding katas, leetcode,
etc.) and had forgotten how to set up typescript projects from scratch
with:

-   good configuration

-   healthy layout

-   immediately runnable unit tests

There are other project generators out there — yeoman, npm-based create
scripts — but I don’t like how opaque they are. I wanted something fully
declarative with a readable project declaration.

This started as a super basic bashscript but then I wanted to jam on
python and after a copy past decided to do some better automation.
