118 lines
3.8 KiB
Nix
118 lines
3.8 KiB
Nix
/*
|
|
|
|
# Usage
|
|
|
|
`emacsWithPackages` takes a single argument: a function from a package
|
|
set to a list of packages (the packages that will be available in
|
|
Emacs). For example,
|
|
```
|
|
emacsWithPackages (epkgs: [ epkgs.evil epkgs.magit ])
|
|
```
|
|
All the packages in the list should come from the provided package
|
|
set. It is possible to add any package to the list, but the provided
|
|
set is guaranteed to have consistent dependencies and be built with
|
|
the correct version of Emacs.
|
|
|
|
# Overriding
|
|
|
|
`emacsWithPackages` inherits the package set which contains it, so the
|
|
correct way to override the provided package set is to override the
|
|
set which contains `emacsWithPackages`. For example, to override
|
|
`emacsPackagesNg.emacsWithPackages`,
|
|
```
|
|
let customEmacsPackages =
|
|
emacsPackagesNg.override (super: self: {
|
|
# use a custom version of emacs
|
|
emacs = ...;
|
|
# use the unstable MELPA version of magit
|
|
magit = self.melpaPackages.magit;
|
|
});
|
|
in customEmacsPackages.emacsWithPackages (epkgs: [ epkgs.evil epkgs.magit ])
|
|
```
|
|
|
|
*/
|
|
|
|
{ lib, makeWrapper, stdenv }: self:
|
|
|
|
with lib; let inherit (self) emacs; in
|
|
|
|
packagesFun: # packages explicitly requested by the user
|
|
|
|
let
|
|
explicitRequires =
|
|
if builtins.isFunction packagesFun
|
|
then packagesFun self
|
|
else packagesFun;
|
|
in
|
|
|
|
stdenv.mkDerivation {
|
|
name = (appendToName "with-packages" emacs).name;
|
|
nativeBuildInputs = [ emacs makeWrapper ];
|
|
inherit emacs explicitRequires;
|
|
phases = [ "installPhase" ];
|
|
installPhase = ''
|
|
requires=""
|
|
for pkg in $explicitRequires; do
|
|
findInputs $pkg requires propagated-user-env-packages
|
|
done
|
|
# requires now holds all requested packages and their transitive dependencies
|
|
|
|
siteStart="$out/share/emacs/site-lisp/site-start.el"
|
|
|
|
addEmacsPath() {
|
|
local list=$1
|
|
local path=$2
|
|
# Add the path to the search path list, but only if it exists
|
|
if [[ -d "$path" ]]; then
|
|
echo "(add-to-list '$list \"$path\")" >>"$siteStart"
|
|
fi
|
|
}
|
|
|
|
# Add a dependency's paths to site-start.el
|
|
addToEmacsPaths() {
|
|
addEmacsPath "exec-path" "$1/bin"
|
|
addEmacsPath "load-path" "$1/share/emacs/site-lisp"
|
|
addEmacsPath "package-directory-list" "$1/share/emacs/site-lisp/elpa"
|
|
}
|
|
|
|
mkdir -p $out/share/emacs/site-lisp
|
|
# Begin the new site-start.el by loading the original, which sets some
|
|
# NixOS-specific paths. Paths are searched in the reverse of the order
|
|
# they are specified in, so user and system profile paths are searched last.
|
|
echo "(load-file \"$emacs/share/emacs/site-lisp/site-start.el\")" >"$siteStart"
|
|
echo "(require 'package)" >>"$siteStart"
|
|
|
|
# Set paths for the dependencies of the requested packages. These paths are
|
|
# searched before the profile paths, but after the explicitly-required paths.
|
|
for pkg in $requires; do
|
|
# The explicitly-required packages are also in the list, but we will add
|
|
# those paths last.
|
|
if ! ( echo "$explicitRequires" | grep "$pkg" >/dev/null ) ; then
|
|
addToEmacsPaths $pkg
|
|
fi
|
|
done
|
|
|
|
# Finally, add paths for all the explicitly-required packages. These paths
|
|
# will be searched first.
|
|
for pkg in $explicitRequires; do
|
|
addToEmacsPaths $pkg
|
|
done
|
|
|
|
# Byte-compiling improves start-up time only slightly, but costs nothing.
|
|
emacs --batch -f batch-byte-compile "$siteStart"
|
|
|
|
mkdir -p $out/bin
|
|
# Wrap emacs and friends so they find our site-start.el before the original.
|
|
for prog in $emacs/bin/*; do # */
|
|
makeWrapper "$prog" $out/bin/$(basename "$prog") \
|
|
--suffix EMACSLOADPATH ":" "$out/share/emacs/site-lisp:"
|
|
done
|
|
|
|
mkdir -p $out/share
|
|
# Link icons and desktop files into place
|
|
for dir in applications icons info man; do
|
|
ln -s $emacs/share/$dir $out/share/$dir
|
|
done
|
|
'';
|
|
inherit (emacs) meta;
|
|
}
|