Skip to content

Feature request: Flake templates with variables #4017

@tobiasBora

Description

@tobiasBora

Is your feature request related to a problem? Please describe.

When we create a new project from a flake template with something like:

nix flake new -t "github:myname/mytemplateproject" templatename

the generated project is fixed, and cannot depend on any configuration variable specified by the user. I'd love to be able to be able to specify some variables, like the name of the project, the description of the project, the licence of the project... and then let a template engine create the good files/files content (both of them could depend on the variable names) automatically.

Describe the solution you'd like
There are two solutions I can think of, which are maybe not mutually exclusive and could benefit from each other:

  • a first solution would be to have directly a good built-in template in nix flake templates. Either we create this code generator from scratch inside nix (longer, more likely to contain bugs, likely to be less powerful), or we rely on existing tools like cookiecutter.
  • a second solution would be to allow the packager to rely on any external template engine to generate the final project, by just asking him to provide an executable to run. There are lots of code generator, like cookiecutter that could be used, and even some more specialized tool, for example a template system may want to invoke npm init to create a npm project. We could therefore turn a nix flake init into a nix run.

I think that both solutions should be used: the first one (based on cookiecutter or alike) provides an easy to use syntax for users that do not care about advanced template generation, and the second option allow more advanced code generator to be used.

Describe alternatives you've considered

For now, I'm using instead nix run to do what I need:

[me@me:/tmp/codegen]$ tree
.
├── flake.lock
├── flake.nix
├── gentemplate
│   ├── {{cookiecutter.directory_name}}
│   │   └── {{cookiecutter.file_name}}.py
│   └── cookiecutter.json
└── gentemplate.nix

2 directories, 5 files

[me@me:/tmp/codegen]$ cat flake.nix 
{
  description = "Template generation";
  inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-unstable;
  inputs.flake-utils.url = "github:numtide/flake-utils";
  outputs = { self, nixpkgs, flake-utils }:
    # See https://github.com/numtide/flake-utils
    flake-utils.lib.eachDefaultSystem
      (system:
        let pkgs = nixpkgs.legacyPackages.${system}; in
        rec {
          # Packages that are created by this lib
          # It is what "nix build .#name" will compile
          # For example "nix build .#mysatsolver"
          packages = flake-utils.lib.flattenTree {
           gentemplate = pkgs.callPackage ./gentemplate.nix { };
          };
          # What package "nix build ." will compile by default:
          defaultPackage = packages.gentemplate;
          # The apps can be run directly via "nix run .#name-of-the-app"
          # Example: "nix run .#mysatsolver"
          apps.gentemplate = flake-utils.lib.mkApp {
            drv = packages.gentemplate;
            # Customize the path of the binary to run
            exePath = "/bin/gentemplate";
          };
          # What "nix run ." will run by default (you can give arguments like
          # "nix run . -- my args goes here")
          defaultApp = apps.gentemplate;
          # Run the shell with "nix develop"
          devShell = import ./shell.nix { inherit pkgs; };
        });
}

[me@me:/tmp/codegen]$ cat "gentemplate/{{cookiecutter.directory_name}}/{{cookiecutter.file_name}}.py" 
print("Hello, {{cookiecutter.greeting_recipient}}!")

[me@me:/tmp/codegen]$ cat gentemplate/cookiecutter.json 
{
    "directory_name": "Hello",
    "file_name": "Howdy",
    "greeting_recipient": "Julie"
}

[me@me:/tmp/codegen]$ nix run
directory_name [Hello]: 
file_name [Howdy]: 
greeting_recipient [Julie]: Bob

[me@me:/tmp/codegen]$ python Hello/Howdy.py 
Hello, Bob!

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureFeature request or proposalflakesnew-cliRelating to the "nix" command
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions