Skip to content
This repository has been archived by the owner on Mar 6, 2024. It is now read-only.

tomakado/projector

Repository files navigation

A flexible, language and framework agnostic tool that allows you to generate projects from templates. Projector has some builtin templates, but you also can use your custom templates.

Currently Projector is in active development stage, therefore breaking changes may occur.

  • Single binary, no extra dependencies
  • Builtin templates that allow you to start quickly
  • Simple template manifest format
  • Custom templates
  • Optional steps for flexibility

Go Reference Go Report Card Coverage Status License

Installation

There are two ways to get Projector right now:

  1. Get binary for your platform on Releases page
  2. Build Projector from source: go install github.com/tomakado/projector

Usage

Get general usage help with -h or --help flags:

❯ projector -h
A flexible, language and framework agnostic tool that allows you to generate projects from templates.
Projector has some builtin templates, but you can use your custom templates or import third-party templates
from GitHub.

Usage:
  projector [command]

Available Commands:
  completion  Generate the autocompletion script for the specified shell
  create      Create project using specified template
  help        Help about any command
  info        Show meta information about template
  init        Create template manifest in current directory (like `create projector` command)
  list        List builtin and cached templates
  validate    Validate manifest without performing actions (dry run)
  version     Display projector version

Flags:
  -h, --help      help for projector
  -v, --verbose   turn verbose mode on

Use "projector [command] --help" for more information about a command.

Create project

Create project with create command:

projector create go/hello-world --author "tomakado <hi@ildarkarymov.ru>" && \
								--name "my-awesome-app" && \
								--package "github.com/tomakado/go-helloworld" && \
							    ./hello-world/

where go/hello-world is template you want to use. You also can use custom manifest file by passing it with --manifest or -m flags.

Optional steps

Template may have optional steps omitted by default. Use -i or --i flags to include them:

projector create go/hello-world --author "tomakado <hi@ildarkarymov.ru>" && \
								--name "my-awesome-app" && \
								--package "github.com/tomakado/go-helloworld" && \
								--include=makefile,dockerfile
							    ./hello-world/

Use --all flag to include all optional steps:

projector create go/hello-world --author "tomakado <hi@ildarkarymov.ru>" && \
								--name "my-awesome-app" && \
								--package "github.com/tomakado/go-helloworld" && \
								--all
							    ./hello-world/

Listing available templates

List all available locally templates with projector list:

❯ projector list
go/hello-world
go/http

Getting info about template

Get a bit more info about concrete template with projector info [template]:

❯ projector info go/hello-world
go/hello-world@1.0.0 by tomakado
URL: https://github.com/tomakado/projector
Description: Basic program to get started with Go

Template validation

Validate custom manifest file with projector validate --manifest=[path-to-custom-manifest-file]:

❯ projector validate -m projector.toml
Manifest is valid ✅

Template debugging

Debug your template with --verbose flag:

❯ projector create go/hello-world -a "tomakado <hi@ildarkarymov.ru>" -n "my-awesome-app" -p "github.com/tomakado/go-helloworld" ./hello-world --verbose
2022/02/19 18:22:32 verbose mode is turned on
2022/02/19 18:22:32 using manifest name "go/hello-world" in embed fs
2022/02/19 18:22:32 initialized embedded fs provider
2022/02/19 18:22:32 working directory = "./hello-world"
2022/02/19 18:22:32 loading manifest "go/hello-world/projector.toml"
2022/02/19 18:22:32 [EmbedFSProvider] reading "go/hello-world/projector.toml" in "resources/templates/"
2022/02/19 18:22:32 parsing manifest
2022/02/19 18:22:32 validating manifest
2022/02/19 18:22:32 passing config and provider to new instance of *projector.Generator
2022/02/19 18:22:32 provider = *manifest.EmbedFSProvider, config = {WorkingDirectory:./hello-world ProjectAuthor:tomakado <hi@ildarkarymov.ru> ProjectName:my-awesome-app ProjectPackage:github.com/tomakado/go-helloworld Manifest:0xc0002a5960 ManifestPath:go/hello-world}
2022/02/19 18:22:32 initializing working directory "./hello-world"
2022/02/19 18:22:32 cd ./hello-world
2022/02/19 18:22:32 traversing manifest steps
2022/02/19 18:22:32 step "init go module and git repository", 1 of 2
2022/02/19 18:22:32 processing files
2022/02/19 18:22:32 extracting file template from "gitignore"
2022/02/19 18:22:32 [EmbedFSProvider] reading "go/hello-world/gitignore" in "resources/templates/"
2022/02/19 18:22:32 parsing file template
2022/02/19 18:22:32 rendering file
2022/02/19 18:22:32 saving rendered file to ".gitignore"
2022/02/19 18:22:32 parsing output path template ".gitignore"
2022/02/19 18:22:32 rendering output path template ".gitignore"
2022/02/19 18:22:32 mkdir .
2022/02/19 18:22:32 writing rendered file to ".gitignore"
2022/02/19 18:22:32 parsing shell script template "go mod init {{ .ProjectPackage }} && git init"
2022/02/19 18:22:32 rendering shell script
2022/02/19 18:22:32 executing shell script "go mod init github.com/tomakado/go-helloworld && git init"
2022/02/19 18:22:32 step "create project bootstrap", 2 of 2
2022/02/19 18:22:32 processing files
2022/02/19 18:22:32 extracting file template from "main.go.tpl"
2022/02/19 18:22:32 [EmbedFSProvider] reading "go/hello-world/main.go.tpl" in "resources/templates/"
2022/02/19 18:22:32 parsing file template
2022/02/19 18:22:32 rendering file
2022/02/19 18:22:32 saving rendered file to "main.go"
2022/02/19 18:22:32 parsing output path template "main.go"
2022/02/19 18:22:32 rendering output path template "main.go"
2022/02/19 18:22:32 mkdir .
2022/02/19 18:22:32 writing rendered file to "main.go"

Сustom template

You can just create file with name projector.toml and start filling, but Projector has template for... templates:

projector create projector --name="projector-demo" ./projector-demo

that generates file with following content:

name="projector-demo"
author="tomakado"
version="snapshot"
url="https://github.com/tomakado/projector-demo"
description="Enter your template description here"

[[steps]]
name="hello world"
shell="echo \"hello, world!\""

Also there is shortcut for it (you have to be inside target directory):

projector init

Manifest

Manifest is a file that describes how Projector should act to generate project. Projector uses TOML format to store manifest on disk.

Example:

name="go/hello-world"
author="tomakado"
version="1.0.0"
url="https://github.com/tomakado/projector"
description="Basic program to get started with Go"

[[steps]]
name="init go module and git repository"
shell="go mod init {{ .ProjectPackage }} && git init"
	[[steps.files]]
	path="gitignore"
	output=".gitignore"
	
[[steps]]
name="create project bootstrap"
	[[steps.files]]
	path="main.go.tpl"
	output="main.go"

The first, top-level section containing fields name, author, version, url, description is about meta information. Then manifest must contain at least one step. Step must have name and either list of files to generate or shell script to execute.

Reference

Manifest

Field Description
name Name of template. Required.
author Author of template. Required.
version Version of template. Required.
url URL of repository or website of template. Optional.
steps Array of steps. See step for more info. Required at least one step.

step

Step is self-sufficient action performed by Projector to generate project. Projector “executes” steps sequentially, one by one. Inside shell field text/template syntax is supported, so you can use values exposed to Template Context inside shell script.

Field Description
name Name of step. Required.
optional Defines if step is optional. If true step will be omitted if not included via -i flag. Optional. Default: false.
files Array of files to generate. See file for more info. Required if shell is not set.
shell Shell script to execute. text/template supported (see Template Context for more info). Required if files is not set.

file

File in terms of Projector manifest is something like task of following kind:

  1. Take file located at path;
  2. Render file content as template with Template Context;
  3. Render output path using output value;
  4. Put rendered file to rendered output path.
Field Description
path Path to source file. text/template supported in content (see Template Context for more info). Required.
output Template of output path for rendered file. See Template Context for more info. Required.

Template Context

Field Description
WorkingDirectory Current working directory. Usually folder where project is being generated.
ProjectAuthor Author of project.
ProjectName Name of project.
ProjectPackage Package name for project. E.g. in Go it would something like github.com/owner/module.
Manifest Reference to manifest. See Manifest for info.
OptionalSteps Slice of optional step names.

Backlog

There are some features I'd like to implement in Projector:

  • Use multiple templates to generate single project (e.g., for having separate templates for Dockerfile, frontend, “service” level, etc.)
  • Nice animated output of current step
  • User-friendly error messages
  • Import third-party templates from GitHub
  • Custom options in template context
  • Import third-party templates from any public or private git repository
  • Template caching
  • List local third-party cached templates
  • Support for file masks on input files declaration

Contribution

If you want to help to develop Projector, the're several options:

  • Create issue with problem you've met or any other kind
  • Submit PRs with bug fixes or new features, especially from backlog 😉

About

A flexible, language and framework agnostic tool that allows you to generate projects from templates.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages