Metadata for Nix: embed, query, and strip it on any expression.
nix-meta embeds metadata as an attribute set under a _meta marker in a Nix expression and traverses the expression to find, update, or remove it.
Anything can live in _meta: description, license, maintainers, platforms, changelog, whatever a package and its consumers need to know. The type and shape are up to you.
Built on nix-ast.
Flake input:
{
inputs.nix-meta.url = "github:z1-0/nix-meta";
outputs = { nix-meta, ... }: {
lib = nix-meta.lib;
};
}The examples below use meta for nix-meta.lib.
Only nodes with bindings can carry _meta: attribute sets and let expressions. nix-meta peels off wrapper expressions (with, assert, lambdas) until it finds a container:
| Expression | Metadata container |
|---|---|
{ a = 1; } |
the set itself |
let x = 1; in { a = 1; } |
the inner set |
let _meta = ...; in { a = 1; } |
the let itself |
let x = 1; in 42 |
the let itself (fallback) |
with p; { a = 1; } |
the inner set |
with p; 42 |
none: get returns null, set/remove leave the AST untouched |
x: 42 |
none |
A let is a fallback container because an unused binding is harmless. with p; 42 has nowhere to attach a binding without changing its meaning.
get :: pkgs -> [AST] -> [a | null]
For each AST, find and evaluate the first _meta binding.
get returns one element per input AST, in the same order: null where an AST has no _meta.
meta.lib.get pkgs [ ast1 ast2 ]
# -> [ metadata-or-null, metadata-or-null ]set :: a -> AST -> AST
Attach metadata to an AST. If the AST already has _meta, set replaces it.
set returns the AST with the metadata embedded.
meta.lib.set { version = "1.0"; author = "me"; } ast
# -> ast with metadata attachedremove :: AST -> AST
Remove the first _meta binding from an AST.
If a let expression loses its last binding this way, remove drops the let and returns its body (an empty let ... in is not valid Nix).
meta.lib.remove ast
# -> ast with first _meta removednix-meta re-exports the full nix-ast API. See its documentation.
Inspect metadata across multiple files:
let
inherit (nix-meta) parse get;
# pkgs is any nixpkgs package set (parse/eval use IFD)
pkgs = nixpkgs.legacyPackages.${builtins.currentSystem};
asts = parse pkgs [
./maintainers/alice.nix # { _meta = { email = "alice@email.com"; }; outputs = { ... }; }
./maintainers/bob.nix # { outputs = { ... }; }
./maintainers/charlie.nix # { _meta = { email = "charlie@email.com"; }; outputs = { ... }; }
];
metas = get pkgs asts; # [ { email = "alice@example.com"; } null { email = "charlie@example.com"; } ]
in