gcgen file

This page describes gcgen files, the files named gcgen_conf.py which may be located in any subdirectory of the project, and which drive all aspects of code generation using gcgen.

The gcgen files provide hooks to modify the scope in the context of their directory and any subdirectories, hooks to specify which files should be parsed for snippets. Snippet and generator definitions, file indentation rules and more.

gcgen requires a gcgen_conf.py file in each directory whose files might contain snippets to parse or where generators should create new files from scratch. This in turn encourages keeping snippet definitions and specific scope variables local to those subdirectories which use them.

To see more about using gcgen in a new project, consult Starting a project. To better understand how the scope and subdirectories work together, see Scope.

Finally, this page will not cover defining snippets or generators see their sections for details on that.

Parse files

When adding snippets to a file, you also need to tell gcgen to parse that file for code-generation to work.

In the same directory, create a gcgen_conf.py file and implement the gcgen_parse_files hook like so:

gcgen_conf.py - parse files
1def gcgen_parse_files():
2    return [
3        "my_file.c",
4        "my_other_file.go"
5    ]

This extra step may seem onerous, but it drastically speeds up the compilation process, which would otherwise have to parse every file, line-by-line. Furthermore, it requires creating gcgen_conf.py files in each directory which uses gcgen for code-generation. This both makes it easier to identify where gcgen is used, and encourages keeping snippet definitions and relevant scope entries local to the consuming code.

Since gcgen_parse_files is a function, you could generate the list of files:

gcgen_conf.py - parse files, parse all python files
1from pathlib import Path
2
3
4def gcgen_parse_files():
5    # return all .py files in the current directory
6    return list(Path(".").glob("*.py"))

Extend the Scope

The introduction touches on the compile process, noting that each gcgen file may implement a function which modifies the scope passed to their own snippets & generators, and all of their subdirectories.

gcgen_conf.py - scope extend hook
 1from gcgen.api import Scope
 2
 3
 4def gcgen_scope_extend(scope: Scope):
 5    # add some definitions
 6    scope["name"] = "Jane"
 7    scope["surname"] = "Doe"
 8    # can also remove definitions
 9    # (this does not affect the parent scope(s))
10    del scope["something"]

Configure indentation

Each snippet and generator is passed an section object which is used to produce the generated output and to indent & dedent lines.

In the gcgen_conf.py file, you can define the characters used to indent on a per-filetype basis:

gcgen_conf.py - configure indentation
1from gcgen.api import Scope
2
3
4gcgen_indent_by = {
5    # indent python files by 4 spaces
6    "py": "    ",
7    # indent go files by one tab
8    "go": " ",
9}

Typically, indentation would be defined in the top-level gcgen_conf.py file, for all subdirectories to inherit. However, a gcgen_conf.py in some subdirectory can implement gcgen_indent_by to configure indentation for further file types.