Python-based development utilities
Project description
Introduction
Codeify 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.
Usage
Codeify 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.
Example
Using 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: Account
main.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.yaml
Your output directory ($OUTPUT
) should now contain the following files:
- Account.h
- CheckingAccount.h
- SavingsAccount.h
- main.cpp
The three Account
header files are generated from class.j2
specified through a directory context file (.codeify
). main.cpp
was generated from main.cpp.j2
.
These were all generated with the use of the spec.yaml
file providing the inputs.
Text Insertion
Codeify 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.sh
Code generation on-the-fly
For 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=App
The 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 Replacement
For 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 line codeify 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 $INPUT
and outputs the updated files in the same structure in the directory $OUTPUT
. Certain file names or types can be ignored if specified with the --ignore
argument for each pattern.
An example with the --ignore
argument is below:
codeify replace -i $INPUT/ -o $OUTPUT/ -d "flip=flop" --ignore "\*.bin"
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.