Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: adds support for passing options to make functions #4

Merged
merged 5 commits into from
Jun 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ Plugins are available for quickly generating configuration files. For example, a
};
};
preCommit = nixago.plugins.pre-commit.mkLocalConfig preCommitConfig;
preCommit = nixago.plugins.pre-commit.mkLocalConfig {
configData = preCommitConfig;
};
# ...
}
```
Expand Down
32 changes: 23 additions & 9 deletions docs/src/contributing/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,21 +146,27 @@ will create a single function for generating our configuration file:

```nix
{ pkgs, lib }:
data:
{ configData }:
with pkgs.lib;
let
files = [ ./template.cue ];
output = ".pre-commit-config.yaml";
pre-commit = pkgs.pre-commit;

# Add an extra hook for reinstalling required stages whenever the file changes
stages = unique (flatten (builtins.map (repo: builtins.map (hook: optionals (hook ? stages) hook.stages) repo.hooks) data.repos) ++ [ "pre-commit" ]);
stages = unique (flatten
(builtins.map
(repo: builtins.map
(hook: optionals (hook ? stages) hook.stages)
repo.hooks)
configData.repos) ++ [ "pre-commit" ]);
stagesStr = builtins.concatStringsSep " " stages;
shellHookExtra = (import ./common.nix { inherit pre-commit stagesStr; }).shellHookExtra;
shellHookExtra =
(import ./common.nix { inherit pre-commit stagesStr; }).shellHookExtra;

# Generate the module
result = lib.mkTemplate {
inherit data files output shellHookExtra;
inherit configData files output shellHookExtra;
};
in
{
Expand All @@ -170,8 +176,15 @@ in

All functions maintain the same basic structure. At the top, we accept an
attribute set as the first argument, which pulls in local copies of `nixpkgs`
and the internal `lib` provided by the flake. The second argument should be
named `data` and contain the data passed in by the end-user.
and the internal `lib` provided by the flake. The second argument should also be
an attribute set that must contain the `configData` attribute. Nixago expects
all plugin functions to take a single attribute set as an argument that, at the
very least, contains the `configData` attribute. The `configData` attribute is
where the raw incoming data from the end user is placed.

It's possible to add additional arguments to the attribute set if your plugin
requires extra configuration. Ensure that you provide ample documentation for
each of these additional arguments to the end user.

The top of the function should declare the `files` and `output` variables. The
`files` variable should point to the CUE file we previously created. The
Expand Down Expand Up @@ -248,13 +261,14 @@ runTest "pre-commit.mkConfig" ./expected.yml {
}
];
}
{ }

```

The `runTest` helper function provided performs most of the underlying work
required to test the plugin. It takes three arguments: the function to call for
the test, the location of the expected test output, and the data to pass to the
specified function.
required to test the plugin. It takes four arguments: the function to call for
the test, the location of the expected test output, the data to pass to the
specified function, and any additional arguments to pass to the plugin function.

The second step is to create the expected output. In this case, the above
invocation should produce the following result:
Expand Down
22 changes: 19 additions & 3 deletions docs/src/quick_start.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ Choose a plugin to use. The below example uses the plugin for [pre-commit][1]:
};
};

preCommit = nixago.plugins.pre-commit.mkLocalConfig preCommitConfig;
preCommit = nixago.plugins.pre-commit.mkLocalConfig {
configData = preCommitConfig;
};
# ...
}
```
Expand Down Expand Up @@ -130,8 +132,22 @@ The input to `mkAll` expects an attribute set where the name is one of the
following:

