Skip to content

Commit

Permalink
Option to install R packages from DESCRIPTION file
Browse files Browse the repository at this point in the history
  • Loading branch information
pchabros committed Nov 24, 2024
1 parent 6f9f633 commit 6abf2ca
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 3 deletions.
9 changes: 9 additions & 0 deletions examples/r/.test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
set -ex

R --version
radian --version

for package in readr stringr data.table yaml testthat; do
Rscript -e "library($package)"
done
14 changes: 14 additions & 0 deletions examples/r/DESCRIPTION
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Type: Package
Package: myPackage
Title: Devenv test R Package
Version: 0.0.0.1
Imports:
readr,
stringr,
nonexistentpackage
Depends:
data.table,
yaml
Suggests:
testthat (>= 3.0.0)
Encoding: UTF-8
4 changes: 4 additions & 0 deletions examples/r/devenv.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,9 @@
enable = true;
package = pkgs.python312Packages.radian;
};
descriptionFile = {
path = "${./DESCRIPTION}";
installPackages.enable = true;
};
};
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
{ pkgs, config, lib, ... }:

{ pkgs
, config
, lib
, ...
}:
let
cfg = config.languages.r;
descriptionFile = import ./descriptionFile.nix;
in
{
options.languages.r = {
Expand All @@ -21,9 +25,23 @@ in
description = "The radian package to use.";
};
};
descriptionFile = {
path = lib.mkOption {
type = lib.types.pathInStore;
description = "Path to DESCRIPTION file";
};
installPackages = {
enable = lib.mkEnableOption "installation of R packages listed in DESCRIPTION file";
};
};
};

config = lib.mkIf cfg.enable {
packages = with pkgs; [ cfg.package ] ++ lib.lists.optional cfg.radian.enable cfg.radian.package;
packages =
[ cfg.package ]
++ lib.lists.optional cfg.radian.enable cfg.radian.package
++ lib.lists.optionals cfg.descriptionFile.installPackages.enable (
descriptionFile.getRPackages pkgs (builtins.readFile cfg.descriptionFile.path)
);
};
}
42 changes: 42 additions & 0 deletions src/modules/languages/r/descriptionFile.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
let
strings = import ./utils/strings.nix;
inherit (builtins)
concatMap
filter
hasAttr
replaceStrings
warn
;
inherit (strings)
matches
extractWithRegex
splitWithRegex
;
in
rec {
getSection =
section: descriptionFile:
extractWithRegex ".*${section}:\n +([a-zA-Z0-9., (>=)\n]*)\n[A-Z].*" descriptionFile;
extractPackages = packages: filter (matches "^[a-zA-Z0-9.]+") packages;
extractSectionPackages = section: extractPackages (splitWithRegex "[\n, ]+" section);
descriptionPackages =
descriptionFile:
concatMap (section: extractSectionPackages (getSection section descriptionFile)) [
"Imports"
"Depends"
"Suggests"
];
normalizePackageName = pkg: replaceStrings [ "." ] [ "_" ] pkg;
getRPackage =
pkg: pkgs:
let
pkgName = normalizePackageName pkg;
in
if hasAttr pkgName pkgs.rPackages then
pkgs.rPackages.${pkgName}
else
warn "Package \"${pkgName}\" does not exist in nixpkgs." null;
getRPackages =
pkgs: descriptionFile:
filter (pkg: pkg != null) (map (pkg: getRPackage pkg pkgs) (descriptionPackages descriptionFile));
}
23 changes: 23 additions & 0 deletions src/modules/languages/r/utils/strings.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
let
inherit (builtins)
filter
head
isNull
isString
match
split
;
in
{
# matches :: string -> string -> bool
matches = pattern: text: !isNull (match "(${pattern})" text);
# extractWithRegex :: string -> string -> string
extractWithRegex =
regex: string:
let
matched = match regex string;
in
if isNull matched then "" else head matched;
# splitWithRegex :: string -> string -> [string]
splitWithRegex = regex: string: filter isString (split regex string);
}

0 comments on commit 6abf2ca

Please sign in to comment.