All Projects → sustrik → tiles

sustrik / tiles

Licence: other
Programmatic code generation

Programming Languages

python
139335 projects - #7 most used programming language

Projects that are alternatives of or similar to tiles

Dbcc
CAN DBC to C (and CSV, JSON and XML) compiler using the mpc parser combinator library
Stars: ✭ 142 (+82.05%)
Mutual labels:  code-generator, code-generation
Evolutility Ui Jquery
Model-driven Web UI for CRUD using REST or localStorage.
Stars: ✭ 164 (+110.26%)
Mutual labels:  code-generator, code-generation
Xcassetpacker
A command line tool for converting a folder of images into an .xcasset package for Xcode
Stars: ✭ 150 (+92.31%)
Mutual labels:  code-generator, code-generation
kube-code-generator
Kubernetes code generator docker image
Stars: ✭ 60 (-23.08%)
Mutual labels:  code-generator, code-generation
EasyEE-Auto
EasyEE 自动化代码生成器。EasyEE Automated code generator.
Stars: ✭ 39 (-50%)
Mutual labels:  code-generator, code-generation
Toolkit
Collection of useful patterns
Stars: ✭ 137 (+75.64%)
Mutual labels:  code-generator, code-generation
Jennifer
Jennifer is a code generator for Go
Stars: ✭ 2,257 (+2793.59%)
Mutual labels:  code-generator, code-generation
Scala Db Codegen
Scala code/boilerplate generator from a db schema
Stars: ✭ 49 (-37.18%)
Mutual labels:  code-generator, code-generation
celerio
Celerio is a code generator tool for data-driven application.
Stars: ✭ 73 (-6.41%)
Mutual labels:  code-generator, code-generation
regen
Easy C++ reflection and code generation
Stars: ✭ 29 (-62.82%)
Mutual labels:  code-generator, code-generation
Geco
Simple code generator based on a console project, running on .Net core and using C# interpolated strings
Stars: ✭ 97 (+24.36%)
Mutual labels:  code-generator, code-generation
oag
Idiomatic Go (Golang) client package generation from OpenAPI documents
Stars: ✭ 51 (-34.62%)
Mutual labels:  code-generator, code-generation
Goreuse
Generic Code for Go
Stars: ✭ 93 (+19.23%)
Mutual labels:  code-generator, code-generation
Php Code Generator
PHP code generator library
Stars: ✭ 141 (+80.77%)
Mutual labels:  code-generator, code-generation
Mid
mid is a generic domain-specific language for generating code and documentation
Stars: ✭ 68 (-12.82%)
Mutual labels:  code-generator, code-generation
Swiftcolorgen
A tool that generate code for Swift projects, designed to improve the maintainability of UIColors
Stars: ✭ 152 (+94.87%)
Mutual labels:  code-generator, code-generation
Colfer
binary serialization format
Stars: ✭ 597 (+665.38%)
Mutual labels:  code-generator, code-generation
Dogen
Reference implementation of the MASD Code Generator.
Stars: ✭ 44 (-43.59%)
Mutual labels:  code-generator, code-generation
evon
Fast and versatile event dispatcher code generator for Golang
Stars: ✭ 15 (-80.77%)
Mutual labels:  code-generator, code-generation
WebApiToTypeScript
A tool for code generating TypeScript endpoints for your ASP.NET Web API controllers
Stars: ✭ 26 (-66.67%)
Mutual labels:  code-generator, code-generation

Tiles

Tiles is a simple Python module meant to help with code generation. It provides a way to work with rectangular areas of text as atomic units. This is particularly important if proper indentation of the generated code is desired.

  1. Import the module
  2. Tile literals
  3. Tile interpolation
  4. Combining tiles
  5. Joining many tiles
  6. Working with whitespace
  7. Worked example 1
  8. Worked example 2
  9. Worked example 3
  10. Notes

Import the module

from tiles import t, emptyln

Tile literals

Tile is a rectangular block of text.

Tile literal is t/ followed by a string. For example:

tile1 = t/"hello"

tile2 = t/'world'

tile3 = t/"""
          Hello,
            world!
          """

However, keep in mind that it's just the rectangular area of text that counts. All the surrounding whitespace is of no significance.

This makes it easy to align tile literals with the rest of the program. Given that the whitespace doesn't count, the literal can be shifted as much to the left or right as needed:

if x:
    for item in lst:
        tile = t/"""
                 Hello,
                   world!
                 """

Tile interpolation

Very much like string interpolation (F-strings), tiles allow to insert pieces of text into the template. To do so, use @{} syntax:

h = "Hello"
w = "world"
tile = t/"""
          @{h},
            @{w}!
          """
print(tile)

The output:

Hello,
  world!

However, unlike with F-strings, the interpolated pieces of text are treated as tiles (rectangular areas of text) rather than as simple strings:

h = "Hello"
w = t/"""
      cruel
      world
      """
tile = t/"""
          @{h}
            @{w}
          """
print(tile)

The output:

Hello
  cruel
  world

See "worked example 1" to get better undestanding of the tiling alorithm.

Combining tiles

While tile interpolation provides the most generic mechanism for combining tiles into larger tiles, sometimes you want just to put one tile besides another as quickly and simply as possible.

To achieve that, tiles support two convenience operators.

Operator + puts two tiles beside each other:

tile1 = t/"""
          Magenta
          Green
          """

tile2 = t/"""
          Red
          Blue
          White
          """

print(tile1 + tile2)

Results in:

MagentaRed
Green  Blue
       White

Operator | (pipe) puts two tiles one on top of the other:

tile1 = t/"""
          Magenta
          Green
          """

tile2 = t/"""
          Red
          Blue
          White
          """

print(tile1 | tile2)

Results in:

Magenta
Green
Red
Blue
White

Of course, operators += and |= work as expected:

tile = t/"""
         Magenta
         Green
         """

tile += t/"""
          Red
          Blue
          White
          """

print(tile)

Results in:

MagentaRed
Green  Blue
       White

Joining many tiles

Joining works similarly to joining strings:

tile = (t/",").join([t/"square", t/"circle", t/"triangle"])
print(tile)

Results in:

square,circle,triangle

There is also a special function for joining tiles in vertical manner:

tile = (t/",").vjoin([t/"square", t/"circle", t/"triangle"])
print(tile)

Results in:

square,
circle,
triangle

Function vjoin has an optional parameter inline (true by default) which puts the separator at the same line with the list item. If switched off, the separator will appear on its own line:

tile = (t/"---").vjoin([t/"square", t/"circle", t/"triangle"], inline=False)
print(tile)

Results in:

square
---
circle
---
triangle

Finally, both join and vjoin have last argument which acts as a kind of a final separator:

tile = (t/",").vjoin([t/"square", t/"circle", t/"triangle"], last=t/";")
print(tile)

Results in:

square,
circle,
triangle;

Working with whitespace

Given that standard tile literals cut off the surrounding whitespace from the tile we need to use a different construct when we actually want the surrounding whitespace to appear in the tile.

The most common use case is when there's a need to add an empty line to a tile. emptyln is a tile containing only a single empty line:

tile = t/"Hello" | emptyln | t/"world"
println(tile)

Prints:

Hello

world

emtyln is really just a shortcut for t%"" where t% is similar to t/ except that it doesn't cut off the whitespace.

(In the example below ␣ stands for space.)

t/"␣␣␣foo␣␣␣" produces foo tile.

t%"␣␣␣foo␣␣␣" produces ␣␣␣foo␣␣␣ tile.

tile = (t%", ").join([t/"square", t/"circle", t/"triangle"])
print(tile)

Results in:

square, circle, triangle

Note that t%"" produces a tile with one empty line and t%"\n" produces a tile containing two empty lines.

To get a completely empty tile with zero lines use t/"".

tile = t/"""
         Magenta
         Green
         """

tile |= t%"" | t/"""
                 Red
                 Blue
                 White
                 """

Results in:

Magenta
Green

Red
Blue
White

Worked example 1

from tiles import tile

colors = t/"""
           White
           Black
           Ultramarine
           Red
           Green
           Blue
           """

shapes = t/"""
           Triangle
           Circle
           """

tile = t/"""
         Colors: @{colors}     Shapes: @{shapes}

         That's all, folks!
         """)

print(tile)

On the picture below you can see how are individual tiles combined to produce the final output. Tiles are shown in red frames. Literal text is in blue frames. Black lines mark boundaries between individual lines.

Note how tiles are always aligned to the top of the line.

Worked example 2

Imagine that we want to generate code that prints out some greetings.

def greet(name):
    return "print('Hello, " + name + "!')\nprint('Welcome!')" 

Although there is no particular need for manipulating rectangular areas of text in this case tiling can be employed to make the code more readable.

def greet(name):
    return t/"""
             print('Hello, @{name}!')
             print('Welcome!')
             """

Given that whitespace surrounding the tile is ignored anyway we can neatly align the generated code with the generator code instead of writing an abomination like this one:

def greet(name):
    return """print('Hello, """ + name + """!')
print('Welcome!')"""

Another consequence of using tiles is that the greeting function can be used in different contexts and the indentation will allways fit:

code = t/"""
         import sys

         @{greet('Alice')}
         if 'also-greet-bob' in sys.argv:
             @{greet('Bob')} 
         """

print(code)

Here's the output. Note how the greeting code is properly aligned in both cases, forming a valid Python program:

import sys

print('Hello, Alice!')
print('Welcome!')
if 'also-greet-bob' in sys.argv:
    print('Hello, Bob!')
    print('Welcome!')

Worked example 3

Tiling can be used to generate code with clean vertical alignment. Consider the case where we have a lists or argument names and types and we want to generate a nicely formatted C function declaration.

arglist = [t/"foo", t/"bar", t/"baz"]
typelist = [t/"int", t/"char*", t/"struct quux"]

argtile = (t/"").vjoin(arglist)
typetile = (t/",").vjoin(typelist, last=t/");")

signature = t/"void frobnicate(@{argtile} @{typetile}"
            
print(signature)

The tile with argument names is put next to the tile with argument types. This is done on tile, not line, level which means that all the argument names stay aligned with each other.

void frobnicate(int         foo, 
                char*       bar,
                struct quux baz);

Notes

Note 1: If you need sequence @{ to appear in the output (and not be treated like an embedded expression) it can be done like this: @{'@'}{

Note 2: With t/, the trailing whitespace that is required to keep the rectangular shape of a tile doesn't get into the output. This makes the algorithm friendy to different tools that complain about whitespace at the end of a line.

Note 3: To provide a better feeling of how a real-world code using tiles look like, here's a fairly long program generating some man pages and a C header file.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].