mirror of
https://github.com/nix-community/emacs-overlay.git
synced 2025-12-06 02:40:25 -08:00
Add emacsWithPackagesFromPackageRequires
This provides a mechanism for creating an Emacs closure that contains the runtime dependencies for a given Emacs package source file, by inspecting its Package-Requires header.
This commit is contained in:
parent
49597c2218
commit
8439afbe1e
5 changed files with 115 additions and 26 deletions
26
README.org
26
README.org
|
|
@ -28,8 +28,12 @@ We also provide two attributes named =emacsGit-nox= and =emacsUnstable-nox=
|
||||||
if you wish to have Emacs built without X dependencies.
|
if you wish to have Emacs built without X dependencies.
|
||||||
|
|
||||||
** Extra library functionality
|
** Extra library functionality
|
||||||
This overlay comes with an extra function to generate an Emacs closure from =use-package= declarations.
|
This overlay comes with extra functions to generate an Emacs closure
|
||||||
This is an abstraction on top of =emacsWithPackages=.
|
from various types of dependency declaration. (These are abstractions
|
||||||
|
on top of =emacsWithPackages=.)
|
||||||
|
|
||||||
|
For example, =emacsWithPackagesFromUsePackage= adds packages which are required in a user's config via =use-package=:
|
||||||
|
|
||||||
#+BEGIN_SRC nix
|
#+BEGIN_SRC nix
|
||||||
{
|
{
|
||||||
environment.systemPackages = [
|
environment.systemPackages = [
|
||||||
|
|
@ -52,6 +56,24 @@ This is an abstraction on top of =emacsWithPackages=.
|
||||||
}
|
}
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
|
Similarly, =emacsWithPackagesFromPackageRequires= adds packages which
|
||||||
|
are declared in a =.el= package file's =Package-Requires= header, which
|
||||||
|
can be handy for CI purposes:
|
||||||
|
|
||||||
|
#+BEGIN_SRC nix
|
||||||
|
...
|
||||||
|
let
|
||||||
|
emacsForCI = pkgs.emacsWithPackagesFromPackageRequires {
|
||||||
|
packageFile = builtins.readFile ./flycheck.el;
|
||||||
|
extraEmacsPackages = epkgs: [
|
||||||
|
epkgs.package-lint
|
||||||
|
];
|
||||||
|
};
|
||||||
|
pkgs.mkShell {
|
||||||
|
buildInputs = [ emacsForCI ];
|
||||||
|
}
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
|
||||||
** Usage of the overlay
|
** Usage of the overlay
|
||||||
*** Latest master each rebuild
|
*** Latest master each rebuild
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,6 @@ let
|
||||||
|
|
||||||
buildInputs = old.buildInputs ++ [ self.libgccjit ];
|
buildInputs = old.buildInputs ++ [ self.libgccjit ];
|
||||||
});
|
});
|
||||||
|
|
||||||
in {
|
in {
|
||||||
inherit emacsGit emacsUnstable;
|
inherit emacsGit emacsUnstable;
|
||||||
|
|
||||||
|
|
@ -106,6 +105,8 @@ in {
|
||||||
|
|
||||||
emacsWithPackagesFromUsePackage = import ./elisp.nix { pkgs = self; };
|
emacsWithPackagesFromUsePackage = import ./elisp.nix { pkgs = self; };
|
||||||
|
|
||||||
|
emacsWithPackagesFromPackageRequires = import ./packreq.nix { pkgs = self; };
|
||||||
|
|
||||||
emacsPackagesFor = emacs: (
|
emacsPackagesFor = emacs: (
|
||||||
(super.emacsPackagesFor emacs).overrideScope'(eself: esuper: let
|
(super.emacsPackagesFor emacs).overrideScope'(eself: esuper: let
|
||||||
|
|
||||||
|
|
|
||||||
25
elisp.nix
25
elisp.nix
|
|
@ -6,35 +6,14 @@ use-package declarations.
|
||||||
{ pkgs }:
|
{ pkgs }:
|
||||||
|
|
||||||
let
|
let
|
||||||
isStrEmpty = s: (builtins.replaceStrings [" "] [""] s) == "";
|
parse = pkgs.callPackage ./parse.nix {};
|
||||||
|
|
||||||
splitString = _sep: _s: builtins.filter
|
|
||||||
(x: builtins.typeOf x == "string")
|
|
||||||
(builtins.split _sep _s);
|
|
||||||
|
|
||||||
stripComments = dotEmacs: let
|
|
||||||
lines = splitString "\n" dotEmacs;
|
|
||||||
stripped = builtins.map (l:
|
|
||||||
builtins.elemAt (splitString ";;" l) 0) lines;
|
|
||||||
in builtins.concatStringsSep " " stripped;
|
|
||||||
|
|
||||||
parsePackages = dotEmacs: let
|
|
||||||
strippedComments = stripComments dotEmacs;
|
|
||||||
tokens = builtins.filter (t: !(isStrEmpty t)) (builtins.map
|
|
||||||
(t: if builtins.typeOf t == "list" then builtins.elemAt t 0 else t)
|
|
||||||
(builtins.split "([\(\)])" strippedComments));
|
|
||||||
matches = builtins.map (t:
|
|
||||||
builtins.match "^use-package[[:space:]]+([A-Za-z0-9_-]+).*" t) tokens;
|
|
||||||
in builtins.map (m: builtins.elemAt m 0)
|
|
||||||
(builtins.filter (m: m != null) matches);
|
|
||||||
|
|
||||||
in {
|
in {
|
||||||
config,
|
config,
|
||||||
extraEmacsPackages ? epkgs: [],
|
extraEmacsPackages ? epkgs: [],
|
||||||
package ? pkgs.emacs,
|
package ? pkgs.emacs,
|
||||||
override ? (epkgs: epkgs)
|
override ? (epkgs: epkgs)
|
||||||
}: let
|
}: let
|
||||||
packages = parsePackages config;
|
packages = parse.parsePackagesFromUsePackage config;
|
||||||
emacsPackages = pkgs.emacsPackagesGen package;
|
emacsPackages = pkgs.emacsPackagesGen package;
|
||||||
emacsWithPackages = emacsPackages.emacsWithPackages;
|
emacsWithPackages = emacsPackages.emacsWithPackages;
|
||||||
in emacsWithPackages (epkgs: let
|
in emacsWithPackages (epkgs: let
|
||||||
|
|
|
||||||
26
packreq.nix
Normal file
26
packreq.nix
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
Parse an emacs package file to derive packages from
|
||||||
|
Package-Requires declarations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
{ pkgs }:
|
||||||
|
let
|
||||||
|
parse = pkgs.callPackage ./parse.nix { };
|
||||||
|
in
|
||||||
|
{ packageFile
|
||||||
|
, extraEmacsPackages ? epkgs: [ ]
|
||||||
|
, package ? pkgs.emacs
|
||||||
|
, override ? (epkgs: epkgs)
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
packages = parse.parsePackagesFromPackageRequires packageFile;
|
||||||
|
emacsPackages = pkgs.emacsPackagesGen package;
|
||||||
|
emacsWithPackages = emacsPackages.emacsWithPackages;
|
||||||
|
in
|
||||||
|
emacsWithPackages (epkgs:
|
||||||
|
let
|
||||||
|
overriden = override epkgs;
|
||||||
|
usePkgs = builtins.map (name: overriden.${name}) packages;
|
||||||
|
extraPkgs = extraEmacsPackages overriden;
|
||||||
|
in
|
||||||
|
[ overriden.use-package ] ++ usePkgs ++ extraPkgs)
|
||||||
61
parse.nix
Normal file
61
parse.nix
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
{ lib }:
|
||||||
|
let
|
||||||
|
isStrEmpty = s: (builtins.replaceStrings [ " " ] [ "" ] s) == "";
|
||||||
|
|
||||||
|
splitString = _sep: _s: builtins.filter
|
||||||
|
(x: builtins.typeOf x == "string")
|
||||||
|
(builtins.split _sep _s);
|
||||||
|
|
||||||
|
parsePackagesFromPackageRequires = packageFile:
|
||||||
|
let
|
||||||
|
lines = splitString "\r?\n" packageFile;
|
||||||
|
requires =
|
||||||
|
lib.concatMapStrings
|
||||||
|
(line:
|
||||||
|
let match = builtins.match "^;;;* *[pP]ackage-[rR]equires *: *\\((.*)\\)" line;
|
||||||
|
in if match == null then "" else builtins.head match)
|
||||||
|
lines;
|
||||||
|
parseReqList = s:
|
||||||
|
let matchAndRest = builtins.match " *\\(? *([^ \"\\)]+)( +\"[^\"]+\" *\\))?(.*)" s;
|
||||||
|
in
|
||||||
|
if isStrEmpty s then
|
||||||
|
[ ]
|
||||||
|
else
|
||||||
|
if matchAndRest == null then
|
||||||
|
throw "Failed to parse package requirements list: ${s}"
|
||||||
|
else
|
||||||
|
[ (builtins.head matchAndRest) ] ++ (parseReqList (builtins.elemAt matchAndRest 2));
|
||||||
|
in
|
||||||
|
parseReqList requires;
|
||||||
|
|
||||||
|
stripComments = dotEmacs:
|
||||||
|
let
|
||||||
|
lines = splitString "\n" dotEmacs;
|
||||||
|
stripped = builtins.map
|
||||||
|
(l:
|
||||||
|
builtins.elemAt (splitString ";;" l) 0)
|
||||||
|
lines;
|
||||||
|
in
|
||||||
|
builtins.concatStringsSep " " stripped;
|
||||||
|
|
||||||
|
parsePackagesFromUsePackage = dotEmacs:
|
||||||
|
let
|
||||||
|
strippedComments = stripComments dotEmacs;
|
||||||
|
tokens = builtins.filter (t: !(isStrEmpty t)) (builtins.map
|
||||||
|
(t: if builtins.typeOf t == "list" then builtins.elemAt t 0 else t)
|
||||||
|
(builtins.split "([\(\)])" strippedComments)
|
||||||
|
);
|
||||||
|
matches = builtins.map
|
||||||
|
(t:
|
||||||
|
builtins.match "^use-package[[:space:]]+([A-Za-z0-9_-]+).*" t)
|
||||||
|
tokens;
|
||||||
|
in
|
||||||
|
builtins.map
|
||||||
|
(m: builtins.elemAt m 0)
|
||||||
|
(builtins.filter (m: m != null) matches);
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
inherit parsePackagesFromPackageRequires;
|
||||||
|
inherit parsePackagesFromUsePackage;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue