Add a method to make Emacs closures from use-package declarations

This commit is contained in:
adisbladis 2019-08-19 10:58:26 +01:00
parent eb82a1c149
commit f84321f435
No known key found for this signature in database
GPG key ID: 110BFAD44C6249B7
3 changed files with 74 additions and 0 deletions

View file

@ -14,6 +14,32 @@ is updated daily.
This package is named =emacsGit= in the overlay.
** Extra library functionality
This overlay comes with an extra function to generate an Emacs closure from =use-package= declarations.
This is an abstraction on top of =emacsWithPackages=.
#+BEGIN_SRC nix
{
environment.systemPackages = [
(emacsWithPackagesUsePackage {
config = builtins.readFile ./emacs.el;
# Package is optional, defaults to pkgs.emacs
package = pkgs.emacsGit;
# Optionally provide extra packages not in the configuration file
extraEmacsPackages = epkgs: [
epkgs.cask
];
# Optionally override derivations
override = epkgs: epkgs // {
weechat = epkgs.melpaPackages.weechat.overrideAttrs(old: {
patches = [ ./weechat-el.patch ];
});
};
})
];
}
#+END_SRC
** Usage of the overlay
*** Latest master each rebuild
One way, and probably the most convenient way to pull in this overlay is by
@ -28,11 +54,13 @@ package =emacsGit= available. These of course change quite rapidly and will
cause compilation time.
#+BEGIN_SRC nix
{
nixpkgs.overlays = [
(import (builtins.fetchTarball {
url = https://github.com/nix-community/emacs-overlay/archive/master.tar.gz;
}))
];
}
#+END_SRC
# LocalWords: EXWM NixOS emacsGit

View file

@ -37,6 +37,8 @@ in {
];
});
emacsWithPackagesFromUsePackage = import ./elisp.nix { pkgs = self; };
emacsPackagesNgFor = emacs: (
(super.emacsPackagesNgFor emacs).overrideScope'(eself: esuper: let

44
elisp.nix Normal file
View file

@ -0,0 +1,44 @@
/*
Parse an emacs lisp configuration file to derive packages from
use-package declarations.
*/
{ pkgs }:
let
isStrEmpty = s: (builtins.replaceStrings [" "] [""] s) == "";
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 {
config,
extraEmacsPackages ? epkgs: [],
package ? pkgs.emacs,
override ? (epkgs: epkgs)
}: let
packages = parsePackages config;
emacsPackages = pkgs.emacsPackagesNgGen 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)