about summary refs log tree commit diff
path: root/parse.nix
diff options
context:
space:
mode:
authorSteve Purcell <steve@sanityinc.com>2020-06-20 15:24:47 +1200
committerSteve Purcell <steve@sanityinc.com>2020-06-20 15:54:57 +1200
commit8439afbe1e1fca1b64c91aac302764d465212bca (patch)
treee6110f0278d5d5355ba08270c08cc652657d8625 /parse.nix
parent49597c22188e20dc05a7dcf2cfbe6f12162a7ed1 (diff)
downloadnixlib-8439afbe1e1fca1b64c91aac302764d465212bca.tar
nixlib-8439afbe1e1fca1b64c91aac302764d465212bca.tar.gz
nixlib-8439afbe1e1fca1b64c91aac302764d465212bca.tar.bz2
nixlib-8439afbe1e1fca1b64c91aac302764d465212bca.tar.lz
nixlib-8439afbe1e1fca1b64c91aac302764d465212bca.tar.xz
nixlib-8439afbe1e1fca1b64c91aac302764d465212bca.tar.zst
nixlib-8439afbe1e1fca1b64c91aac302764d465212bca.zip
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.
Diffstat (limited to 'parse.nix')
-rw-r--r--parse.nix61
1 files changed, 61 insertions, 0 deletions
diff --git a/parse.nix b/parse.nix
new file mode 100644
index 000000000000..9fbe7c747389
--- /dev/null
+++ b/parse.nix
@@ -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;
+}