This repository provides some Nix functions for getting information of Emacs Lisp packages. It uses talyz/fromElisp parser to parse S expressions.
This repository provides functions for parsing a Cask file, a MELPA-style recipe, and a package list on ELPA. Then you can use the parsing result to inspect dependencies, fetch the source repository, and generate a list of files of the package.
It also has good support for flake references. You can get a flake reference to the source repository of a package.
The fetch functions in this package requires Nix 2.4 or later.
default.nix
in this repository provides several functions for elisp development.
You can import the repository directly:
with (import (builtins.fetchGit {
url = "https://github.com/akirak/nix-elisp-helpers.git";
ref = "master";
...
}));
Alternatively, you can use niv
to add to your repository:
niv add akirak/nix-elisp-helpers
with (import (import ./nix/sources.nix).nix-elisp-helpers { inherit pkgs; });
You can also use the functions via flake, but they are available under lib.${system}
due to an indirect dependency on nixpkgs.
parseCask
function takes a Cask
file content as an argument and returns the package data in an attribute set:
let
packageInfo = parseCask (builtins.readFile ./Cask)
in
...
development.dependencies
holds all depends-on
items in development
, e.g.:
assert (builtins.map builtins.head packageInfo.development.dependencies ==
["f" "s" "dash" "ansi" "ecukes" "servant" "ert-runner" "el-mock" "noflet" "ert-async" "shell-split-string"]);
...
parseMelpaRecipe
function takess a MELPA-style recipe string as an argument and returns its content as an attribute set:
# The file contains '(smex :repo "nonsequitur/smex" :fetcher github)'
let
package = parseMelpaRecipe (builtins.readFile ./smex);
in
...
It’s handy because it returns an attribute set:
assert (package.ename == "smex");
assert (package.repo == "nonsequitur/smex");
assert (package.fetcher == "github");
assert (package.files == null);
...
fetchTreeFromMelpaRecipe
function takes a string or attribute set for a MELPA-style recipe and fetches a snapshot of the source repository of the package.
The snapshot is stored in Nix, and the store path is returned.
fetchTreeFromMelpaRecipe (builtins.readFile ./my-package-recipe)
let
recipe = ./dash;
src = fetchTreeFromMelpaRecipe (builtins.readFile recipe);
in
pkgs.emacsPackages.melpaBuild {
pname = "dash";
version = "2.15";
# The remote source is used
inherit src recipe;
...
}
Note that this function does not work in pure evaluation mode.
You can also use flakeRefAttrsFromMelpaRecipe
function to retrieve an attribute set that can be passed to builtins.fetchTree
function which is available since Nix 2.4.
Note: Nixpkgs includes an equivalent function in pkgs/applications/editors/emacs/elixp-packages/libgenerated.nix
.
flakeRefUrlFromMelpaRecipe
function takes a recipe string as an argument and returns a URL-like flake reference:
let
recipe = ''
(smex :repo "nonsequitur/smex" :fetcher github)
'';
in
assert (flakeRefUrlFromMelpaRecipe recipe == "github:nonsequitur/smex");
...
Note that this function may not completely support all of the reference specs.
expandMelpaRecipeFiles
function expands :files
spec in a recipe under a given directory.
This is equivalent to package-build-expand-file-specs
function in package-build, which is used to build packages on MELPA:
expandMelpaRecipeFiles ./. ["*.el" [":excludes" ".dir-locals.el" "*-test.el"]]
The first argument must be a path to a directory, and the second argument can be either a list or null
. When null
is given as a spec, the default spec of MELPA is used.
It returns an attribute set of matching files relative from the directory:
{
"hello.el" = "hello.el";
"hello-utils.el" = "hello-utils.el";
}
It can be combined with parseMelpaRecipe
:
let
package = parseMelpaRecipe (builtins.readFile ./awesome-package);
files = expandMelpaRecipeFiles ./. package.files;
in
assert (files == {
"awesome-package.el" = "awesome-package.el";
"awesome-package-utils.el" = "awesome-package-utils.el";
});
...
Note: This function returned a result in the past, but it now returns an attribute set.
This library does not support 100% of the recipe format supported by MELPA.The following :fetcher
types are generally supported: github
, gitlab
, and git
. hg
may not be supported.
:url
is supported when you use git
fetcher.
:repo
is supported when you use one of github
and gitlab
fetcher types.
:branch
is supported.
:version-regexp
is not supported. Maybe coming soon.
:commit
is supported.
:files
is supported.
Parse an ELPA-style package list (example) and returns an attribute set.
packages = parseElpaPackages (builtins.readFile ./elpa-packages)
Each value in the attribute set (which should be originally a plist) is converted to an attribute set:
assert (packages.ztree.url == "https://github.com/fourier/ztree");
...
flakeRefAttrsFromElpaAttrs
takes an attribute set from a value in the result of parseElpaPackages
and returns an attribute set that can be passed to builtins.fetchTree
:
let
packages = parseElpaPackages (builtins.readFile ./elpa-packages);
in
builtins.fetchTree (flakeRefAttrsFromElpaAttrs {} packages.ztree)
The first argument is an attribute set which can consist of the following options:
- If
preferReleaseBranch
is true,:release-branch
is chosen as the branch if there is one.
parsePkg
parses the content of a *-pkg.el
file.
let
description = parsePkg ''
(define-package "my-package" "0.5"
"My first package"
'((emacs "26.2")
(dash "2.18")))
'';
in
..
{
ename = "my-package";
version = "0.5";
summary = "My first package";
packageRequires = {
emacs = "26.2";
dash = "2.18";
};
}
If the package description has no field for the requirements, the value of packageRequires
attribute will become null.
Note the attribute names follow the conventions used by parseMelpaRecipe
if applicable.
flakeRefUrlFromFlakeRefAttrs
converts an attribute set to its equivalent URL-style representation.
This project uses talyz/fromElisp for parsing Emacs Lisp expressions in Nix.