mirror of
https://github.com/emacs-twist/org-babel.git
synced 2024-12-14 11:07:30 +00:00
Initial commit
This commit is contained in:
commit
16c3622825
12 changed files with 195 additions and 0 deletions
7
flake.lock
Normal file
7
flake.lock
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"nodes": {
|
||||
"root": {}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
5
flake.nix
Normal file
5
flake.nix
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
description = "Nix library for extracting source blocks from Org";
|
||||
|
||||
outputs = { ... }: { lib = import ./nix; };
|
||||
}
|
18
nix/default.nix
Normal file
18
nix/default.nix
Normal file
|
@ -0,0 +1,18 @@
|
|||
with builtins;
|
||||
let
|
||||
excludeOrgSubtreesOnHeadlines = import ./excludeOrgSubtreesOnHeadlines.nix;
|
||||
|
||||
matchOrgTag = import ./matchOrgTag.nix;
|
||||
matchOrgHeadline = import ./matchOrgHeadline.nix;
|
||||
matchOrgHeadlines = headlines: s:
|
||||
builtins.any (t: matchOrgHeadline t s) headlines;
|
||||
|
||||
tangleOrgBabel = pkgs.callPackage ./tangleOrgBabel.nix {
|
||||
processLines = processOrgLines;
|
||||
};
|
||||
in
|
||||
{
|
||||
inherit matchOrgTag matchOrgHeadline matchOrgHeadlines;
|
||||
inherit excludeOrgSubtreesOnHeadlines;
|
||||
inherit tangleOrgBabel;
|
||||
}
|
8
nix/dropUntil.nix
Normal file
8
nix/dropUntil.nix
Normal file
|
@ -0,0 +1,8 @@
|
|||
pred: items:
|
||||
with builtins;
|
||||
let
|
||||
xs = import ./dropWhile.nix (x: ! (pred x)) items;
|
||||
in
|
||||
if length xs > 0
|
||||
then tail xs
|
||||
else [ ]
|
11
nix/dropWhile.nix
Normal file
11
nix/dropWhile.nix
Normal file
|
@ -0,0 +1,11 @@
|
|||
pred:
|
||||
with builtins;
|
||||
let
|
||||
go = items:
|
||||
if length items == 0
|
||||
then [ ]
|
||||
else if ! (pred (head items))
|
||||
then items
|
||||
else go (tail items);
|
||||
in
|
||||
go
|
37
nix/excludeOrgSubtreesOnHeadlines.nix
Normal file
37
nix/excludeOrgSubtreesOnHeadlines.nix
Normal file
|
@ -0,0 +1,37 @@
|
|||
# Exclude lines of Org subtrees by a heading predicate
|
||||
pred:
|
||||
with builtins;
|
||||
let
|
||||
dropWhile = import ./dropWhile.nix;
|
||||
|
||||
splitListWith = import ./splitWith.nix;
|
||||
|
||||
isHeadline = s: substring 0 1 s == "*";
|
||||
|
||||
genericHeadlineRegexp = "(\\*+)[[:space:]].+";
|
||||
|
||||
getHeadlineLevel = headline:
|
||||
stringLength (head (match genericHeadlineRegexp headline));
|
||||
|
||||
prependOptionalStars = n: rest:
|
||||
if n == 0
|
||||
then rest
|
||||
else prependOptionalStars (n - 1) ("\\*?" + rest);
|
||||
|
||||
makeSubtreeEndRegexp = outlineLevel:
|
||||
prependOptionalStars (outlineLevel - 1) "\\*[[:space:]].+";
|
||||
|
||||
dropTillSubtreeEnd = level:
|
||||
dropWhile (s: !(isHeadline s && match (makeSubtreeEndRegexp level) s != null));
|
||||
|
||||
go_ = cut:
|
||||
cut.before
|
||||
++
|
||||
(if cut.sep == null
|
||||
then [ ]
|
||||
else go (dropTillSubtreeEnd (getHeadlineLevel cut.sep) cut.after));
|
||||
|
||||
go = lines: go_ (splitListWith (s: isHeadline s && pred s) lines);
|
||||
|
||||
in
|
||||
go
|
4
nix/matchOrgHeadline.nix
Normal file
4
nix/matchOrgHeadline.nix
Normal file
|
@ -0,0 +1,4 @@
|
|||
headlineText: s:
|
||||
builtins.match
|
||||
"\\*+[[:space:]]+${headlineText}([[:space:]]+:[^[:space:]]+:)?[[:space:]]*"
|
||||
s != null
|
4
nix/matchOrgTag.nix
Normal file
4
nix/matchOrgTag.nix
Normal file
|
@ -0,0 +1,4 @@
|
|||
tag: s:
|
||||
builtins.match
|
||||
"\\*+[[:space:]].+:${tag}:.*"
|
||||
s != null
|
11
nix/splitWith.nix
Normal file
11
nix/splitWith.nix
Normal file
|
@ -0,0 +1,11 @@
|
|||
pred:
|
||||
with builtins;
|
||||
let
|
||||
go = before: rest:
|
||||
if (length rest == 0)
|
||||
then { inherit before; sep = null; after = [ ]; }
|
||||
else if pred (head rest)
|
||||
then { inherit before; sep = head rest; after = tail rest; }
|
||||
else (go (before ++ [ (head rest) ]) (tail rest));
|
||||
in
|
||||
go [ ]
|
37
nix/tangleOrgBabel.nix
Normal file
37
nix/tangleOrgBabel.nix
Normal file
|
@ -0,0 +1,37 @@
|
|||
# Quick-and-dirty re-implementation of org-babel-tangle in Nix.
|
||||
{ languages
|
||||
, processLines
|
||||
}:
|
||||
string:
|
||||
with builtins;
|
||||
let
|
||||
lines = filter isString (split "\n" string);
|
||||
|
||||
dropUntil = import ./dropUntil.nix;
|
||||
|
||||
blockStartRegexp =
|
||||
"[[:space:]]*\#\\+[Bb][Ee][Gg][Ii][Nn]_[Ss][Rr][Cc][[:space:]]+"
|
||||
+ "(" + (concatStringsSep "|" languages) + ")"
|
||||
+ "([[:space:]].*)?";
|
||||
|
||||
isBlockStart = line: match blockStartRegexp line != null;
|
||||
|
||||
splitListWith = import ./splitWith.nix;
|
||||
|
||||
blockEndRegexp = "[[:space:]]*\#\\+[Ee][Nn][Dd]_[Ss][Rr][Cc].*";
|
||||
|
||||
isBlockEnd = line: match blockEndRegexp line != null;
|
||||
|
||||
go = acc: xs:
|
||||
let
|
||||
st1 = dropUntil isBlockStart xs;
|
||||
st2 = splitListWith isBlockEnd st1;
|
||||
in
|
||||
if length xs == 0
|
||||
then acc
|
||||
else if length st1 == 0
|
||||
then acc
|
||||
else (go (acc ++ [ st2.before ]) st2.after);
|
||||
|
||||
in
|
||||
concatStringsSep "\n" (concatLists (go [ ] (processLines lines)))
|
33
test/test.nix
Normal file
33
test/test.nix
Normal file
|
@ -0,0 +1,33 @@
|
|||
# nix-instantiate --eval --strict test/test.nix
|
||||
with builtins;
|
||||
let
|
||||
pkgs = import (fetchTree (fromJSON (readFile ../flake.lock)).nodes.nixpkgs.locked) {
|
||||
system = builtins.currentSystem;
|
||||
};
|
||||
exclude = import ../nix/excludeOrgSubtreesOnHeadlines.nix;
|
||||
matchOrgTag = import ../nix/matchOrgTag.nix;
|
||||
matchOrgHeadline = import ../nix/matchOrgHeadline.nix;
|
||||
dropUntil = import ../nix/dropUntil.nix;
|
||||
lines = filter isString (split "\n" (readFile ./test.org));
|
||||
in
|
||||
pkgs.lib.runTests {
|
||||
testTagPredicate = {
|
||||
expr = head (exclude (matchOrgTag "ARCHIVE") lines);
|
||||
expected = "* Good morning";
|
||||
};
|
||||
|
||||
testHeadlinePredicate = {
|
||||
expr = head (exclude (matchOrgHeadline "Archived entry") lines);
|
||||
expected = "* Good morning";
|
||||
};
|
||||
|
||||
testSubtree = {
|
||||
expr = head (dropUntil (s: s == "Hello!") (exclude (matchOrgTag "irregular") lines));
|
||||
expected = "* Get to work";
|
||||
};
|
||||
|
||||
testTagPredicate2 = {
|
||||
expr = pkgs.lib.last (exclude (matchOrgTag "optional") lines);
|
||||
expected = "It was a good day!";
|
||||
};
|
||||
}
|
20
test/test.org
Normal file
20
test/test.org
Normal file
|
@ -0,0 +1,20 @@
|
|||
* Archived entry :ARCHIVE:
|
||||
** Child inside an archive entry
|
||||
* Good morning
|
||||
Good morning!
|
||||
* Zao :optional:
|
||||
/Zao/ means good morning in Mandarin Chinese.
|
||||
Chinese is optional for non-Chinese people living in countries other than China.
|
||||
* Hello
|
||||
Hello!
|
||||
** Irreguar cases :irregular:
|
||||
*** If he/she isn't fine
|
||||
Call an ambulance.
|
||||
Why did he come to the office in the first place?
|
||||
* Get to work
|
||||
Do you love your work?
|
||||
* Bye
|
||||
Bye!
|
||||
It was a good day!
|
||||
* Zaijian :optional:
|
||||
/Zaijian/ means goodbye in Mandarin Chinese.
|
Loading…
Reference in a new issue