Low-level nix integration to straight.el

This commit is contained in:
László Vaskó
2019-10-20 22:22:09 +02:00
committed by László Vaskó
parent 41090724c9
commit a5d40e9754
5 changed files with 211 additions and 1 deletions

View File

@ -1 +1,5 @@
# nix-straight.el
# nix-straight.el
Low-level integration to [straight.el](https://github.com/raxod502/straight.el)
See [nix-doom-emacs](https://github.com/vlaci/nix-doom-emacs) for a usage example.

73
default.nix Normal file
View File

@ -0,0 +1,73 @@
{ # Package set to build the Emacs environment from
emacsPackages
# You may override to use your version of `straight`
, straight ? null
# Your `init.el` file to use for discovering and installing packages
, emacsInitFile
# Additional argument to pass to Emacs or your init file
, emacsArgs ? []
# Additional files you wish to load prior to executing package discovery
# Good place to place to call `advice-add` from
, emacsLoadFiles ? [] }:
let
libstraight = epkgs.callPackage ./libstraight.nix { inherit epkgs; };
epkgs =
if straight == null then
emacsPackages.overrideScope' (self: super:
{ straight = self.callPackage ./straight { }; })
else
emacsPackages;
packageJSON = libstraight.packagesJSON {
inherit emacsInitFile emacsLoadFiles emacsArgs;
};
packageList = override:
libstraight.parsePackagesJSON (packageJSON.overrideAttrs override);
emacsEnv = libstraight.emacsEnv { inherit emacsInitFile emacsLoadFiles emacsArgs; };
in {
/* Final environment (.emacs.d) with the populated `straight`` repository
The required packages can be acquired from a call to
`packageList` function.
Type: emacsEnv :: { straightDir :: string, packages :: [derivation] } -> derivation
Example:
emacsEnv {
straightDir = "$out/straight";
packages = packageList (super: { ... } );
};
*/
inherit emacsEnv;
/* Package list inferred from processing `emacsInitFile`
The passed function will be called via an `overrideAttrs
call on the`underlying derivation.
Type: packageList :: attrs -> attrs -> derivation
Example:
packageList (super: {
src = ...;
preInstall = ''
...
''
});
*/
inherit packageList;
/* JSON formatted list of packages
These are the packages needed to be populated in the
`straight` repository. Mostly for diagnostic purposes.
Type: packageJSON :: derivation
*/
inherit packageJSON;
}

82
libstraight.nix Normal file
View File

@ -0,0 +1,82 @@
{ lib, stdenv, epkgs, writeScript }:
let
inherit (builtins) filter trace;
inherit (lib) concatMapStringsSep escapeShellArgs importJSON flatten unique optionalString;
expandDependencies = packages:
let
withDeps = p:
map (x:
if x == null then [ ] else
[ x ] ++ withDeps x.propagatedBuildInputs
) (flatten p);
in (unique (filter (d: d ? ename) (flatten (withDeps packages))));
install = repo: packages:
let
installPkg = repo: pkg: (''
REPO=${repo}
psrc=(${pkg}/share/emacs/*/*/${pkg.ename}*)
if [[ ! -d $psrc ]]; then
ln -snf ${pkg}/share/emacs/site-lisp $REPO/${pkg.ename}
else
ln -snf $psrc $REPO/${pkg.ename}
fi
${optionalString (pkg.src.meta ? homepage) ''
if [[ ! -d $REPO/${baseNameOf pkg.src.meta.homepage} ]]; then
ln -snf $psrc $REPO/${baseNameOf pkg.src.meta.homepage}
fi
''}
'');
in writeScript "install-repo" ''
mkdir -p ${repo}
${(concatMapStringsSep "\n" (installPkg repo) (expandDependencies packages))}
'';
parsePackagesJSON = json:
let
list = importJSON json;
in map (x:
if epkgs ? "${x}" then epkgs.${x}
else (trace "XXX no attribute found for use-package ${x}") null) list;
packagesJSON = { emacsInitFile, emacsLoadFiles, emacsArgs }: stdenv.mkDerivation {
name = "emacs-straight-packages.json";
buildInputs = [ epkgs.emacs ];
buildPhase = ":";
installPhase = ''
runHook preInstall
emacs -q \
--batch \
--directory=${epkgs.straight}/share/emacs/site-lisp \
--load=${./setup.el} \
${concatMapStringsSep "\n" (f: "--load=${f}") emacsLoadFiles} \
--eval="(nix-straight-get-used-packages \"${emacsInitFile}\")" \
${escapeShellArgs emacsArgs} > $out
runHook postInstall
'';
};
emacsEnv = { emacsInitFile, emacsLoadFiles, emacsArgs }: { packages, straightDir }: stdenv.mkDerivation {
name = "straight-emacs-env";
buildPhase = ":";
buildInputs = [ epkgs.emacs ];
installPhase = ''
runHook preInstall
mkdir -p $out
${(install "${straightDir}/repos" packages)}
emacs -q \
--batch \
--directory=${epkgs.straight}/share/emacs/site-lisp \
--load=${./setup.el} \
${concatMapStringsSep "\n" (f: "--load=${f}") emacsLoadFiles} \
--eval="(nix-straight-build-packages \"${emacsInitFile}\")" ${escapeShellArgs emacsArgs}
runHook postInstall
'';
};
in {
inherit install parsePackagesJSON packagesJSON emacsEnv;
}

39
setup.el Normal file
View File

@ -0,0 +1,39 @@
;;; -*- lexical-binding: t; -*-
(require 'json)
(require 'straight)
(defun nix-straight-get-used-packages (init-file)
(let ((nix-straight--packages nil))
(advice-add 'straight-use-package
:override (lambda (recipe &rest r)
(let ((pkg (if (listp recipe)
(car recipe)
recipe)))
(message "straight-use-package %s %s; pkg=%s" recipe r pkg)
(add-to-list 'nix-straight--packages pkg))))
(advice-add 'straight-recipes-retrieve
:override (lambda (pkg)
(list)))
(load init-file nil nil t)
(princ (if (null nix-straight--packages)
"[]"
(json-encode nix-straight--packages)))
nix-straight--packages))
(defun nix-straight-build-packages (init-file)
(setq straight-default-files-directive '("*" (:exclude "*.elc")))
(advice-add 'straight-vc-git-clone
:override (lambda (&rest r)))
(advice-add 'straight-recipes-retrieve
:override (lambda (pkg &rest r)
(message " Crafting recipe %s" pkg)
(if (file-exists-p (straight--repos-dir (format "%s" pkg)))
`(,pkg :local-repo ,(format "%s" pkg))
(message " --> Repo directory for package not exists, assuming built-in; %s" pkg)
`(,pkg :type built-in))))
(load init-file nil nil t))
(provide 'setup)
;;; setup.el ends here

12
straight/default.nix Normal file
View File

@ -0,0 +1,12 @@
{ fetchFromGitHub, trivialBuild }:
trivialBuild rec {
pname = "straight.el";
ename = pname;
src = fetchFromGitHub {
owner = "raxod502";
repo = "straight.el";
rev = "388bf37f30f0934c8ef1b52edfd65875e945da21";
sha256 = "1d8kg63yamkanrx6l8mi8ybj2xb8zmkhqc10q5p3xn319gs36jgp";
};
}