Skip to content
A simple cross language struct and enum file generator.
Nim TypeScript Python
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
docs
examples
src
.gitattributes
.gitignore
.plzconfig
LICENSE
README.md
mkdocs.yml
pleasew
requirements.txt
wings.nimble

README.md

wings

A simple cross language struct and enum file generator. (You might want to use a linter with this to clean up some trailing whitespaces and uneven tabbings.)

Requirements

*Note: Replace plz with ./pleasew if you do not have please installed.

Supported languages

Supported types

wings Go Kotlin Nim Python TypeScript
int int Int int int number
str string String string str string
bool bool Boolean bool bool boolean
date time.Time Date - date Date
[]type []type ArrayList<type> seq[type] list []

!!! info Unsupported types are initialized as custom struct / classes unless specified otherwise.

!!! warning "Nim date" It is currently unsupported since I haven't figure out how to parse ISOString time properly from string in Nim.

Run plz run //src/main:wings -- "{filepath}" to generate the files.

!!! warning "Issue with nimble" I also have a task made for nimble (nimble genFile "{filepath}") but its currently broken for the latest version (see official issue here). If you have an older version of nimble, it should work as intended.

Struct

Input file:

go-filepath classroom
kt-filepath another
nim-filepath folder
py-filepath python
ts-filepath some/files

go-import time
go-import homework:path/to/homework
kt-import java.util.ArrayList
nim-import times
py-import datetime:date
ts-import { IWingsStruct }:wings-ts-util
ts-import Homework:path/to/Homework

py-implement People
ts-implement People

# Any person who is studying in a class

Student {
    id          int          -1
    name        str
    cur_class   str
    is_active   bool         true
    year        date
    homeworks   []Homework
}

tsFunc(
    public addHomework(hw: Homework): void {
        this.Homeworks.push(hw);
    }
)

Output files:

/*
 * This is a generated file
 * 
 * If you would like to make any changes, please edit the source file instead.
 * run `nimble genFile "{SOURCE_FILE}"` upon completion.
 * 
 * Source: student.struct
 */

package classroom

import (    
    "time"
    homework "path/to/homework"
)

type Student struct {
    ID int `json:"id"`
    Name string `json:"name"`
    CurClass string `json:"cur_class"`
    IsActive bool `json:"is_active"`
    Year time.Time `json:"year"`
    Homeworks []homework.Homework `json:"homeworks"`
}

type Students []Student
/*
 * This is a generated file
 * 
 * If you would like to make any changes, please edit the source file instead.
 * run `nimble genFile "{SOURCE_FILE}"` upon completion.
 * 
 * Source: student.struct
 */

package another

import java.util.ArrayList

// Any person who is studying in a class
class Student {
    var ID: Int = -1
    var name: String = ""
    var curClass: String = ""
    var isActive: Boolean = true
    var year: Date = Date()
    var homeworks: ArrayList<Homework> = ArrayList<Homework>()

    fun toJsonKey(key: string): string {
        when (key) {
            "ID" -> return "id"
            "name" -> return "name"
            "curClass" -> return "cur_class"
            "isActive" -> return "is_active"
            "year" -> return "year"
            "homeworks" -> return "homeworks"
            else -> return key
        }
    }
}
# This is a generated file
# 
# If you would like to make any changes, please edit the source file instead.
# run `nimble genFile "{SOURCE_FILE}"` upon completion.
# 
# Source: student.struct

import json
import times

# Any person who is studying in a class
type
    Student* = object
        ID* : int
        name* : string
        curClass* : string
        isActive* : bool
        year* : DateTime
        homeworks* : seq[Homework]

proc parse*(student: var Student, data: string): void =
    let jsonOutput = parseJson(data)
    
    student.ID = jsonOutput["id"].getInt()
    student.name = jsonOutput["name"].getStr()
    student.curClass = jsonOutput["cur_class"].getStr()
    student.isActive = jsonOutput["is_active"].getBool()
    student.year = now()  # as you can see, this isn't working
    student.homeworks = jsonOutput["homeworks"].getElems()
# This is a generated file
# 
# If you would like to make any changes, please edit the source file instead.
# run `nimble genFile "{SOURCE_FILE}"` upon completion.
# 
# Source: student.struct

import json
from datetime import date

# Any person who is studying in a class
class Student(People):
    id: int = -1
    name: str = ""
    cur_class: str = ""
    is_active: bool = True
    year: date = date.today()
    homeworks: list = list()
    
    def init(self, data):
        self = json.loads(data)
/*
 * This is a generated file
 * 
 * If you would like to make any changes, please edit the source file instead.
 * run `nimble genFile "{SOURCE_FILE}"` upon completion.
 * 
 * Source: student.struct
 */

import { IWingsStruct } from 'wings-ts-util';
import Homework from 'path/to/Homework';

