Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.org
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Example:

Default: =[ "emacs-lisp" "elisp" ]=
**** Filtering subtrees
You can transform the input by specifying =processLines= option.
You can transform the input by specifying =transformLines= option.
It must be a function that takes a list of strings and returns a list of strings.

Comment thread
akirak marked this conversation as resolved.
This library also contains =excludeHeadlines= function which can be used to exclude subtrees according to a predicate on the headline text, so you can use it in the option.
Expand All @@ -76,10 +76,12 @@ Example:
#+begin_src nix
{
# Exclude archived subtrees
processLines = excludeHeadlines (matchOrgTag "ARCHIVE");
transformLines = excludeHeadlines (matchOrgTag "ARCHIVE");
}
#+end_src

/=processLines= has been renamed to =transformLines= and deprecated. They work exactly the same way./

You can use the following predicates from this library:

- tag :: Returns true if the headline matches a tag given as the argument. The argument must be a string.
Expand Down
72 changes: 46 additions & 26 deletions nix/tangleOrgBabel.nix
Original file line number Diff line number Diff line change
@@ -1,37 +1,55 @@
# Quick-and-dirty re-implementation of org-babel-tangle in Nix.
{ languages ? [ "emacs-lisp" "elisp" ]
, processLines ? lines: lines
, tangleArg ? "yes"
{
languages ? [
"emacs-lisp"
"elisp"
],
transformLines ? null,
processLines ? null,
tangleArg ? "yes",
}:
string:
with builtins;
let
warn =
msg: value:
if builtins ? warn then
builtins.warn msg value
else
trace msg value;

effectiveTransformLines =
if transformLines != null then
transformLines
else if processLines != null then
warn "`processLines` is deprecated; use `transformLines` instead."
processLines
else
lines: lines;

lines = filter isString (split "\n" string);

dropUntil = import ./dropUntil.nix;

blockStartRegexp =
"[[:space:]]*\#\\+[Bb][Ee][Gg][Ii][Nn]_[Ss][Rr][Cc][[:space:]]+"
+ "(" + (concatStringsSep "|" languages) + ")"
+ "("
+ (concatStringsSep "|" languages)
+ ")"
+ "(([[:space:]].*)?)";

parseParamsString = import ./parseParamsString.nix;

parseParamsString' = s:
if s == null
then { }
else parseParamsString s;

checkBlockParams = attrs:
foldl' (acc: value: acc && value) true
(attrValues
(mapAttrs (name: value:
if name == ":tangle"
then value == tangleArg
else true
) attrs));

isBlockStart = line:
parseParamsString' = s: if s == null then { } else parseParamsString s;

checkBlockParams =
attrs:
foldl' (acc: value: acc && value) true (
attrValues (mapAttrs (name: value: if name == ":tangle" then value == tangleArg else true) attrs)
);

isBlockStart =
line:
(match blockStartRegexp line != null)
&& checkBlockParams (parseParamsString' (elemAt (match blockStartRegexp line) 2));

Expand All @@ -41,16 +59,18 @@ let

isBlockEnd = line: match blockEndRegexp line != null;

go = acc: xs:
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);
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)))
concatStringsSep "\n" (concatLists (go [ ] (effectiveTransformLines lines)))
37 changes: 37 additions & 0 deletions test/test.nix
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,41 @@ pkgs.lib.runTests {
"Extra spaces around params"
];
};

testTangleOrgBabelTransformLines = {
expr = tangleOrgBabel {
transformLines = exclude (matchOrgTag "ARCHIVE");
} (readFile ./testTangle.org);

expected = pkgs.lib.removeSuffix "\n" ''
Default
Alternative language name
Upper case
:tangle yes
Extra spaces around params
'';
};

testTangleOrgBabelProcessLinesDeprecated = {
expr = tangleOrgBabel {
processLines = exclude (matchOrgTag "ARCHIVE");
} (readFile ./testTangle.org);

expected = pkgs.lib.removeSuffix "\n" ''
Default
Alternative language name
Upper case
:tangle yes
Extra spaces around params
'';
};

testTangleOrgBabelTransformLinesTakesPrecedence = {
expr = tangleOrgBabel {
transformLines = _: [ ];
processLines = _: [ "#+begin_src emacs-lisp" "deprecated" "#+end_src" ];
} (readFile ./testTangle.org);

expected = "";
};
}
Loading