Giter VIP home page Giter VIP logo

genesis's Introduction

Genesis

SPM Git Version license

Genesis is a templating and scaffolding tool.

A Genesis template is a manifest of options and files written in yaml or json. Option values can be provided in various ways otherwise you will be interactively asked for inputs. Template files are written in Stencil. The list of files can make use of dynamic paths and be generated multiple times depending on the format of the input.

  • ✅ Template manifests in easy to read and write yaml or json
  • ✅ Template files written in Stencil templating language
  • ✅ Provide options via ENV, command line, file or interactively
  • ✅ Powerful command line interactivity with choices, lists and branching
  • ✅ Write dynamic file paths

The very simple example:

options:
  - name: project
    description: The name of the project
    question: What is the name of your project?
    required: true
    type: string
files:
  - template: project.stencil
    path: "{{ project }}.project"

And then run like this:

$ genesis generate template.yml
What is the name of your project? MyProject
Generated files:
  MyProject.project

Or you can provide the required options via arguments

$ genesis generate template.yml --options name:MyProject
Generated files:
  MyProject.project

Much more powerful templates are possible. See more complete documentation here

Installing

Make sure Xcode 13 is installed first.

$ mint install yonaskolb/genesis

Make

$ git clone https://github.com/yonaskolb/Genesis.git
$ cd Genesis
$ make

Swift Package Manager

Use CLI

$ git clone https://github.com/yonaskolb/Genesis.git
$ cd Genesis
$ swift run mint

Use as dependency

Add the following to your Package.swift file's dependencies:

.package(url: "https://github.com/yonaskolb/Genesis.git", from: "0.1.0"),

And then import GenesisKit. See GenesisKit for more information.

Usage

Run genesis help for usage instructions

Usage: genesis generate <templatePath> [options]

Options:
  -d, --destination <value>    Path to the directory where output will be generated. Defaults to the current directory
  -h, --help                   Show help information for this command
  -n, --non-interactive        Do not prompt for required options
  -o, --options <value>        Provide option overrides, in the format --options "option1: value 2, option2: value 2.
  -p, --option-path <value>    Path to a yaml or json file containing options

Providing options

Options will be passed to the template in the following order, merging along the way, with duplicate options overriding the previous ones.

1. Environment Variables

Set any environment variables before you call generate, or use already existing ones from your development environment

name="My Name" genesis generate template.yml

2. Options File

Pass a path to a json or yaml file with --option-file This can include more structures and complex data. For example:

name: MyProject
targets:
  - name: MyTarget
    type: application
  - name: MyFramework
    type: framework  

3. Options Argument

Pass specific options with --options like this

-- options "option1: value 2, option2: value 2"

4. Interactive input

Genesis will ask you for any missing options if they are required. You can turn off interactive input with --non-interactive.

5. Default value

Each option can have a default value which be used as a fallback.

Missing value

If an option is required and still hasn't received a value from anywhere, generation will fail.

Template

A genesis template is a yaml or json file that includes a list of options and files

Options

Options are structured input for the Stencil templates. They serve as documentation and allow for Genesis to interactively ask for input.

  • name: This is the name that is referenced in the template as well as the command line
  • value: This is the default value that will be used if none are provided. This can have Stencil tags in it
  • question: The question that is asked when asking for input. This can have Stencil tags in it
  • description: An extended description of the option and what it does
  • required: Whether this option is required or not for the template to generate. If it is not provided via the command line, option file, or input, generation will fail
  • type: This is the type of option. It defaults to string but can be any one of the following:
    • string a simple string
    • boolean a boolean
    • choice a string from a list of choices. Requires choices to be defined
    • array an array of other options. If child options are defined, if will be an array of options, otherwise it will split a string by command, removing any whitespace between
  • options: An array of child options. Used if the array type contains objects