// Any person who is studying in a class
export default class Student implements People {
    [key: string]: any;
    public id: number = -1;
    public name: string = '';
    public curClass: string = '';
    public isActive: boolean = true;
    public year: Date = new Date();
    public homeworks: [] = [];
    
    public init(data: any): boolean {
        try {
            this.id = data.id;
            this.name = data.name;
            this.curClass = data.cur_class;
            this.isActive = data.is_active;
            this.year = new Date(data.year);
            
            if (data.homeworks !== "null") {
                this.homeworks = data.homeworks;
            }
        } catch (e) {
            return false;
        }
        return true;
    }
    
    public toJsonKey(key: string): string {
        switch (key) {
            case 'id': {
                return 'id';
            }
            case 'name': {
                return 'name';
            }
            case 'curClass': {
                return 'cur_class';
            }
            case 'isActive': {
                return 'is_active';
            }
            case 'year': {
                return 'year';
            }
            case 'homeworks': {
                return 'homeworks';
            }
            default: {
                return key;
            }
        }
    }

    public addHomework(hw: Homework): void {
        this.Homeworks.push(hw);
    }
}

The format of the fields goes from left to right in such order "field name", "field type", "field JSON name", and "initialize as" (optional, not used in Go and Nim).

*Note: There is no gurranttee that "initialize as" field goes through a proper conversion or localization based on the targetted output languages so ideally you want to make sure it works with all versions of output that will be using it.

Enum

Input file:

go-filepath path
kt-filepath to
nim-filepath some
py-filepath python
ts-filepath file/person

Emotion {
    Accomplished
    Angry
    Annoyed
    Appalled
    Excited
    Exhausted
    FeelsGood
    Frustrated
    Happy
    Meh
    Sad
    Satisfied
}
/*
 * This is a generated file
 * 
 * If you would like to make any changes, please edit the source file instead.
 * run `nimble genFile "{SOURCE_FILE}"` upon completion.
 * 
 * Source: emotion.enum
 */

package path

type Emotion int

const (    
    Accomplished = iota
    Angry
    Annoyed
    Appalled
    Excited
    Exhausted
    FeelsGood
    Frustrated
    Happy
    Meh
    Sad
    Satisfied
)
/*
 * This is a generated file
 * 
 * If you would like to make any changes, please edit the source file instead.
 * run `nimble genFile "{SOURCE_FILE}"` upon completion.
 * 
 * Source: emotion.enum
 */

package to

enum class Emotion {    
    Accomplished,
    Angry,
    Annoyed,
    Appalled,
    Excited,
    Exhausted,
    FeelsGood,
    Frustrated,
    Happy,
    Meh,
    Sad,
    Satisfied,
}
# This is a generated file
# 
# If you would like to make any changes, please edit the source file instead.
# run `nimble genFile "{SOURCE_FILE}"` upon completion.
# 
# Source: emotion.enum

type
    Emotion* = enum
        Accomplished,
        Angry,
        Annoyed,
        Appalled,
        Excited,
        Exhausted,
        FeelsGood,
        Frustrated,
        Happy,
        Meh,
        Sad,
        Satisfied,
# This is a generated file
# 
# If you would like to make any changes, please edit the source file instead.
# run `nimble genFile "{SOURCE_FILE}"` upon completion.
# 
# Source: emotion.enum

from enum import Enum, auto

class Emotion(Enum):
    Accomplished = auto()
    Angry = auto()
    Annoyed = auto()
    Appalled = auto()
    Excited = auto()
    Exhausted = auto()
    FeelsGood = auto()
    Frustrated = auto()
    Happy = auto()
    Meh = auto()
    Sad = auto()
    Satisfied = auto()
/*
 * This is a generated file
 * 
 * If you would like to make any changes, please edit the source file instead.
 * run `nimble genFile "{SOURCE_FILE}"` upon completion.
 * 
 * Source: emotion.enum
 */

enum Emotion{    
    Accomplished,
    Angry,
    Annoyed,
    Appalled,
    Excited,
    Exhausted,
    FeelsGood,
    Frustrated,
    Happy,
    Meh,
    Sad,
    Satisfied,
}

export default Emotion;

filepath

Basically the path location of where the generated file lives relative to where the build is ran (which if you use Please or Nimble as suggested, it will always be at the top level folder of this project - wings/).

If the namespace for a specific language is not defined, the file for that language will not be generated.

import

Usually the include or import statement required for some part of the file to work properly. (In this case, its mostly external classes or enums for custom typing.)

implement

In many occassion, your struct or object might be implementing a separate interface class. Use this to specify the class that it is implementing. (There is not support for this in go since it would already inherently associate your struct to the interface if you implemented all the functions and variables defined in the interface.)

{lang}Func

Specific functions for specific programming languages. Ideally, you should have a separate utility classes that do all the other operations. This is mostly designed to be used for defining functions in an interface that the struct / class is implementing.

You can’t perform that action at this time.