1. A path to the function to be called, relative to the `plugins` set (i.e.,
`prettier.`mkIgnoreConfig`)
2. The name of a plugin
`prettier.mkIgnoreConfig`)
2. The name of a plugin with `.opts` appended (i.e., `prettier.opts`)

Appending the function name after the plugin name is optional. In this case, the
`mkAll` function will call the `default` function. This function is specific to
each plugin; refer to the source code for what is called.

The value of the attribute should be the raw configuration data that will be
passed to the function. All plugin functions take a `configData` argument which
contains the configuration data. This argument is supplied with the value of the
attribute.

Some plugin functions accept additional arguments beyond `configData`. To pass
other arguments using the `mkAll` function, you must add an extra attribute in
the format of `pluginName.opts`. The value of this attribute should be a set
that will be merged into the final call to the plugin function.

The `default` function will be called from the plugin in the second case. See
the individual plugins for which function this is. The second parameter is the
Expand Down
61 changes: 50 additions & 11 deletions lib/all.nix
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,60 @@ all:
with pkgs.lib;
let
plugins = import ../plugins { inherit pkgs lib; };
makeAll = name: data: (
let
# If the input is not in the `plugin.function` format, assume we want
# `plugin.default`
path =
let s = splitString "." name;
in
if (builtins.length (s) > 1) then s else [ name "default" ];

make = getAttrFromPath path plugins;
# Create separate sets of plugin calls and plugin options
filteredOpts = filterAttrs
(path: data: (
let
parts = splitString "." path;
partsLength = builtins.length parts;
in
if partsLength > 1 then (builtins.elemAt parts 1) == "opts" else false
))
all;
filteredFuncs = filterAttrs
(path: data: (
let
parts = splitString "." path;
partsLength = builtins.length parts;
in
if partsLength > 1 then (builtins.elemAt parts 1) != "opts" else true
))
all;

# Convert option keys to `pluginName` instead of `pluginName.opts`
opts = mapAttrs'
(name: data: (
let
parts = splitString "." name;
pluginName = builtins.elemAt parts 0;
in
nameValuePair pluginName data
))
filteredOpts;

# Convert function keys to `pluginName.default` if name was omitted
funcs = mapAttrs'
(path: data: (
let
parts = splitString "." path;
partsLength = builtins.length parts;
in
nameValuePair (if partsLength > 1 then path else "${path}.default") data
))
filteredFuncs;

makeAll = path: configData: (
let
parts = splitString "." path;
make = getAttrFromPath parts plugins;
pluginName = builtins.elemAt parts 0;
in
make data
make ({ inherit configData; }
// (optionalAttrs (opts ? pluginName) opts.${pluginName}))
);

result = mapAttrsToList makeAll all;
result = mapAttrsToList makeAll funcs;
in
{
configs = catAttrs "configFile" result;
Expand Down
9 changes: 5 additions & 4 deletions lib/eval.nix
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
/*
Evaluates the given input files and data and returns a derivation which builds the result.
Evaluates the given input files and configData and returns a derivation which
builds the result.
*/
{ pkgs, lib }:
{ inputFiles
, outputFile
, postBuild ? ""
, data ? { }
, configData ? { }
, cue ? pkgs.cue
, ...
}@args:

with pkgs.lib;
let
json = optionalString (data != { }) (builtins.toJSON data);
json = optionalString (configData != { }) (builtins.toJSON configData);

defaultFlags = {
outfile = "$out"; # Output the evaluation result to the derivation output
Expand All @@ -23,7 +24,7 @@ let
"inputFiles"
"outputFile"
"postBuild"
"data"
"configData"
"cue"
];

Expand Down
6 changes: 3 additions & 3 deletions lib/template.nix
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
/* Create a template instance using the given data, files, and output.

This function is a wrapper for creating instances of ../modules/template.nix.
The three primary arguments (`data`, `files`, and `output`) are fed into the
The three primary arguments (`config`, `files`, and `output`) are fed into the
module configuration. The optional `shellHookExtra` argument can be supplied
which is also fed into the module. The optional `flags` argument is fed into
the module `specialArgs` and is used for passing additional flags to the
underlying `cue eval` command. The function returns the evaluated config from
the module.
*/
{ pkgs, lib }:
{ data, files, output, postBuild ? "", shellHookExtra ? "", flags ? { } }:
{ configData, files, output, postBuild ? "", shellHookExtra ? "", flags ? { }, ... }:
with pkgs.lib;
let
result = evalModules {
modules = [
../modules/template.nix
{
inherit data files output postBuild shellHookExtra;
inherit configData files output postBuild shellHookExtra;
}
];
specialArgs = ({ inherit pkgs; flakeLib = lib; } // flags);
Expand Down
6 changes: 3 additions & 3 deletions modules/template.nix
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,15 @@ in
description = "The generated configuration file";
default = flakeLib.eval
({
inherit (config) configData;
inputFiles = config.files;
outputFile = config.output;
data = config.data;
postBuild = config.postBuild;
} // flags);
};
data = mkOption {
configData = mkOption {
type = types.attrs;
description = "The configuration data";
description = "The raw configuration data";
};
files = mkOption {
type = types.listOf types.path;
Expand Down
16 changes: 10 additions & 6 deletions plugins/conform/mkConfig.nix
Original file line number Diff line number Diff line change
@@ -1,26 +1,30 @@
{ pkgs, lib }:
data:
{ configData, ... }:
with pkgs.lib;
let
files = [ ./template.cue ];
output = ".conform.yaml";

# Expand out the data
# Expand out the configData
test = {
commit = { };
license = { };
};

dataFinal = {
configDataFinal = {
policies =
(optional (data ? commit) { type = "commit"; spec = data.commit; }) ++
(optional (data ? license) { type = "license"; spec = data.license; });
(optional
(configData ? commit)
{ type = "commit"; spec = configData.commit; }) ++
(optional
(configData ? license)
{ type = "license"; spec = configData.license; });
};

# Generate the module
result = lib.mkTemplate {
inherit files output;
data = dataFinal;
configData = configDataFinal;
};
in
{
Expand Down
4 changes: 2 additions & 2 deletions plugins/just/mkConfig.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{ pkgs, lib }:
data:
{ configData }:
let
files = [ ./template.cue ];
output = ".justfile";
Expand All @@ -18,7 +18,7 @@ let

result = lib.mkTemplate {
inherit files output postBuild flags;
data = { inherit data; };
configData = { data = configData; };
};
in
{
Expand Down
6 changes: 3 additions & 3 deletions plugins/lefthook/mkConfig.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{ pkgs, lib }:
data:
{ configData }:
with pkgs.lib;
let
files = [ ./template.cue ];
Expand All @@ -14,7 +14,7 @@ let
"source_dir"
"source_dir_local"
];
stages = builtins.attrNames (builtins.removeAttrs data skip_attrs);
stages = builtins.attrNames (builtins.removeAttrs configData skip_attrs);
stagesStr = builtins.concatStringsSep " " stages;
shellHookExtra = ''
# Install configured hooks
Expand All @@ -25,7 +25,7 @@ let

# Generate the module
result = lib.mkTemplate {
inherit data files output shellHookExtra;
inherit configData files output shellHookExtra;
};
in
{
Expand Down
6 changes: 3 additions & 3 deletions plugins/pre-commit/mkConfig.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{ pkgs, lib }:
data:
{ configData }:
with pkgs.lib;
let
files = [ ./template.cue ];
Expand All @@ -12,14 +12,14 @@ let
(repo: builtins.map
(hook: optionals (hook ? stages) hook.stages)
repo.hooks)
data.repos) ++ [ "pre-commit" ]);
configData.repos) ++ [ "pre-commit" ]);
stagesStr = builtins.concatStringsSep " " stages;
shellHookExtra =
(import ./common.nix { inherit pre-commit stagesStr; }).shellHookExtra;

# Generate the module
result = lib.mkTemplate {
inherit data files output shellHookExtra;
inherit configData files output shellHookExtra;
};
in
{
Expand Down
4 changes: 2 additions & 2 deletions plugins/prettier/mkConfig.nix
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{ pkgs, lib }:
data:
{ configData }:
with pkgs.lib;
let
files = [ ./template.cue ];
output = ".prettierrc.json";

# Generate the module
result = lib.mkTemplate {
inherit data files output;
inherit configData files output;
};
in
{
Expand Down
4 changes: 2 additions & 2 deletions plugins/prettier/mkIgnoreConfig.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{ pkgs, lib }:
data:
{ configData }:
with pkgs.lib;
let
files = [ ./template_ignore.cue ];
Expand All @@ -12,7 +12,7 @@ let
# Generate the module
result = lib.mkTemplate {
inherit files output flags;
data = { inherit data; };
configData = { data = configData; };
};
in
{
Expand Down
Loading