Skip to content

A CLI tool to generate files and run commands from templates.

License

Notifications You must be signed in to change notification settings

filipesilva/gen

Repository files navigation

Gen

Gen logo

A CLI tool to generate files and run commands from templates.

It is intended to make it easy to create new custom projects and generate files within existing projects. Like rails new and rails generate, but generic.

$ gen from/here to/there --name foo
create  to/there/deps.edn
create  to/there/src/foo.clj
run     git init

Special thanks to jaide for the logo!

Install

You need babashka and bbin to install gen.

Then run bbin install https://github.com/filipesilva/gen.git. You should now be able to run gen --version and gen --help.

Usage

gen parses variables like {{name}} in file paths, file contents, and commands, then replaces them with the values you provided in CLI flags like --name foo.

To get started make a new template folder, and put a file with a template var there:

mkdir my-first-template
echo "Hello {{x}}!" > my-first-template/hello.md

Now you can use that template folder to generate new files:

$ gen my-first-template my-first-gen --x world
create  my-first-gen/hello.md

$ cat my-first-gen/hello.md
Hello world!

You can also use git repositories such as sources:

$ gen https://github.com/filipesilva/gen-license ./ --author "John Doe"
create  LICENSE

$ cat LICENSE
MIT License

Copyright (c) 2025 John Doe

Permission is hereby granted, free of charge, to any person obtaining a copy
...

In this example both "2025" and "John Doe" were templated, but we only provided a value for author. That's because gen comes with a few default vars that you can see in gen --help:

$ gen --help
...
Default vars:
  --dest-name            Defaults to last part of `dest`
  --date      2025-01-11 Current date as yyyy-mm-dd
  --year      2025       Current year
...

Filters

Parsing uses Selmer. Check the Selmer docs for advanced variable usage like {{name|capitalize}} filters and {% if condition %}yes!{% endif %} conditionals.

gen adds a few filters of it's own related to casing, courtesy of camel-snake-kebab:

  • pascal-case
  • camel-case
  • screaming-snake-case
  • snake-case
  • kebab-case
  • camel-snake-case
  • http-header-case

Snake case is especially useful for Clojure filenames. Use src/{{my-var|snake-case}}.clj to turn a foo-bar var into foo_bar.

Configuration

gen will look for configuration in gen.edn on the source directory. You can use these files to control gen and use extra functionality.

You can see help for the config format using gen --config-help. The defaults are:

{:root ""           ;; root for template files
 :vars {}           ;; default vars, e.g. {:author "me"}
 :cmds []           ;; run in shell after file generation, e.g. ["git init"]
 :default-alias nil ;; used if no alias is specified
 :aliases {}}       ;; aliases are extra sets of configuration that are merged on top

EDN is like JSON but better, and the norm in Clojure projects.

The :cmd key is especially useful to initialize git repositories and install project dependencies. For instance, https://github.com/filipesilva/gen-scratch has this gen.edn:

{:cmds ["git init"]}

Calling gen with this template will show the files created and the ran commands:

$ gen https://github.com/filipesilva/gen-scratch foo
create  foo/README.md
create  foo/deps.edn
create  foo/src/foo.clj
run     git init

Aliases let you have multiple configuration sets in a single configuration file. The https://github.com/filipesilva/gen-license template we used before has this gen.edn:

{:default-alias :mit
 :aliases
 {:mit       {:root "mit"}
  :eclipse   {:root "eclipse"}
  :unlicense {:root "unlicense"}}}

When we called gen https://github.com/filipesilva/gen-license . --author "John Doe" we didn't specify any alias. But since there was a :default-alias set to :mit we used the root folder in the :mit alias.

To use the :eclipse alias, add it at the end of source gen https://github.com/filipesilva/gen-license:eclipse. We don't need to provide a value for author because the eclipse license template does not use that var.

Multiple aliases stack on top of each other, and the resulting merged config will be used.

gen will also look for a ~/.gen-global.edn file where you can set names for sources and global default vars:

{;; shorthands e.g. `gen scratch app`
 :sources {:scratch "~/repos/gen-scratch"
           :license "https://github.com/user/license:mit"}
 ;; global defaults, local and cli vars will overwrite these
 :vars    {:name   "John Doe"
           :author "John Doe"
           :email  "[email protected]"}}

Now calling gen license . is the same as gen https://github.com/user/license:mit . --author "John Doe".

Usage in a existing project

Besides making new projects, gen can be used in a project you already have and where you want to make new files from project-specific templates, like rails generate.

Imagine you want to make unit tests with a default format.

Start by adding a gen.edn at the project root, and the template files:

{:default-alias :test
 :aliases
 {:test {:root "templates/test"}}}
;; templates/test/{{name}}_test_.clj
(ns {{name}}-test
  (:require [clojure.test :refer [deftest is testing]]))
  
(deftest missing
  (is false))

Now run gen test --name foo:

$ gen test --name foo
create  test/foo_test.clj

Notice how you didn't have to specify the source. test is the destination directory, and the default alias is :test. When you omit the source, gen will look up from the current dir for the first gen.edn that it finds and use that as the source.

You can use multiple aliases and use them on the source argument like gen :test test --name foo. This way you can make your own template library for your project.

Clojure library

You can use gen in your clojure projects to generate files.

(require '[filipesilva.gen :as gen])

(gen/generate {:source "from/here"
               :dest   "to/there"
               :root   "." ;; root within :source
               :vars   {:name "foo"}
               :cmds   ["git init"]
               :allow-missing false
               :overwrite false
               :dry-run false})

Development

You can install the local repo using bbin install .

bb test and bb e2e for testing.

Version is auto determined from the git repository

About

A CLI tool to generate files and run commands from templates.

Resources

License

Stars

Watchers

Forks

Packages

No packages published