Files

  • path: This is the path the file will be generated at. It can include Stencil tags to make it dynamic.
  • contents: A file template string
  • template: A path to a file template
  • copy: A path to copy. This can be a file or a directory
  • context: An optional context property path that will be passed to the template. If this resolves to an array, a file for each element will be created, using tags in path to differentiate them.
  • include: Whether the file should be written. This is a Stencil if tag without the braces. For example instead of {% if type == 'framework' %} you would write type == 'framework'

Stencil Templates

Each Stencil template has all the filters available in StencilSwiftKit, and has access to all the options. See Stencil for more info about tags.

Small example:

{% if name %}
name: {{ name }}
{% endif %}

GenesisKit

The library GenesisKit can be used to easily provide generation in your own tools.

import GenesisKit

// create a context
let context: [String: Any] = ["name": "hello"]

// create a template, either from a file or programmatically
let template = try GenesisTemplate(path: "template.yml")

// Create the generator
let generator = try TemplateGenerator(template: template)

// generate the files
let generationResult = try generator.generate(context: context, interactive: false)

// write the files to disk
try generationResult.writeFiles(path: "destination")

Contributions

Pull requests and issues are welcome

License

Genesis is licensed under the MIT license. See LICENSE for more info.

genesis's People

Contributors

aomathwift avatar guseducampos avatar janiduw avatar noppefoxwolf avatar yonaskolb avatar yutailang0119 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

genesis's Issues

Glob support

Would be great if you could glob paths like this. I am currently hacking on a workaround, will submit a PR if I get it working.

files:
  - template: "**/*.swift"

Feature -- allow for git repositories

As a user I want to be able to pass a git repository instead of a template.yml file so that I can maintain my own templates and make use of community templates.

use:

$ mkdir HappyDance && cd HappyDance
$ genesis generate https://github.com/thecb4/GenesisTemplate
  1. It should allow for http || https || git protocols
  2. It should download to a common folder
        // replace the standard path call with one that checks the string and does some work 
        // let templatePath = Path(self.templatePath.value).absolute()
        let templatePath = determinePath(from: self.templatePath.value)
    /**
      This method allows for the use of git repositories to hold templates in addition to passing in a flat template file.

      - Parameter from: The string passed in from the command line
      - Returns: Returns the Path of the template file

      ## Important Notes ##
      1. template.yml file should be top level of the git repository
      2. template repositories will be downloaded to a .genesis folder in users home (~) directory
      3. Each download replaces prior versions of the template

    */
    func determinePath(from: String) -> Path {

      if
        from.contains("http")  ||
        from.contains("https") ||
        from.contains("git")
      {

        do {

          let project = URL(string: from)!.lastPathComponent.components(separatedBy: ".")[0]

          let mkdirCommand  = try shellOut(to: "ls .genesis 2>/dev/null || mkdir .genesis", at: "~")

          print("removing existing template")
          let deleteCommand = try shellOut(to: "rm -rf .genesis/\(project)", at: "~")

          print("cloning repository")
          let cloneCommand = try shellOut(to: "git clone --verbose \(from)", at: "~/.genesis")

          return Path("~/.genesis/\(project)/template.yml").absolute()

        } catch {

          print(error)
          exit(1)

        }

      } else {

        return Path(from).absolute()

      }

    }

Array options arguments support

It would be great to be able to pass specific options array like this.
I am currently trying this implementation. If it goes well I will submit a PR.

If anyone has any other ideas on how to pass options, please let me know here.

-- options name: MyProject, targets.name: MyTarget, targets.type: application

or

-- options "name: MyProject, targets: [name: MyTarget, type: application]"

Is there any ways to continue to input options if needed?

I want to input some options if I want to input those. Is there any ways to do this?
For example, I want to generate such file if I want to use Firebase.

{% if firebase %}
FIREBASE_APP_ID = '{{ firebase.app_id }}'
FIREBASE_CI_TOKEN = '{{ firebase.ci_token }}'
FIREBASE_APP_DISTRIBUTION_GROUP = '{{ firebase.app_distribution_group }}'
{% endif %}

This feature may be able to be realized as single attempt of array input option, but I couldn't find how to input options only once.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.