An Emacs Lisp reader in Nix. Yes, it’s necessary.
nix-repl> :p fromElisp "(use-package lsp-mode :ensure :commands lsp)" [ [ "use-package" "lsp-mode" ":ensure" ":commands" "lsp" ] ]
fromElisp
provides four main functions: fromElisp
, parseElisp
,
fromOrgModeBabelElisp
and parseOrgModeBabelElisp
.
- fromElisp elisp (string)
Takes a string argument and tries to convert the Elisp read from it to the closest equivalent data type in Nix.
For example,
(use-package highlight-symbol :ensure t :hook (((python-mode emacs-lisp-mode nix-mode) . highlight-symbol-mode) ((python-mode emacs-lisp-mode nix-mode) . highlight-symbol-nav-mode)) :config (highlight-symbol-nav-mode) (setq highlight-symbol-idle-delay 0.5) (set-face-attribute 'highlight-symbol-face nil :background "dark cyan"))
is read as
[[ "use-package" "highlight-symbol" ":ensure" true ":hook" [[[ "python-mode" "emacs-lisp-mode" "nix-mode" ] "highlight-symbol-mode" ] [[ "python-mode" "emacs-lisp-mode" "nix-mode" ] "highlight-symbol-nav-mode" ]] ":config" [ "highlight-symbol-nav-mode" ] [ "setq" "highlight-symbol-idle-delay" 0.5 ] [ "set-face-attribute" [ "quote" "highlight-symbol-face" ] [ ] ":background" "dark cyan" ]]]
- parseElisp elisp (string)
Takes a string argument and provides an AST with additional structural info, such as object type, line number and list depth.
The AST provided for the code
(setq mouse-wheel-scroll-amount '(3 ((shift) . 1)))
would be
[{ depth = 0; line = 1; type = "list"; value = [ { line = 1; type = "symbol"; value = "setq"; } { line = 1; type = "symbol"; value = "mouse-wheel-scroll-amount"; } { line = 1; type = "quote"; value = { depth = 1; line = 1; type = "list"; value = [ { line = 1; type = "integer"; value = 3; } { depth = 2; line = 1; type = "list"; value = [ { depth = 3; line = 1; type = "list"; value = [ { line = 1; type = "symbol"; value = "shift"; } ]; } { line = 1; type = "integer"; value = 1; } ]; } ]; }; } ]; }]
- fromOrgModeBabelElisp text (string)
fromElisp
, but for Org mode babel files. RunsfromElisp
on the result of tangling all Elisp code blocks with:tangle yes
set. Tangling is done internally, not by Org mode. - parseOrgModeBabelElisp text (string)
parseElisp
, but for Org mode babel files. RunsparseElisp
on the result of tangling all Elisp code blocks with:tangle yes
set. Tangling is done internally, not by Org mode.
- tokenizeElisp elisp (string)
Takes a string argument and produces a list of tokens from the Elisp read from it. Used internally by
fromElisp
andparseElisp
. - tokenizeElisp’ args (attrs)
An alternate version of
tokenizeElisp
allowing the specification of the starting line number.args is an attribute set with the following attributes:
- elisp (string, required)
The string of Elisp to tokenize.
- startLineNumber (int, optional)
The line number to use for the first line of elisp. Useful if elisp is a block of code from a larger file and you want line numbers to be correct.
- elisp (string, required)
- parseElisp’ tokens (list)
An alternate version of
parseElisp
which takes as its argument a list of tokens produced bytokenizeElisp
. - fromElisp’ ast (list)
An alternate version of
fromElisp
which takes as its argument an AST produced byparseElisp
. - tokenizeOrgModeBabelElisp text (string)
Run tokenizeElisp’ on all Elisp code blocks (with
:tangle yes
set) from Org mode babel text text. - tokenizeOrgModeBabelElisp’ defaultArgs (attrs) text (string)
An alternate version of
tokenizeOrgModeBabelElisp
which allows the specification of default arguments for Org babel headers. Currently only:tangle
is supported. - parseOrgBabelElisp’ defaultArgs (attrs) text (string)
An alternate version of
parseOrgBabelElisp
which allows the specification of default arguments for Org babel headers. Currently only:tangle
is supported. - fromOrgBabelElisp’ defaultArgs (attrs) text (string)
An alternate version of
fromOrgModeBabelElisp
which allows the specification of default arguments for Org babel headers. Currently only:tangle
is supported.
You can use fromElisp
in your code in multiple ways.
You can use fetchGit
without a rev
attribute to try it out quickly
and then add the rev
when you want reproducibility.
with (import (builtins.fetchGit {
url = "https://github.com/talyz/fromElisp.git";
ref = "master";
# rev = "c13d6035666f36ca940db996f1dbaf83cb4e8453";
}));
# ... code ...
If you use niv to manage your Nix dependencies, simply run
$ niv add talyz/fromElisp
to add fromElisp
to your dependencies and import it as follows:
with (import (import ./nix/sources.nix).fromElisp {});
# ... code ...
If you plan on contributing to fromElisp
and want to do it from
your own source, you can import it as a Git submodule.
- No Unicode support
Nix doesn’t support Unicode, so we can’t either.
- No evaluation
This is a reader and not an evaluator. You can make some pretty reasonable assumptions from the structure of the code, though: it’s, for example, used in the Emacs overlay to implement the functionality of
emacsWithPackagesFromUsePackage
.