Package: codeify
IntroductionCodeify is a pure Python code-generation utility for accelerating development in any platform / environment.Codeify's code generator processes an input directory and produces an output directory with similar structure
along with the aid of a provided specification file and Jinja templates for generated outputs.UsageCodeify should be used for development-only purposes.  This should not be tied into any critical processes
and should be seen only as a tool to speed up development.ExampleUsing a sample input directory with the following files:spec.yaml---
structs:
    Account:
        fields:
            id: { type: int }
            name: { type: std::string }

    CheckingAccount:
        fields:
            amount: { type: double }
        _extends: Account

    SavingsAccount:
        fields:
            amount: { type: double }
            interest_rate: { type: double }
        _extends: Accountmain.cpp.j2{% for name, value in structs.items() %}
#include "{{ name }}.h"
{% endfor %}

int main()
{
    // TODO: Implement
    return 0;
}class.j2#pragma once

namespace structs
{
    class {{ class_name }}{% if class_data._extends %} : {{ class_data._extends }}{% endif %}
    {
    private:
        {% for field_name, field in class_data.fields.items() %}
        {{ field.type }} {{ field_name }}_;
        {% endfor %}
    public:
        {% for field_name, field in class_data.fields.items() %}
        {{ field.type }} get{{ pascal_name(field_name) }}() const
        {
            return {{ field_name }}_;
        }

        void set{{ pascal_name(field_name) }}({{ field.type }} && value)
        {
            {{ field_name }}_ = std::move(value);
        }

        {% endfor %}
    };
}.codeify---
ignore: [ spec.yaml, class.j2 ]
generate:
{% for name, data in structs.items() %}
    {{ name }}.h:
        input: class.j2
        data:
            class_name: {{ name }}
            class_data: {{ data }}
{% endfor %}You can then run Codeify on the input directory ($INPUT) specifying both an output directory ($OUTPUT) and a specification file ($INPUT/spec.yaml):codeify generate -i $INPUT -o $OUTPUT -s $INPUT/spec.yamlYour output directory ($OUTPUT) should now contain the following files:Account.hCheckingAccount.hSavingsAccount.hmain.cppThe threeAccountheader files are generated fromclass.j2specified through a directory context file (.codeify).main.cppwas generated frommain.cpp.j2.
These were all generated with the use of thespec.yamlfile providing the inputs.Text InsertionCodeify supports in-place splicing lines into files when files cannot be generated but modified.Some example commands illustrate this functionality on imaginary files:# Insert immediately before a line
codeify insert "[ ] turn off the lights" --before "\[.\] close the door" -i TODO.txt

# Insert immediately after a line
codeify insert "(C) Beeblebrox Enterprises" --after "author: Zaphod .*" -i CONTRIBUTORS.md

# Append a line
codeify insert "rsync -rv $HOME/Pictures $BACKUP" -i backup_files.shCode generation on-the-flyFor generating code ad-hoc with some command line arguments, you can create a single Jinja template and define parameters on the command line to produce a
code-generated output.  This can be used for creating source code files or copy-pasting source code segments to an IDE or text editor.The example template file below and command line output demonstrates this feature:php.tpl{%- set php_fields = [] -%}
{%- for field in fields -%}
    {%- set _ = php_fields.append('$'+field) -%}
{%- endfor -%}
{%- if namespace -%}
namespace {{ namespace }};

{% endif -%}
class {{ class_name }}
{
    {%- for field in fields %}
    private ${{ field }};
    {%- endfor %}

    public function __construct({{ php_fields | join(', ') }})
    {
        {%- for field in fields %}
        $this->{{ field }} = ${{ field }};
        {%- endfor %}
    }
{% for field in fields %}
    public function get{{ (field[0] | upper) + field[1:] }}()
    {
        return $this->{{ field }};
    }
{% endfor %}
}From the command line:codeify echo php.tpl -d class_name=User -d "fields=[userId,username,passwordHash,name,email,activated]" -d namespace=AppThe following output is generated:namespace App;

class User
{
    private $userId;
    private $username;
    private $passwordHash;
    private $name;
    private $email;
    private $activated;

    public function __construct($userId, $username, $passwordHash, $name, $email, $activated)
    {
        $this->userId = $userId;
        $this->username = $username;
        $this->passwordHash = $passwordHash;
        $this->name = $name;
        $this->email = $email;
        $this->activated = $activated;
    }

    public function getUserId()
    {
        return $this->userId;
    }

    public function getUsername()
    {
        return $this->username;
    }

    public function getPasswordHash()
    {
        return $this->passwordHash;
    }

    public function getName()
    {
        return $this->name;
    }

    public function getEmail()
    {
        return $this->email;
    }

    public function getActivated()
    {
        return $this->activated;
    }

}Text ReplacementFor projects and source code that require mostly minor text changes (e.g. renaming a namespace), Codeify can be instructed to find and replace all instances of a string on a per-line basis within all files in a supplied directory.  All substitutions are provided either via Yaml file (in key-value form) or command line definitions (in "key=value" form).  The results are output into a separate directory.For example, the command linecodeify replace -i $INPUT/ -o $OUTPUT/ -d "::v1_1::=::v1_2::"will replace all instances of::v1_1::with::v1_2::in all files within the directory$INPUTand outputs the updated files in the same structure in the directory$OUTPUT.  Certain file names or types can be ignored if specified with the--ignoreargument for each pattern.An example with the--ignoreargument is below:codeify replace -i $INPUT/ -o $OUTPUT/ -d "flip=flop" --ignore "\*.bin"