diff --git a/lessons/submodule-types/character.nix b/lessons/submodule-types/character.nix new file mode 100644 index 0000000..7ae18f7 --- /dev/null +++ b/lessons/submodule-types/character.nix @@ -0,0 +1,40 @@ +{ + lib, + options, + config, + ... +}: let + cfg = config; + opts = options; +in { + options = { + name = lib.mkOption { + type = lib.types.str; + }; + title = lib.mkOption { + type = lib.types.str; + }; + origin = lib.mkOption { + type = lib.types.str; + }; + + greeting = lib.mkOption { + type = lib.types.str; + }; + }; + + config = { + greeting = ( + lib.concatStringsSep + "\n" + ( + [ + "Hello" + ] + ++ (lib.optional opts.name.isDefined "My name is ${cfg.name}.") + ++ (lib.optional opts.title.isDefined "I am a ${cfg.title}.") + ++ (lib.optional opts.origin.isDefined "I am from ${cfg.origin}.") + ) + ); + }; +} diff --git a/lessons/submodule-types/config.nix b/lessons/submodule-types/config.nix new file mode 100644 index 0000000..14595b4 --- /dev/null +++ b/lessons/submodule-types/config.nix @@ -0,0 +1,15 @@ +{...}: { + config = { + characters = [ + { + name = "Boaty McBoatface"; + origin = "England"; + } + { + name = "djacu"; + title = "Nix Enthusiast"; + origin = "USA"; + } + ]; + }; +} diff --git a/lessons/submodule-types/eval.nix b/lessons/submodule-types/eval.nix new file mode 100644 index 0000000..49f232a --- /dev/null +++ b/lessons/submodule-types/eval.nix @@ -0,0 +1,11 @@ +{pkgs}: +( + pkgs.lib.evalModules { + modules = [ + ./options.nix + ./config.nix + ]; + } +) +.config +.greeting diff --git a/lessons/submodule-types/lesson.md b/lessons/submodule-types/lesson.md index 4aa5ac7..796fe00 100644 --- a/lessons/submodule-types/lesson.md +++ b/lessons/submodule-types/lesson.md @@ -1 +1,41 @@ # Submodule Types + +After learning about composed types, you can imagine that nesting can get deep quickly. +The logic for tracking each layer can become overwhelming. +This is where one of the most useful types included in type system comes into play: `submodule`. +It allows you to define nested modules with their own option imports, declarations, and definitions. + +First we will define our submodule. +In `character.nix` we have something that looks very similar to what we built before. +We have `name`, `title`, and `origin` as inputs and a greeting that combines all these as an output. + +[//]: # (./character.nix) + +In our `options.nix`, we have a `characters` option that is a list of submodule that points to our `character.nix` file. +We have also defined a `greeting` option that will take all `greeting` definitions from our characters and join them into a single string. +Note: these two `greeting` options are not the same; `character.nix` and `options.nix` each have their own `greeting` option. + +!!! note + We could have written the `character.nix` submodule in place. + For the sake of readability, we gave it its own file. + Also, writing it in its own file allows us to use it elsewhere if desired. + +[//]: # (./options.nix) + +In our `config.nix`, we define all of our characters. +The behavior of the submodule type is attr-*like*. +So inside our list we have attribute sets; each one can have a value for attributes `name`, `title` and `origin`. + +[//]: # (./config.nix) + +Setup an `eval.nix` to evaluate our modules and return the `config.greeting` attribute. + +[//]: # (./eval.nix) + +Create a `run.sh` run script to evaluate the `eval.nix` file. + +[//]: # (./run.sh) + +And if we run the script (`./run.sh`), we have our configuration. + +[//]: # (self.eval) diff --git a/lessons/submodule-types/options.nix b/lessons/submodule-types/options.nix new file mode 100644 index 0000000..2bbb3b3 --- /dev/null +++ b/lessons/submodule-types/options.nix @@ -0,0 +1,27 @@ +{ + lib, + config, + ... +}: let + cfg = config; +in { + options = { + characters = lib.mkOption { + type = lib.types.listOf (lib.types.submodule ./character.nix); + }; + greeting = lib.mkOption { + type = lib.types.str; + }; + }; + + config = { + greeting = + lib.concatStringsSep + "\n\n" + ( + builtins.map + (character: character.greeting) + cfg.characters + ); + }; +} diff --git a/lessons/submodule-types/run.sh b/lessons/submodule-types/run.sh new file mode 100755 index 0000000..d5086db --- /dev/null +++ b/lessons/submodule-types/run.sh @@ -0,0 +1,3 @@ +nix eval -f eval.nix \ + --apply 'x: x {pkgs = import {};}' \ + --json | nix run nixpkgs#jq -- -r