Skip to content

Stupid Gen(erator)

Ever wanted to generate a text file, but did not feel like learning yet another way to write a for loop #yawtwafl? Then this tool is for you! (Source code: here)

Example

It's real simple:

#test.py.multi
>Start
for i in range(5) : 
    >hello {% i %}
    if i % 2 == 0 : 
        >   world {% i * i + 3 %}
>End
Run the program with stupidgen -C --run test.py.multi...

//test.cpp.multi
#include <iostream> //Don't forget this

int main() {
    >Start
    for (int i = 0; i < 5; i++) {
        >hello {% i %}
        if (i % 2 == 0)
        >   world {% i * i + 3 %}
    }
    >End
    return 0;
}

//Test.java.multi
class Test {
    void main(String... args) {
        >Start
        for (int i = 0; i< 5; i++) {
            >hello {% i %}
            if (i % 2 == 0) {
                >   world {% i * i + 3 %}
            }
        }
        >End
    }
}
Run the program with stupidgen -C --run Test.java.multi...

//Test.groovy.multi
class Test {
    static void main(String... args) {
        >Start
        for (int i = 0; i< 5; i++) {
            >hello {% i %}
            if (i % 2 == 0) {
                >   world {% i * i + 3 %}
            }
        }
        >End
    }
}
Run the program with stupidgen -C --run Test.groovy.multi...

--test.lua.multi
>Start
for i=0,4 do 
    >hello {% i %}
    if i % 2 == 0 then 
        >   world {% i * i + 3 %}
    end
end
>End
Run the program with stupidgen -C --run test.lua.multi...

//test.js.multi
>Start
for (var i=0; i < 5; i++) {
    >hello {% i %}
    if (i % 2 == 0)
        >   world {% i * i + 3 %}
}
>End
Run the program with stupidgen -C --run test.js.multi...

And tadaaa! It automatically prints the following to the standard output:

Start
hello 0
    world 3
hello 1
hello 2
    world 7
hello 3
hello 4
    world 19
End
Are you amazed? You are amazed. I know you are. But now the question that everyone is asking is...

How can this possibly work?

StupidGen works in two steps. A first step processes your input file to transform it into a proper C++/python/java... file. Then, when you give it the --run option, this file is compiled (if necessary) and executed. Without the --run option, the stupidgen command just produces the intermediate C++/javascript... file, and you are left with the (heavy) responsability of running it yourself.

So how does that first step work? Years of research into template generation have led to the discovery of the following rules:

  • every line that starts with a > is treated as text, and is replaced by a line of code that will simply print this line
  • on a text line, everything that is between {% and %} is treated as code that generates a string.

  • every line that starts with . is treated as code, and is left unmodified (except for the starting . which is discarded)

  • That's all.

But wait, what about the lines that don't start with > or . like in your example above? Well that's where the -C option comes in: it tells the tool to treat all these lines as if they were Code lines.

If you prefer, there is the opposite option -T that treats these lines as Text lines. In this case, you have to prefix every code line with ., but you can omit the > from text lines. Depending on the amount of text vs. code that you have, one option might be preferrable to the other. With the -T option, the example above becomes:

.#For python, you can't omit the '>' when the text is inside a block,
.#because we need the information on the current indentation level.
Start
.for i in range(5) : 
    >hello {% i %}
.   if i % 2 == 0 : 
        >world {% i * i + 3 %}
End
.#include <iostream>
.int main() {
Start
.   for (int i = 0; i < 5; i++) {
hello {% i %}
.       if (i % 2 == 0)
    world {% i * i + 3 %}
.   }
End
.   return 0;
.}
.class Test {
.   void main(String... args) {
Start
.       for (int i = 0; i< 5; i++) {
hello {% i %}
.           if (i % 2 == 0) {
    world {% i * i + 3 %}
.           }
.       }
End
.   }
.}
.class Test {
.   static void main(String... args) {
Start
.       for (int i = 0; i< 5; i++) {
hello {% i %}
.           if (i % 2 == 0) {
    world {% i * i + 3 %}
.           }
.       }
End
.   }
.}
Start
.for i=0,4 do 
hello {% i %}
.   if i % 2 == 0 then 
    world {% i * i + 3 %}
.   end
.end
End
Start
.for (var i=0; i < 5; i++) {
hello {% i %}
.   if (i % 2 == 0)
    world {% i * i + 3 %}
.}
End

Are you convinced? Then check out the installation guide to get started.

Additional options

Depending on the kind of text you want to generate, or the kind of language you want to use to generate it, the default symbols (., >, {%, and %}) might not be very practical. Fortunatly, you can replace these symbols with others of your choosing using the ... command line options.

As we mentionned before, there are different ways to treat lines that do not start by one of the two escape symbols (. and > by default).

  • The -C option treats these lines as code lines (as if there was a . in front of each of them).
  • The -T option treats them as text lines (as if they were starting with a >)
  • The -D option discards them from the output

By default, stupidgen just preprocess your file, and outputs the code, but you can use --run to make it run the hell out of it.

You can use -o <filenam> to indicate where the code file should be saved (when you are not using the --run option), or --print to print it to the standard output. Usually, the language used in the file will be guessed from the extension of the file. So a file with a .py.multi extension will be processed to a python file, while .java.multi is treated as a java file, etc... However you can force stupidgen to treat a file as a specific language with the --language <lang> option.

Check out the supported languages.