nix-community / flakelight

Framework for simplifying flake setup [maintainer=@accelbread]
MIT License
229 stars 6 forks source link

Document how to pass extra custom module arguments #20

Open ratson opened 6 months ago

ratson commented 6 months ago

I would like pass a shared utility function as an extras module argument. I could not find any documentation about how to do it.

The only reference I found in https://github.com/nix-community/flakelight/blob/master/API_GUIDE.md

Default values are automatically initialized from your flake inputs by reading your flake.lock. Note that this does not include the self argument, which must be passed explicitly if you want to use it.

And it has no example on how to pass the self argument if desired.

It would be helpful if there is also documentation about how to write a custom flakelight module.

accelbread commented 5 months ago

Hey, sorry, missed the notification for this. Thanks!

For the self argument, it gets passed if you use inherit inputs like here: https://github.com/nix-community/flakelight/blob/5983f517f942b8ca177b678f3f102c8b56ab791c/API_GUIDE.md?plain=1#L106-L115

I'll make the docs more clear there.

For passing a shared utility function, you can either add a module argument or add it to your lib output.

If you put it in your lib, you can access it from outputs.lib.

For adding a module argument, you can do something like:

let
  cool-fn = x: x;
in {
  _module.args.cool-fn = cool-fn;
  _module.args.moduleArgs.cool-fn = cool-fn;
}

When I get to writing templates, I'll make a template with docs for flakelight-modules.

accelbread commented 4 months ago

Updated docs for passing inputs; still need to write template for modules.

ratson commented 4 months ago

Thanks for the detailed answer and the updates. Feel free to close the issue.

daniel-sampliner commented 3 months ago

I'm trying to use the _module.args example above, but it's not working as I'd expect. Consider:

{
  inputs = {
    flakelight.url = "github:nix-community/flakelight";
    nixpkgs.url = "nixpkgs/nixpkgs-unstable";
  };
  outputs = { flakelight, ... }:
    flakelight ./empty {
      _module.args.foo = "foo";

      outputs = { foo, ... }: {
        example.test = foo;
      };
    };
}

This fails saying it's missing the argument 'foo':

 :; nix eval .#example.test
error:
       … in the left operand of the update (//) operator

         at «string»:56:13:

           55|             # This is shadowed in the next //
           56|             // sourceInfo
             |             ^
           57|             // {

       … while evaluating the attribute 'value'

         at /nix/store/qxf6anli54ij0q1sdlnlgx9hyl658a4v-source/lib/modules.nix:821:9:

          820|     in warnDeprecation opt //
          821|       { value = addErrorContext "while evaluating the option `${showOption loc}':" value;
             |         ^
          822|         inherit (res.defsFinal') highestPrio;

       (stack trace truncated; use '--show-trace' to show the full trace)

       error: function 'outputs' called without required argument 'foo'

       at /nix/store/0svd8xllv1cv93vscipvf0m8g3s2gvsi-source/flake.nix:10:17:

            9|
           10|       outputs = { foo, ... }: {
             |                 ^
           11|         example.test = foo;

Am I misunderstanding/misusing something here?


Note that I can change it like this so it will no longer error:

{
  inputs = {
    flakelight.url = "github:nix-community/flakelight";
    nixpkgs.url = "nixpkgs/nixpkgs-unstable";
  };
  outputs = { flakelight, ... }:
    flakelight ./empty {
      _module.args.foo = "foo";

      outputs = { config, ... }: {
        example.test = config._module.args.foo;
      };
    };
} 
 :; nix eval .#example.test
"foo"

However, I don't think I should have to do this?

accelbread commented 3 months ago

@daniel-sampliner I've pushed a1e3b8bc3e09dd5d019484d59c05edff7019fb70, which makes all args available through moduleArgs.

Copying the above example, previously you had to also set your arg on moduleArgs for it to be available:

let
  cool-fn = x: x;
in {
  _module.args.cool-fn = cool-fn;
  _module.args.moduleArgs.cool-fn = cool-fn;
}

Now just the first line is needed so your example should work as is.

daniel-sampliner commented 3 months ago

Thanks for the quick fix!

For what it's worth, I had tried specifying with moduleArgs as well like shown but that fails in a different way

 :; nix eval .#example.test
error:
       … in the left operand of the update (//) operator

         at «string»:56:13:

           55|             # This is shadowed in the next //
           56|             // sourceInfo
             |             ^
           57|             // {

       … while evaluating the attribute 'value'

         at /nix/store/qxf6anli54ij0q1sdlnlgx9hyl658a4v-source/lib/modules.nix:821:9:

          820|     in warnDeprecation opt //
          821|       { value = addErrorContext "while evaluating the option `${showOption loc}':" value;
             |         ^
          822|         inherit (res.defsFinal') highestPrio;

       (stack trace truncated; use '--show-trace' to show the full trace)

       error: The option `_module.args.moduleArgs' is defined multiple times while it's expected to be unique.

       Definition values:
       - In `<unknown-file>':
           {
             foo = "foo";
           }
       - In `/nix/store/bm0zc7s7cgivaaiv0smgah498a49vil2-source/builtinModules/moduleArgs.nix'
       Use `lib.mkForce value` or `lib.mkDefault value` to change the priority on any of these definitions.

It still fails like this after the above commit. I don't know if that's important now that your change makes the extra moduleArgs declaration unnecessary.

accelbread commented 3 months ago

Huh, seems the module system doesn't merge args; AFAIK it used to but I may be wrong. Well, shouldn't be needed now since its set to all args.