init
This commit is contained in:
commit
0e5218513e
4 changed files with 128 additions and 0 deletions
11
CMakeLists.txt
Normal file
11
CMakeLists.txt
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
cmake_minimum_required(VERSION 3.9)
|
||||
project(nix-scope-plugin)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(NIX_EXPR REQUIRED IMPORTED_TARGET nix-expr)
|
||||
|
||||
add_library(nix-scope-plugin MODULE scope.cc)
|
||||
target_link_libraries(nix-scope-plugin PkgConfig::NIX_EXPR)
|
||||
set_target_properties(nix-scope-plugin PROPERTIES PREFIX "lib")
|
||||
|
||||
install(TARGETS nix-scope-plugin DESTINATION lib/nix/plugins)
|
||||
27
flake.lock
generated
Normal file
27
flake.lock
generated
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1771923393,
|
||||
"narHash": "sha256-Fy0+UXELv9hOE8WjYhJt8fMDLYTU2Dqn3cX4BwoGBos=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "ea7f1f06811ce7fcc81d6c6fd4213150c23edcf2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
38
flake.nix
Normal file
38
flake.nix
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
description = "Nix plugin providing a `scope` builtin for constructing nested attrsets from dotted paths";
|
||||
|
||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||
|
||||
outputs = { self, nixpkgs }:
|
||||
let
|
||||
supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
|
||||
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
|
||||
in
|
||||
{
|
||||
packages = forAllSystems (system:
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
nix = pkgs.nix;
|
||||
in
|
||||
{
|
||||
default = pkgs.stdenv.mkDerivation {
|
||||
pname = "nix-scope-plugin";
|
||||
version = "0.1.0";
|
||||
src = self;
|
||||
nativeBuildInputs = [ pkgs.cmake pkgs.pkg-config ];
|
||||
buildInputs = [ nix nix.dev pkgs.boost pkgs.nlohmann_json ];
|
||||
};
|
||||
});
|
||||
|
||||
devShells = forAllSystems (system:
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages.${system};
|
||||
nix = pkgs.nix;
|
||||
in
|
||||
{
|
||||
default = pkgs.mkShell {
|
||||
packages = [ pkgs.cmake pkgs.pkg-config nix nix.dev pkgs.boost pkgs.nlohmann_json ];
|
||||
};
|
||||
});
|
||||
};
|
||||
}
|
||||
52
scope.cc
Normal file
52
scope.cc
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#include <nix/expr/primops.hh>
|
||||
#include <nix/expr/eval.hh>
|
||||
#include <nix/expr/eval-inline.hh>
|
||||
#include <nix/expr/nixexpr.hh>
|
||||
#include <nix/expr/attr-set.hh>
|
||||
|
||||
using namespace nix;
|
||||
|
||||
static void prim_scope(EvalState & state, const PosIdx pos, Value ** args, Value & v)
|
||||
{
|
||||
std::vector<Symbol> path;
|
||||
|
||||
state.forceStringNoCtx(*args[0], pos, "'scope' path argument");
|
||||
auto s = std::string(args[0]->string_view());
|
||||
if (s.empty())
|
||||
state.error<TypeError>("'scope' requires a non-empty path")
|
||||
.atPos(pos)
|
||||
.debugThrow();
|
||||
size_t start = 0;
|
||||
while (start < s.size()) {
|
||||
auto dot = s.find('.', start);
|
||||
if (dot == std::string::npos) {
|
||||
path.push_back(state.symbols.create(s.substr(start)));
|
||||
break;
|
||||
}
|
||||
path.push_back(state.symbols.create(s.substr(start, dot - start)));
|
||||
start = dot + 1;
|
||||
}
|
||||
|
||||
// Build nested attrset from inside out
|
||||
// Given path [a, b, c] and value v: { a = { b = { c = v; }; }; }
|
||||
Value * inner = args[1];
|
||||
for (auto it = path.rbegin(); it != path.rend(); ++it) {
|
||||
auto attrs = state.buildBindings(1);
|
||||
attrs.insert(*it, inner);
|
||||
Value * wrapper = state.allocValue();
|
||||
wrapper->mkAttrs(attrs.finish());
|
||||
inner = wrapper;
|
||||
}
|
||||
v = *inner;
|
||||
}
|
||||
|
||||
static RegisterPrimOp rp({
|
||||
.name = "scope",
|
||||
.args = {"path", "value"},
|
||||
.doc = R"(
|
||||
Construct a nested attribute set from a dotted string path and a value.
|
||||
|
||||
Example: `scope "a.b.c" 42` evaluates to `{ a = { b = { c = 42; }; }; }`.
|
||||
)",
|
||||
.fun = prim_scope,
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue