knit

module
v0.2.0-alpha Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 19, 2022 License: MIT

README

Knit

Knit is a code generation toolkit that simplifies the process of adding and maintaining custom code generators in any project.

Example

Here's an example of knit's usage with OpenAPI and template literals.

schema.yml

openapi: "3.0.0"
info:
  version: 1.0.0
  title: Example Codegen
paths:
  /pets:
    post:
      operationId: CreatePet
  /cars:
    post:
      operationId: CreateCar

example.go:

package example

/*
  Generates void functions for every endpoint

  @knit input ./schema.yml
  @knit loader openapi
  @knit template tmpl`
    {{ range $k, $v := .Paths }} 
      func {{ .Post.OperationID }}() error {
        return nil
      }
    {{end}}  
  `
*/
// @+knit
// @!knit

Now running knit example.go will update the file:

package example

/*
  Generates void functions for every endpoint

  @knit input ./schema.yml
  @knit loader openapi
  @knit template tmpl`
    {{ range $k, $v := .Paths }} 
      func {{ .Post.OperationID }}() error {
        return nil
      }
    {{end}}  
  `
*/
// @+knit

func CreatePet() error {
  return nil
}

func CreateCar() error {
  return nil
}

// @!knit

Annotations

Annotations in knit are used to identify code generator options and the output location of the generated code.

It takes a combination of both option annotations and codegen annotations to successfully use knit to insert generated code into a file.

Option Annotations

Options are defined on the opening annotations in the following format:

@knit <option> <value>

See below for a list of available options.

Codegen Annotations

The location in which the generated code is inserted into a code file is dictated by the open/close knit annotations:

// @+knit
  < code is generated here >
// @!knit
Annotation Parsing Algorithm

It may be helpful to understand how the parsing algorithm works when knitting multiple generators in one file.

The parser algorithm first splits the entire code file into blocks by the ending annotation: @!knit

It then loops over each block and uses regex to match and parse any generator options.

package test

func foo() {}
func bar() {}

// @knit input schema.yml
// @knit loader openapi
// @knit template ./file.tmpl
// @+knit

func Generated() { foo() }

// @!knit
//       ^ new "block" was split here

/// ... more code

/*
  Another generator definition entirely.
  This won't use the previously defined options.

  @knit input schema.yml
  @knit loader openapi
  @knit template tmpl`
    func Generated2 { bar() }
  `
*/
// @+knit

func Generated2() { bar() }

// @!knit

Options

Options allow you to define the behavior of your code generator in a series of key-value pairs.

@knit <option> <value>

All options support environment variable expansion. All $env variables starting with $ will be expanded before the option line is parsed.

input

The input option specifies the input file.

Relative paths to files are resolved using the directory in which knit has been executed.

Currently remote input loading is not available but is planned. Please see issue #5 for more details.

loader

The loader option specifies the loader used to load the input file.

Currently the only loader type is openapi

template

The template option specifies either a template file or template literal.

Currently the only supported template engine is the text/template package native to Go.

File
/*
  @knit input ./schema.yml
  @knit loader openapi
  @knit template ./relative/path/to/file.tmpl
*/

Relative paths to files are resolved using the directory in which knit has been executed.

Currently remote template loading is not available but is planned. Please see issue #5 for more details.

Template Literal
/*
  @knit input ./schema.yml
  @knit loader openapi
  @knit template tmpl`
    type Generated struct {
    {{ range $k, $v := .Paths }} 
        {{ .Post.OperationID }} string
    {{end}}
    }
  `
*/

Template literals are defined within backticks and must be prefixed with the extension of the file the template would otherwise be defined in.

As a rule of thumb, if a template literal exceeds 10 lines, it should probably be promoted to its own template file.

Currently, backticks within a template literal will break the option parser. See issue #10 for more details. As a workaround, please define the template in a file.

Demo

To demo knit, please clone the repository and run the following:

go run cmd/main.go -glob "./test/*.go"

Directories

Path Synopsis
pkg

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL