Go generator to copy values from type to type and fields from struct to struct. Copier without reflection.

Overview

Copygen

GoDoc Go Report Card MIT License

Copygen is a command-line code generator that generates type-to-type and field-to-field struct code without adding any reflection or dependencies to your project. Manual-copy code generated by Copygen is 391x faster than jinzhu/copier, and adds no allocation to your program. Copygen is the most customizable type-copy generator to-date and features a rich yet simple setup inspired by goverter.

Topic Categories
Usage Types, Setup, Command Line, Output
Customization Custom Types, Templates
Matcher Automatch, Depth
Optimization Shallow Copy vs. Deep Copy, When to Use

Usage

Each example has a README.

Example Description
main The default example.
manual Uses the manual map feature.
automatch Uses the automatch feature with depth.
deepcopy (Roadmap Feature) Uses the deepcopy option.
error Uses templates to return an error (temporarily unsupported).

This example uses three type-structs to generate the ModelsToDomain() function.

Types

./domain/domain.go

// Package domain contains business logic models.
package domain

// Account represents a user account.
type Account struct {
	ID     int
	UserID string
	Name   string
	Other  string // The other field is not used.
}

./models/model.go

// Package models contains data storage models (i.e database).
package models

// Account represents the data model for account.
type Account struct {
	ID       int
	Name     string
	Password string
	Email    string
}

// A User represents the data model for a user.
type User struct {
	UserID   int
	Name     int
	UserData string
}

Setup

Setting up Copygen is a 2-step process involving a YML and GO file.

setup.yml

# Define where the code will be generated.
generated:
  setup: ./setup.go
  output: ../copygen.go

  # Define the optional custom templates used to generate the file.
  template: ./generate.go

# Define custom options (which are passed to generator options) for customization.
custom:
  option: The possibilities are endless.

The main example ignores the template fields.

setup.go

Create an interface in the specified setup file with a type Copygen interface. In each function, specify the types you want to copy from as parameters, and the type you want to copy to as return values.

/* Specify the name of the generated file's package. */
package copygen

/* Copygen defines the functions that will be generated. */
type Copygen interface {
  // custom see table below for options
  ModelsToDomain(models.Account, models.User) *domain.Account
}

Copygen uses no allocation with pointers which means fields are assigned to objects passed as parameters.

options

You can specify options for your functions using comments. Do NOT put empty lines between comments that pertain to one function. Options are evaluated in order of declaration.

Option Use Description Example
map from to Manual Field Mapping Copygen uses its automatcher by default.
Override this using map to set fields that will be mapped to and from eachother.
Regex is supported for from-fields.
map .* package.Type.Field
map models.Account.ID domain.Account.ID
depth field level Use a specific field depth. Copygen uses the full-field depth by default.
Override this using depth with regex and a depth-level integer.
depth .* 2
depth models.Account.* 1
deepcopy field Deepcopy from-fields. Copygen shallow copies fields by default.
Override this using deepcopy with regex.
For more info, view Shallow Copy vs. Deep Copy.
deepcopy package.Type.Field
deepcopy .* (all fields)
custom option Specify custom options. You may want to use custom templates.
custom options are passed to a function's options.
Returns map[string][]string (trim-spaced).
ignore true
swap false

View a reference on Regex.

Convert

In certain cases, you may want to specify a how a specific type or field is copied with a function. This can be done by defining a function with a convert option.

/* Define the function and field this converter is applied to using regex. */
// convert .* models.User.UserID
// Itoa converts an integer to an ascii value.
func Itoa(i int) string {
	return c.Itoa(i)
}

Command Line

Install the command line utility. Copygen is an executable and not a dependency, so use go install.

go install github.com/switchupcb/[email protected]

Install a specific version by specifying a tag version.

go install github.com/switchupcb/[email protected]

Run the executable with given options.

# Specify the .yml configuration file.
copygen -yml path/to/yml

The path to the YML file is specified in reference to the current working directory.

Output

This example outputs a copygen.go file with the specified imports and functions.

// Code generated by github.com/switchupcb/copygen
// DO NOT EDIT.

// Package copygen contains the setup information for copygen generated code.
package copygen

import (
	c "strconv"

	"github.com/switchupcb/copygen/examples/main/domain"
	"github.com/switchupcb/copygen/examples/main/models"
)

// Itoa converts an integer to an ascii value.
func Itoa(i int) string {
	return c.Itoa(i)
}

// ModelsToDomain copies a Account, User to a Account.
func ModelsToDomain(tA *domain.Account, fA models.Account, fU models.User) {
	// Account fields
	tA.Name = fA.Name
	tA.UserID = Itoa(fU.UserID)
	tA.ID = fA.ID

}

Customization

Copygen's method of input and output allows you to generate code not limited to copying fields.

Custom Types

Custom types external to your application can be created for use in the setup.go file. When a file is generated, all types (structs, interfaces, funcs) are copied EXCEPT the type Copygen interface.

type DataTransferObject struct {
  // ...
}

type Model interface {
  // ...
}

func New() {
  // ...
}

Templates

Templates can be created using Go to customize the generated code algorithm. The copygen generator uses the package templates Generate(*models.Generator) to generate code. As a result, this funtion is required for your templates to work. View models.Generator for context on the parameters passed to each function. Generator options are parsed from the YML configuration file. Function options refer to custom options. Any other option represents a field option.

Templates are interpreted by yaegi which has limitations on module imports (Pull Request Pending): As a result, templates are temporarily unsupported. The error example modifies the .yml to use custom functions which return error. This is done by modifying the .yml and creating custom template files.

Matcher

Copygen provides two ways to configure fields: Manually and using the Automatcher. Matching is specified in a .go file (which functions as a schema in relation to other generators). Tags are complicated to use with other generators which is why they aren't used.

Automatch

When fields aren't specified using options, Copygen will attempt to automatch type-fields by name. Automatch supports field-depth (where types are located within fields) and recursive types (where the same type is in another type). Automatch loads types from Go modules (in GOPATH). Ensure your modules are up to date by using go get -u .

Depth

The automatcher uses a field-based depth system. A field with a depth-level of 0 will only match itself. Increasing the depth-level allows its sub-fields to be matched. This system allows you to specify the depth-level for whole types and specific fields.

// depth-level in relation to the first-level fields.
type Account
  // 0
  ID      int
  Name    string
  Email   string
  Basic   domain.T // int
  User    domain.DomainUser
              // 1
              UserID   string
              Name     string
              UserData map[string]interface{}
  // 0
  Log     log.Logger
              // 1
              mu      sync.Mutex
                          // 2
                          state   int32
                          sema    uint32
              // 1
              prefix  string
              flag    int
              out     io.Writer
                          // 2
                          Write   func(p []byte) (n int, err error)
              buf     []byte

Optimization

Shallow Copy vs. Deep Copy

The library generates a shallow copy by default. An easy way to deep-copy fields with the same return type is by using new() as/in a converter function or by using a custom template.

When to Use Copygen

Copygen's customizability gives it many potential usecases. However, Copygen's main purpose is save you time by generating boilerplate code to map objects together.

Why would I do that?

In order to keep a program adaptable (to new features), a program may contain two types of models. The first type of model is the domain model which is used throughout your application to model its business logic. For example, the domain models of Copygen focus on field relations and manipulation. In contrast, the ideal way to store your data (such as in a database) may not match your domain model. In order to amend this problem, you create a data model. The data models of Copygen are located in its configuration loader. In many cases, you will need a way to map these models together to exchange information from your data-model to your domain (and vice-versa). It's tedious to repeateadly do this in the application (through assignment or function definitions). Copygen solves this problem.

Contributing

You can contribute to this repository by viewing the Project Structure, Code Specifications, and Roadmap.

Comments
  • Feedback: README

    Feedback: README

    I consider myself to be an experienced Go developer and have used various codegen tools in the past including SQLBoiler. I've been grappling with the issue of mapping data between different representations (structs) at different levels of an application, and came across both goverter and copygen.

    Copygen seems like it's solving the problem I want to solve, the way I want to solve it: CLI tool to generate zero-overhead mapping code between structs. Therefore I'm quite interested.

    I read through the README and I have some points of feedback and questions. They may or may not be palatable and I acknowledge I'm spouting off some opinions 10 minutes after finding your project, but first impressions from would-be users can have a certain value so please take it in that light.

    1. Looking at the README overall, I think a more simple onramp would be valuable. If you look at goverter it starts with a straightforward 1-to-1 mapping with identical field names and types, and the examples get more complex from there. In the copygen README, you're starting off with a 2-to-1 struct mapping, so off the bat I'm spending brain cycles trying to figure out how the made-up model objects are supposed to relate to one another, rather than just grokking the tool. I suggest cutting back the gradient so you start with an absolute rock-bottom example and take it up one piece at a time.
    2. Moving on, the README states that setup involves a .go file and a .yml file. That seems like perhaps excessive moving parts and setup for the most basic scenarios. The most vital component of the .yml file seems to be specifying input and output file names, but sane defaults could be used to allow things to "just work" with only the .go file. Perhaps it looks for copygen.go and copygen.yml by default, and generates copygen.gen.go? Thoughts?
    3. Moving on to the setup.go section, it makes sense until the statement Copygen uses no allocation with pointers which means fields are assigned to objects passed as parameters. This is confusing because the signature you show just above it is ModelsToDomain(models.Account, models.User) *domain.Account which I gather is creating a domain.Account and returning a pointer to it; it shouldn't be assigning to the objects that are passed as parameters. I am probably misunderstanding; a clarification or better wording would be valuable.
    4. On the options header:
      • I would suggest changing away from a table to a format that doesn't introduce line breaks, since said line breaks make it more difficult to visually parse the examples.
      • Suggest always showing fully concrete examples before showing examples that use regexes.
      • Instead of just saying map from to I would suggest map <from> <to> or similar, so it's easy to see what's literal and what's meant to be variable.
      • Suggest showing actual code examples for each of these so you can see how they work in practice.
    5. In the output of the first example, it seems like it copied the Itoa function. If I already wrote the function in one .go file, it doesn't seem like I'd need it defined again. I suppose if you're using a setup.go that's in one directory and putting your copygen.go in another directory, yes you'd need to move the bits over. But why not put it all in the same place and avoid that complexity?
    6. The Customization section is, at the risk of sounding whiny and negative, a little mind-boggling. I don't understand the use cases behind Custom Types or Templates. Okay, I see that you need to use Templates to add an error-return although that seems a little extreme, I believe such is available out of the box with goverter.
    7. Rather than jumping into deep customization, let's say I want to do a 1-to-1 struct mapping where a couple of the fields have different names and a couple have different types (int vs. int64 or int vs. string, let's say). I want to leverage copygen's automatic mapping for the most part and just provide a couple options, arguments, utility functions, what have you, to deal with the special cases. An example of this would be awesome.
    8. There's not really enough data given under Matcher, apparently there's manual methods and there's automatic methods. Examples and comparisons would be great.
    9. The depth example is hard to parse, I see that it's supposed to illustrate field depth but the indentation is a little confusing. I would suggest some curly braces so you get better delineation of where the sub-structs start and end. And then, actual code examples that perform mapping using the detailed example of depth that was just provided.

    Apologies if any of this comes across as harsh or entitled, it's not meant that way. I'm very interested in using a tool like copygen for my projects, and this one seems overall more powerful and flexible than goverter, but I find myself right away bouncing off of some confusions and perceived complexity, and I wanted to give some feedback on this.

    documentation 
    opened by tooolbox 9
  • Parser failure with alias imports

    Parser failure with alias imports

    Hey there! There is a failure when using aliased imports for certain model packages (see below). Removing the alias removes the shown error as well, albeit the conversion still doesn't work or me 😅 .

    I believe we make sure aliased imports work correctly, since many services have the same package name for their models

    Setup

    YML

    generated:
      setup: ./models/copygen.go
      output: ./models/mappers_gen.go
    
    

    Go

    THIS DOESN'T WORK

    package models
    
    import usermodels "github.com/..blahblah../users/models"
    
    type Copygen interface {
    	ModelsToDomain(usermodels.User) User
    }
    

    THIS DOES

    package models
    
    import "github.com/..blahblah../users/models"
    
    type Copygen interface {
    	ModelsToDomain(models.User) User
    }
    

    Output

    No output

    Error

    an error occurred while parsing the types of function "ModelsToDomain".
    an error occurred while searching for the top-level Field "User" of package "usermodels".
    the type declaration for the Field "User" of package "usermodels" could not be found in the AST.
    Is the imported package up to date?
    

    Generation

    paste any generated code here.
    

    Environment

    Operating System: OSX Copygen Version: 0.2.1

    edge case 
    opened by 3nvi 6
  • generate duplicate code

    generate duplicate code

    Please provide the following information.

    Setup

    YML

    generated:
      setup: ./setup.go
      output: ../copygen.go
    
    

    Go

    // setup.go
    
    package setup
    
    import (
    	"github.com/switchupcb/copygen/examples/oboe/domain"
    	"github.com/switchupcb/copygen/examples/oboe/model"
    )
    
    type Copygen interface {
    	ModelsToDomain(model.Adgroup, model.Campaign) domain.Adgroup
    }
    
    // domain.go 
    
    package domain
    
    type Adgroup struct {
    	ID   int64
    	Name string
    	Planning Planning
    	Promotion Promotion
    	ResourcePos ResourcePos
    }
    
    type Promotion struct {
    	PromotionType int32
    }
    
    type Planning struct {
    	PlanningID string
    }
    
    type ResourcePos struct {
    	PlacementIDs []string
    }
    
    // model.go
    
    package model
    
    type Adgroup struct {
    	ID           int64
    	Name         string
    	PlanningID   string
    	PlacementIDs []string
    }
    
    type Campaign struct {
    	PromotionType int32
    }
    
    

    Output

    Error

    Generation

    // Code generated by github.com/switchupcb/copygen
    // DO NOT EDIT.
    
    package setup
    
    import (
    	"github.com/switchupcb/copygen/examples/oboe/domain"
    	"github.com/switchupcb/copygen/examples/oboe/model"
    )
    
    // ModelsToDomain copies a Adgroup, Campaign to a Adgroup.
    func ModelsToDomain(tA domain.Adgroup, fA model.Adgroup, fC model.Campaign) {
    	// Adgroup fields
    	tA.ResourcePos.PlacementIDs = fA.PlacementIDs
    	tA.ResourcePos.PlacementIDs = fA.PlacementIDs
    	tA.Promotion.PromotionType = fC.PromotionType
    	tA.ResourcePos.PlacementIDs = fA.PlacementIDs
    	tA.ResourcePos.PlacementIDs = fA.PlacementIDs
    	tA.Promotion.PromotionType = fC.PromotionType
    	tA.Planning.PlanningID = fA.PlanningID
    	tA.Name = fA.Name
    	tA.ID = fA.ID
    
    }
    
    

    Environment

    windows: windows Copygen Version: v0.2.4

    edge case 
    opened by Jiang-Le 5
  • CopyGen v0.3

    CopyGen v0.3

    Version 0.3 will include the following changes:

    • [x] new method of Parsing
    • [x] Weird Edge Case Fix when using a lot of Conversion
    • [x] go/template template support from #9
    • [x] Ability to match by tags
    • [x] Ability to invoke automatch using automatch option.
    • [x] Getting closer to supporting third party module imports in interpreted templates.
    • [x] Logo

    BONUS

    • [x] integration tests
    • [x] programmatic usage
    • [x] parse every Go type including basic, array, slice, map, chan, interface, and func types (but not generate)

    Status Started on April 5, 2022. Expectation of completion on April 12, 2022 (as of April 10, 2022). Packaging attempted on April 12, 2022. Completed April 13, 2022.

    opened by switchupcb 3
  • Match fields by data from tag

    Match fields by data from tag

    Match fields by tags like it does the json tag. You must set the tag from which copygen should take fields aliases by writing

    // tag <structume_name> <tag_name>
    
    opened by f0mster 3
  • Feature: linter for github actions

    Feature: linter for github actions

    Hi!

    I've added golangci-lint for github actions. And fixed some linter issues.

    You can check linter run in my forked repo: https://github.com/RomanSerikov/copygen/runs/3771871892

    opened by RomanSerikov 3
  • matcher thinks that two types with same name from different files are the same type.

    matcher thinks that two types with same name from different files are the same type.

    Reproduce:

    add

    type StructType struct {
        A string
    }
    

    to examples/automatch/domain/domain.go and

    type StructType struct {
        B string
    }
    

    examples/automatch/model/model.go than add field FieldTypeA StructType to both files. After codegen you will get

    	tA.FieldTypeA = fA.FieldTypeA
    	tA.FieldTypeA = fA.FieldTypeA
    
    1. you will get two same lines
    2. types are not compatible.
    opened by f0mster 2
  • add Whitespace Linter

    add Whitespace Linter

    Hi @switchupcb!

    In this PR i've enabled the whitespace linter in golangci-lint config and fixed all issues.

    In my humble opinion this linter may increase code readability.

    Also made some changes in cli package and so on.

    Hope you'll like it :)

    opened by RomanSerikov 2
  • Parser: Collected Type Imports excluded from Collections

    Parser: Collected Type Imports excluded from Collections

    In the generated code below, mapping directly between types works correctly, but for the slice types it doesn't output the full import path.

    Setup

    YML

    generated:
      setup: ./setup.go
      output: ../copygen.go
    

    Go

    package copygen
    
    import (
    	"local/test/domain"
    	"local/test/models"
    )
    
    type Copygen interface {
    	MyModelToMyDomain(src *models.MyModel) *domain.MyDomain
    	MyModelsToMyDomains(src []*models.MyModel) []*domain.MyDomain
    }
    

    Output

    Generation

    // Code generated by github.com/switchupcb/copygen
    // DO NOT EDIT.
    
    package copygen
    
    import (
    	"local/test/domain"
    	"local/test/models"
    )
    
    // MyModelToMyDomain copies a *models.MyModel to a *domain.MyDomain.
    func MyModelToMyDomain(tM *domain.MyDomain, fM *models.MyModel) {
    	// *domain.MyDomain fields
    	tM.Foo = fM.Foo
    }
    
    // MyModelsToMyDomains copies a []*MyModel to a []*MyDomain.
    func MyModelsToMyDomains(tM []*MyDomain, fM []*MyModel) {    // <------ Error here: "undeclared name: MyDomain" (should be: domain.MyDomain)
    	// []*MyDomain fields
    }
    
    

    Environment

    Operating System: macOS Copygen Version: latest

    edge case 
    opened by dansimau 1
  • change write file mode

    change write file mode

    in mac m1:

    copygen -yml ./setup.yml
    ls -l
    

    show

    ➜  copygen git:(master) ✗ ls -l
    total 8
    --w-------  1 yoogo  staff  660  5 25 10:05 copygen.go
    drwxr-xr-x  3 yoogo  staff   96  5 25 09:25 domains
    drwxr-xr-x  3 yoogo  staff   96  5 25 09:25 models
    drwxr-xr-x  4 yoogo  staff  128  5 25 09:29 setup
    

    continue execute cat copygen.go:

    ➜  copygen git:(master) ✗ cat copygen.go
    cat: copygen.go: Permission denied
    

    but other pc no problem。。。。

    opened by yoogoc 1
  • Interpreter: Add ability to use multiple files in .go custom generator

    Interpreter: Add ability to use multiple files in .go custom generator

    Problem

    Separating files of a .go template file results in an error if a declaration cannot be found.

    Fix

    Determine how to interpret the entire package before calling func Generate(gen *models.Generator) (string, error).

    enhancement 
    opened by switchupcb 1
  • Error: the

    Error: the "type Copygen interface" could not be found in the setup file

    Please provide the following information.

    Setup

    YML

    # Define where the code will be generated.
    generated:
      setup: ./setup.go
      output: ./copygen.go
    
      # Define the optional custom templates used to generate the file (.go, .tmpl supported).
      # template: ./generate.go
    # Define custom options (which are passed to generator options) for customization.
    # custom:
    #   option: The possibilities are endless.
    

    Go

    package copygen
    
    import (
    	"demo/admin/adapters/reposit/dal"
    	"demo/admin/domain"
    )
    
    type Copygen interface {
    	Basic(user *domain.AgrUser) *dal.SysUser
    }
    

    Output

    Error

    the "type Copygen interface" could not be found in the setup file
    

    Generation

    
    

    Environment

    Operating System: windows 10 Copygen Version: 0.4.0 Golang Version : 1.19.4

    edge case 
    opened by pobearm 2
  • Copygen v0.5

    Copygen v0.5

    Version 0.5 will require the following changes.

    • [ ] implement https://github.com/switchupcb/copygen/issues/33
    • [ ] Options, Matcher, Generator: cast option for direct type conversions (as opposed to a convert function)
      • use go/types AssignableTo() function to add casting field (in a similar manner to map).

    The following changes would be ideal, but cannot be confirmed.

    • [ ] https://github.com/switchupcb/copygen/issues/30

    Status Not Started.

    ETA This target will be started when one of the following situations occur.

    • Copygen is sponsored with work time.
    • One of these features is needed in a library of significance.
    • 2023 Downtime (and https://github.com/golang/go/issues/20744 is fixed).
    opened by switchupcb 0
  • models: IsInterface doesn't work with named interfaces

    models: IsInterface doesn't work with named interfaces

    Problem

    The Field.IsInterface() function doesn't work for named interfaces. This occurs because — while parsing — named field's are deepcopied, then have their definition's replaced. Such that a string comparison of that definition (i.e NamedInterface[9:] == "interface") would return false. This function used to be resolved by checking a .Collection field (of models.Field), but that field was removed due to being unnecessary... until now.

    Solution

    Collection

    The previous .Collection field specifies which type of collection (f.IsPointer() || (f.IsArray() || f.IsSlice() || f.IsMap() || f.IsChan()) || f.IsFunc() || f.IsInterface()) the field is. This field was removed in a previous version because it was being used to account for the actual type definition of the field (i.e *Account where Definition == "Account" and Collection == *). Not only did this contribute to confusion, but it also made generating type-to-type code harder.

    Adding back the Collection field would not cause confusion anymore because it would not be used for any other portion of the code. However, expanding the purpose of this field to represent an Underlying type of the field may be more useful. Currently, there is no way to determine the underlying type of a field. As an example, a field id Number will have a Name=="id" and Definition=="Number"; Number is an alias to a string. However, there is currently no way to find more information about the underlying field string that Number represents.

    Underlying

    An Underlying field of a models.Field would represent the actual underlying type (in a models.Field object) if it exists. There is a distinction between the go/types Underlying() method and models.Field Underlying() method. In go/types, the underlying function represents a unique instance of a go/type, and can represent go/types that have underlying go/types (such that a "Named' type is nothing more than a go/types.Named type). In contrast, the models.Field underlying field represents a default type (in colloquial terms), which likely shares an instance with other default underlying types.

    To be specific, models.Field objects typically represent the copygen definition of a field: These objects are created in a context which always gives them a Name (either in the Copygen Interface function parameters func(to string) from string or as a field of other models.Field structs, etc). In contrast, the model.Field present in the Field.Underlying field would represent actual default types (basic types, map, struct, interface, category.go) which a user (developer) can use to determine more information about a field's Go Type.

    The objects contained in a .Underlying models.Field field should represent the same object when it represents the same Go type. As an example, id Number and word Word models.Field objects represent two different models.Field. However, since the underlying type of each models.Field.Definition is an alias (Number, Word) to a string, the Field.Underlying of each models.Field should point to the same object (which is a models.Field representation of a string).

    Thus, it would be expected for users who — for whatever reason — modify the Underlying field of a models.Field to also modify the .Underlying field of every other models.Field that references it. Otherwise, the user can always use field.Deepcopy() prior to modifying that field, if that is ever necessary.

    edge case enhancement 
    opened by switchupcb 1
  • Parser: Fix Free Floating Comments

    Parser: Fix Free Floating Comments

    Copygen allows developers to define types, structs, and more in its setup.go file and has no issues copying them to the output; except for comments. The Go AST makes it "very difficult to update the AST and retain correct comment place (from 2017)" and is not likely to change any time soon. As a result, Copygen sometimes generates free-floating comments (i.e multi.go). Copygen's comments are handled in its Parser. Feel free to use any necessary libraries or rewriting of the comment-parsing mechanism to fix this issue.

    help wanted 
    opened by switchupcb 0
Releases(v0.4.0)
  • v0.4.0(Jun 27, 2022)

    Copygen v0.4

    Copygen is a command-line code generator that generates type-to-type and field-to-field struct code without adding any reflection or dependencies to your project. Copygen v0.4 adds the ability to disable the matcher from the command-line and includes a number of patches for increased stability.

    Schema

    The schema has remained stable.

    Parser

    The ability to parse every Go type including basic, array, slice, map, chan, interface, and func types has been tested.

    The following issues in the parser have been fixed:

    • any issues regarding basic type-field parsing and matching.
    • any issues regarding composite, function, and complex types with packages.
    • any issues with collection types that use pointers.
    • any issues with duplicate variables names.
    • any issues with collected type imports being excluded from collection types.
    • any issues with custom option parsing.
    • permission errors on MacOS.
    • edge case where the setup file's package is the same as the output file's package, and the setup file uses definitions from the output file's package is handled.
    • potential mismatch of options to functions that are declared in non-alphabetical order.
    • caching has been refactored to prevent unintended behavior while also improving parsing performance.

    Cyclic Functionality Refactor

    In previous versions of Copygen, cyclic types were only partially parsed (as intended). In Copygen v0.4, cyclic types are FULLY parsed. This means that you must be sure to handle any circular pointers such as a field that contains a subfield, which is also contained in that subfield.Fields (or any of the subfield's subfields, etc).

    Matcher

    The matcher's stability has been improved with regards to typefield-matching. The matcher models a one-to-many relationship (one to-field to many from-fields).

    Generation

    Pointer semantics are fixed when pointers are copied to non-pointers. Imports are now resolved in the generated file's output: This feature is also supported in code generated by custom templates.

    Support for .tmpl generation is implemented and no longer in a beta stage. .go template support for third-party modules (in the template file itself; NOT the setup) is still awaiting a pull request. This may be fixed in v0.5 if gomacro's issues are fixed.

    For more information, read about Templates.

    Debug

    The debug method CountFields has been removed. Use field.AllFields to get the length of every field in a field (including itself) or field.Fields to get the length of the field's fields. In a similar manner, field.AllFields can be used to PrintFieldRelation between to-type and from-type fields. As a result, the method only directly compares the given field slices (as opposed to ALL subfields).

    Project Structure

    Example files are no longer included in the built copygen binary.

    Other

    Copygen has been mentioned in awesome-go. Copygen has been tested at scale in Disgo.

    Future

    Copygen v0.5 will focus on adding new options. For more information, check out the Roadmap. A bounty for an issue has been added: Claim a Reddit Gold by solving the issue with setup file declared free-floating comments.

    Missing Features

    Copygen is only "missing" one major feature (that is implementable through convert customization): Deepcopy. The ideal deepcopy option allows the user the from-fields that will be deepcopied using regex. Support for the deepcopy option may be added in v0.5.

    Disclaimer

    Copygen will be assigned with v1.0.0 when its functionality remains stable over two minor versions.

    Source code(tar.gz)
    Source code(zip)
  • v0.3.9(Jun 22, 2022)

    This patch fixes a potential mismatch of options to functions that are declared in non-alphabetical order and improves stability with regards to comment-parsing. Copygen outputs functions in their declared order, rather than alphabetical order (similar to versions prior to v3).

    Source code(tar.gz)
    Source code(zip)
  • v0.3.8(Jun 7, 2022)

  • v0.3.7(May 22, 2022)

  • v0.3.6(May 17, 2022)

    This release adds the ability to disable the matcher from the command-line using -xm or programmatically by setting Enviroment.DisableMatcher = true. In addition, examples (and its packages) are no longer included in the go install binary or go get module.

    Source code(tar.gz)
    Source code(zip)
  • v0.3.5(May 5, 2022)

  • v0.3.4(Apr 29, 2022)

    Parser

    This patch fixes any issues with collection types that use pointers. It also fixes an import-issue with an obscure, but possibly common case where the setup file's package is the same as the output file's package, and the setup file uses definitions from the output file's package. Cyclic type output is more intuitive due to parser refactoring.

    Generator

    Imports are now resolved in the generated file's output: This feature is also supported in code generated by custom templates.

    Source code(tar.gz)
    Source code(zip)
  • v0.3.3(Apr 28, 2022)

    The project has been updated to go 1.18.

    Parser

    This patch reimplements support for interfaces, fixes func parsing, and prevents any issues with cyclic types from occurring. Caching has been refactored to prevent unintended behavior, while also improving parsing performance. In addition, *all types have been tested: This means that there should be no more edge-cases regarding the current supported types. In other words, the ability to parse every Go type including basic, array, slice, map, chan, interface, func, and every combination in-between is supported.

    Matcher

    The matcher will match pointers of any type and handle their semantics. For example, using tb **bool and fb *bool will result in tb = &fb.

    Other

    Copygen has been mentioned in awesome-go.

    Source code(tar.gz)
    Source code(zip)
  • v0.3.2(Apr 25, 2022)

    Parser

    This patch fixes any issues regarding composite, function, and complex types with packages. It also fixes an duplicate variables names (added in the go/types parser refactor). As a result, there may be unknown issues regarding complex cyclic types. Support for interfaces is temporarily removed.

    Matcher

    This patch prevents a typefield's subfields from matching with another typefield's subfields, when that other typefield is already matched with the typefield itself. It also defines a one-to-many matcher behavior in relation to to-from fields (where a to-field can only have one match; from-field can have multple). This may have implications with regards to manual mapping which we will deal with on a case-by-case basis.

    Generator

    Pointer semantics are fixed when copying pointers to non-pointers.

    Source code(tar.gz)
    Source code(zip)
  • v0.3.1(Apr 23, 2022)

    This patch fixes any issues regarding basic type-field parsing and matching.

    Parser

    All types are officially supported.

    Generator

    • The .go generate template uses strings.Builder.
    • .tmpl base template requires refactor.
    • Template consistency throughout the application has been fixed.
    • The roadmap has been updated.

    Cyclic Functionality Refactor

    In previous versions of Copygen, cyclic types were only partially parsed (intended). Parsing cyclic types have been refactored such that cyclic types are now FULLY parsed. This means that the user must be sure to handle any circular pointers. For example, a field that contains a subfield, which is also contained in subfield.Fields (or any of the subfield's subfields...).

    Debug

    The debug method CountFields has been removed. Use field.AllFields to get the length of every field in a field (including itself) or field.Fields to get the length of the field's fields. In a similar manner, field.AllFields can be used to PrintFieldRelations between to-type and from-type fields. As a result, the method only directly compares the given field slices (as opposed to ALL subfields).

    Source code(tar.gz)
    Source code(zip)
  • v0.3.0(Apr 14, 2022)

    Copygen v0.3

    Copygen is a command-line code generator that generates type-to-type and field-to-field struct code without adding any reflection or dependencies to your project. Copygen v0.3 adds the ability to use the generator programmatically from any step of the program. Implement custom loaders, matchers, and generator functions, or pass .yml files similar to the command line interface.

    Schema

    The schema has remained stable and includes the addition of 2 new options: tag and automatch. The tag option allows you to match by tag, while the automatch option allows you to explicitly and/or selectivity invoke the existing automatcher. Go text/templates that use the .tmpl extension are now supported; with no extra effort required. Simply use them in the same way you would use a .go template.

    For more information, view the options table.

    Parser

    The ability to parse every Go type including basic, array, slice, map, chan, interface, and func types has been implemented.

    Matcher

    The matcher's stability has been an improved. Issues regarding fields with similar names/definitions resulting in duplicate fields have been resolved.

    Generation

    NEW to Copygen's generation capabilities is the ability to generate code using text/templates (.tmpl) AND generate code programmatically. Implement custom loaders, matchers, and generator functions, or pass .yml files similar to the command line interface. Get started by viewing the program example.

    .go template support for third-party modules (in the template file itself; NOT the setup) is still awaiting a pull request. This may be fixed in v0.4 if gomacro's issues are fixed. Otherwise, support for .tmpl generation is still in a beta stage.

    For more information, read about Templates.

    Project Structure

    The parser has been simplified with a go/types implementation. Options have been refactored and feature a better explanation in the Contributing Guideline.

    Other

    Copygen ranks highly for its keyword on search engines and is featured in this article: What Is Copygen?

    Future

    Copygen v0.4 will focus on stability improvements and an expansion of generation features for all parse-able types. For more information, check out the Roadmap.

    Missing Features

    Copygen is only "missing" one major feature (that is implementable through convert customization): Deepcopy. As stated in the last release, the ideal deepcopy option allows the user the from-fields that will be deepcopied using regex. Support for the deepcopy option requires improvements to the generator, which is the focus of v0.4. However, there is no guarantee that deepcopy will be implemented at that time.

    Disclaimer

    Copygen will not be assigned with v1.0.0 until its functionality is more solidified. A GPL License has been added, along with the ability to purchase license exceptions to support further development. This does not affect the ability for people to generate proprietary code, but does protect modifications to Copygen.

    For more information, read What Can I Do?

    Source code(tar.gz)
    Source code(zip)
  • v0.2.4(Oct 26, 2021)

    go install can't be used with directives so we must replace the interpreter fork with a harder version (that doesn't use replace in the go mod until it's implemented upstream.

    Source code(tar.gz)
    Source code(zip)
  • v0.2.3(Oct 19, 2021)

    This release provides full template support. Go modules may be unsupported.

    yaegi does not support Go modules in its current state. We've created a Pull Request upstream, but it's been assigned with a "longer-term" tag after a month. As a result, the repository uses an up-to-date fork in order to provide support for Go Modules in templates. If there are any bugs with template imports, please refer to https://github.com/traefik/yaegi/pull/1265.

    Source code(tar.gz)
    Source code(zip)
  • v0.2.2(Oct 17, 2021)

  • v0.2.1(Oct 9, 2021)

  • v0.2.0(Oct 5, 2021)

    Copygen v0.2.0

    Copygen is a command-line code generator that generates type-to-type and field-to-field struct code without adding any reflection or dependencies to your project.

    Schema

    The schema has changed compared to v0.1. Only configuration options (filepaths and custom generator options) are defined in the YML. The current schema is inspired by goverter with a few changes to increase the simplicity of the UI: The user modifies a .go interface to specify types rather than having to manipulate a YML.

    Supported options (convert, depth, map, custom) can be used without an indicator and in addition to external comments (which is kept with generated code). These can be used on convert functions and mapping functions which are defined in the setup.go file. External package types are supported by Copygen v0.2, as they were in v0.1.

    Users are able to create functions within the UI and have them kept along with generated code.

    Matcher

    The matcher has kept the same functionality but been simplified. All the fields (including subfields) will be collected for each type and compared. A map option will determine whether the automatcher is used or not.

    Generation

    Templates are still waiting on a Pull Request. We will consider using a working-fork if this isn't supported in the upstream library by v0.3.

    Project Structure

    The project has refactored its structure to better model the steps it takes in generating code. The majority of the complexity lies in the parser, which is updated when options are changed, or an edge-case (i.e channels, etc) is found. The documentation has been updated.

    Disclaimer

    Copygen — being 14 days old — is still in its early stages. As a result, it will not be assigned with v1.0.0 until its functionality is more solidified.

    Future

    Copygen is only "missing" one major feature (that is implementable through convert customization): Deepcopy. Ideally, the user is able to specify the from-fields that will be deepcopied. This information will be used at generation time (cli/generator -> templates/template.go) in order to generate the correct deepcopy code depending on a field's definition (i.e struct -> direct, int -> direct, slice -> loop, etc) and primitive sub-field definitions _(i.e int, string, etc subfield in struct). Support for the deepcopy option is already implemented: Only modifications to the generator are required.

    This feature may or may not be included in v0.3 which will be focused on stability through quality control (tests, workflows, edge-cases, etc).

    Allocation

    One other feature that may or may not be included is the addition of allocations when pointers aren't used on to-types. Including this feature is debatable because the user is always able to create a new type prior to calling a Copygen function. In contrast, adding allocation would only change the user's workflow by moving a variable's assignment (to catch the result of a Copygen function). Each method has little — if no — difference in performance. This feature would require a template change (or addition) equivalent to the deepcopy feature.

    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Sep 29, 2021)

    Copygen v0.1.0

    Copygen is a command-line code generator that generates type-to-type and field-to-field struct code without adding any reflection or dependencies to your project. This makes it 391x faster than the reflection based solution copier with the aim of also being faster to use. Copygen features an entire README, Project Structure, and Roadmap that will speed up the time it takes to be fully-featured.

    Schema

    Every code generation tool has its own schema. While some generators are able to use a specific layer as a single source of truth (i.e SQL, GraphQL, etc), this is harder to do due to the nature of copygen. The "schema" of copygen is defined partially in your code, and partially in a YML file that adds full fledged customization of generated code via converters (and templates once interpretation is available). As of now, we have a pull request ready to solve the template roadblock.

    Matcher

    Copygen features an automatcher that makes mapping domain models to data models take less time with an out-of-the-box solution. This AST-based automatcher supports depth and is not coupled with a specific loader. The YML provides the ability to manually map fields to other fields if preferred.

    Generation

    Copygen aims to be more customizable with its templates. Users will be able to use the Go language to create func-based template algorithms without having to fork the project. The user will be provided all the field information one is provided in the default program, with the ability to truly customize their program using custom options. For this reason, more examples are encouraged over focus on implementation because copygen is a tool for code generation, but doesn't define it.

    Project Structure

    The project has a general structure that aims to decouple functionalities with eachother. Models, Loaders, and Generators help with building the program piece by piece. Documentation is prioritized.

    Disclaimer

    Copygen — being 7 days old — is still in its early stages. As a result, it will not be assigned with v1.0.0 until its functionality is more solidified. Future minor version changes may be breaking._

    Source code(tar.gz)
    Source code(zip)
Owner
SwitchUpCB
SwitchUpCB
copy and paste across machines

Copy-paste across machines using GitLab Snippets as a storage backend. This is a simple CLI tool inspired by the usability of pbcopy and pbpaste or xc

Bradley Wood 111 Aug 29, 2022
simple clipboard copy for complex outputs

Terminal Clipboard Different from others terminal's clipboard coppiers, this one can copy complex and interminables commands like tail -f or outputs t

Daniel Kanczuk 0 Nov 5, 2021
Command line tool to copy images from a camera SD card to your hard drive

Command line tool to copy images from a camera SD card to your hard drive

Clay Dowling 0 Nov 26, 2021
Go-grep - A grep copy written in go

Work in progress running/bulding # run from file go run src/main.go -f sample.tx

Lucas Pinheiro 2 Aug 19, 2022
Idiomatic Go input parsing with subcommands, positional values, and flags at any position. No required project or package layout and no external dependencies.

Sensible and fast command-line flag parsing with excellent support for subcommands and positional values. Flags can be at any position. Flaggy has no

Eric Greer 815 Jan 1, 2023
A rich tool for parsing flags and values in pure Golang

A rich tool for parsing flags and values in pure Golang. No additional library is required and you can use everywhere.

ALi.w 14 Jan 25, 2022
A prediction program which analyzes given numbers and calculates new values

Guess-It-2 About This is a prediction program which analyzes given numbers and calculates new values. Usage To test the program, download this zip fil

null 0 Nov 30, 2021
This CLI tool sends HTTP GET requests and print MD5 hash values of the response's body

HTTP Body Hash Generator This CLI (Command Line Interface) tool sends HTTP GET requests and print MD5 hash values of the response's body. Usage You ne

Uğur Kınık 0 Feb 10, 2022
yq lets you read YAML files easily on the terminal. You can find key/values easily

yq yq lets you read YAML files easily on the terminal. You can find key/values easily. Motivation Reading yaml configurations for k8s file becomes ard

Farhan 3 Nov 2, 2021
Prompts users to enter values for required flags in Cobra CLI applications

Cobra Flag Prompt Cobra Flag Prompt prompts users to enter values for required flags. It is an extension of Cobra, and requires that you use Cobra to

null 1 Nov 13, 2021
A command line tool for filling missing metric values on Mackerel.

mackerel-null-bridge A command line tool for filling missing metric values on Mackerel. Description When sending error metrics, etc., you may be force

ikeda-masashi 0 Jan 11, 2022
Json-match - Command line util for matching values in a JSON input

json-match Match JSON input by specifying key and value > json-match -json '{\"p

Trond Boksasp 0 Jan 12, 2022
Are you programming and suddenly your stomach is rumbling? No problem, order your Ifood without leaving your favorite text editor ❤️

vim-ifood Você ta programando e de repente bateu aquela fome? Sem problemas, peça seu Ifood sem sair do seu editor de texto favorito ❤️ Are you progra

Felipe Volpone 4 Jun 2, 2022
Go library for detecting and expanding the user's home directory without cgo.

go-homedir This is a Go library for detecting the user's home directory without the use of cgo, so the library can be used in cross-compilation enviro

Mitchell Hashimoto 1.3k Jan 5, 2023
Godbolt console wrapper for easily execute local file without any security risk and compiler.

Godbolt CLI Godbolt console wrapper for easily execute local file without any security risk and compiler. Install Compile the source code and add to y

aiocat 1 May 22, 2022
Brian Strauch 292 Oct 5, 2022
🚀 Get Youtube Live stream chat feed without any authentication!

youtube-live-chat-downloader Fetches Youtube live chat messages with no authentication required. How does it work? The request for fetching live chat

Abhinav Raut 11 Oct 17, 2022
🏗️ Fetch a specific commit without any history (shallow depth w/o cloning)

shallow-fetch-sha ??️ For a given git repository and commit, fetch and checkout just that commit without any history. This can be extremely useful in

Rob Herley 0 Nov 27, 2021
Snippet CLI manger for quickly using code snippets without leaving the terminal

SnipKit - Snippet CLI manager This repository is still work in progress! SnipKit aims to paste code snippets from your favorite snippet manager into y

null 42 Dec 27, 2022