/** Build a meta-module that includes sub-modules * * Because of the way that the emacsWithPackages function works, it * can only load a single "default.el" as an entry point. * */ { pkgs, lib, ... }: rec { /** * Create a new elisp module with a set of package dependencies. * * When calling this function three arguments are required. It * returns a "module", which is an attribute set. * * { * name = "base"; * path = ./.; * pkgs = [ hello ]; * } * * The path must point to the root of the module, which is then used * as an offset. The pkgs set may contain both emacs and non-emacs * packages that the module depends on to function. depends on to * function. */ buildModule = with pkgs; (name: path: pkgs: { inherit name pkgs; path = runCommand "${name}.el" {} '' mkdir -p $out/share/emacs/site-lisp cp -r ${path}/default.el $out/share/emacs/site-lisp/${name}.el ''; }); /** * Build a bootstrap module which includes submodules * * */ bootstrap = modules: let # Take a module and unfold the paths into a list unfold = { path, pkgs, ... }: [ path ] ++ pkgs; # Create an elisp require statement mkInclude = modules: lib.concatMapStringsSep "\n" (name: "(require '${name})") modules; # Build the list of module paths mkModPaths = modules: builtins.foldl' (acc: mod: acc ++ (unfold mod)) [] modules; # Build the list of module names mkModList = modules: map (m: m.name) modules; ### Function invocations modList = mkModList modules; modPaths = mkModPaths modules; loader = pkgs.writeTextFile { name = "default.el"; text = '' ;;; THIS FILE IS AUTOMATICALLY GENERATED ${(mkInclude modList)} ''; }; loaderWrap = pkgs.runCommand "default.el" {} '' mkdir -p $out/share/emacs/site-lisp/ cp ${loader} $out/share/emacs/site-lisp/default.el ''; paths = modPaths ++ [ loaderWrap ]; in with pkgs; symlinkJoin { name = "libkookie-emacs-packages"; inherit paths; }; }