emacs: Add basic tree-sitter support (#219559)

This commit adds basic support for tree-sitter in the emacs build,
such that (if the user opts into tree-sitter support), tree-sitter
will be enabled and binary library files for tree-sitter can be
included in the `lib` directory of packages passed to
`emacsWithPackages`. The libraries will be aggregated and included in
treesit-extra-load-path.

The previous pattern for this in the community was to add tree-sitter
libaries by patching emacs's `RUNPATH` with `patchelf` in a post-fixup
phase. However, this has the substantial drawback that two different
emacs installations with different lists of available tree-sitter
libraries must be entirely separate builds. By supplying the
tree-sitter libraries in the wrapping layer of `emacsWithpackages`, it
becomes possible to share a single, more-cacheable "core emacs".

This support defaults to "on" only in emacs 29 and up, since previous
versions do not support tree-sitter out of the box.
This commit is contained in:
Chris Hodapp 2023-03-14 20:51:29 -07:00 committed by GitHub
parent 28b44d37a2
commit 1a8edfe192
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 17 additions and 1 deletions

View file

@ -45,6 +45,7 @@
else if withAthena then "athena" else if withAthena then "athena"
else "lucid") else "lucid")
, withSystemd ? lib.meta.availableOn stdenv.hostPlatform systemd, systemd , withSystemd ? lib.meta.availableOn stdenv.hostPlatform systemd, systemd
, withTreeSitter ? lib.versionAtLeast version "29", tree-sitter ? null
}: }:
assert (libXft != null) -> libpng != null; # probably a bug assert (libXft != null) -> libpng != null; # probably a bug
@ -58,6 +59,7 @@ assert withGTK2 -> !withGTK3 && gtk2-x11 != null && !withPgtk;
assert withGTK3 -> !withGTK2 && ((gtk3-x11 != null) || withPgtk); assert withGTK3 -> !withGTK2 && ((gtk3-x11 != null) || withPgtk);
assert withPgtk -> withGTK3 && !withX && gtk3 != null; assert withPgtk -> withGTK3 && !withX && gtk3 != null;
assert withXwidgets -> withGTK3 && webkitgtk != null; assert withXwidgets -> withGTK3 && webkitgtk != null;
assert withTreeSitter -> tree-sitter != null;
(if withMacport then llvmPackages_6.stdenv else stdenv).mkDerivation (finalAttrs: (lib.optionalAttrs nativeComp { (if withMacport then llvmPackages_6.stdenv else stdenv).mkDerivation (finalAttrs: (lib.optionalAttrs nativeComp {
@ -164,7 +166,8 @@ assert withXwidgets -> withGTK3 && webkitgtk != null;
ImageCaptureCore GSS ImageIO ImageCaptureCore GSS ImageIO
] ]
++ lib.optionals stdenv.isDarwin [ sigtool ] ++ lib.optionals stdenv.isDarwin [ sigtool ]
++ lib.optionals nativeComp [ libgccjit ]; ++ lib.optionals nativeComp [ libgccjit ]
++ lib.optionals withTreeSitter [ tree-sitter ];
hardeningDisable = [ "format" ]; hardeningDisable = [ "format" ];
@ -193,6 +196,7 @@ assert withXwidgets -> withGTK3 && webkitgtk != null;
++ lib.optional withImageMagick "--with-imagemagick" ++ lib.optional withImageMagick "--with-imagemagick"
++ lib.optional withXinput2 "--with-xinput2" ++ lib.optional withXinput2 "--with-xinput2"
++ lib.optional (!withToolkitScrollBars) "--without-toolkit-scroll-bars" ++ lib.optional (!withToolkitScrollBars) "--without-toolkit-scroll-bars"
++ lib.optional withTreeSitter "--with-tree-sitter"
; ;
installTargets = [ "tags" "install" ]; installTargets = [ "tags" "install" ];
@ -241,6 +245,7 @@ assert withXwidgets -> withGTK3 && webkitgtk != null;
passthru = { passthru = {
inherit nativeComp; inherit nativeComp;
treeSitter = withTreeSitter;
pkgs = recurseIntoAttrs (emacsPackagesFor finalAttrs.finalPackage); pkgs = recurseIntoAttrs (emacsPackagesFor finalAttrs.finalPackage);
tests = { inherit (nixosTests) emacs-daemon; }; tests = { inherit (nixosTests) emacs-daemon; };
}; };

View file

@ -42,6 +42,8 @@ let
nativeComp = emacs.nativeComp or false; nativeComp = emacs.nativeComp or false;
treeSitter = emacs.treeSitter or false;
in in
packagesFun: # packages explicitly requested by the user packagesFun: # packages explicitly requested by the user
@ -109,6 +111,9 @@ runCommand
${optionalString nativeComp '' ${optionalString nativeComp ''
mkdir -p $out/share/emacs/native-lisp mkdir -p $out/share/emacs/native-lisp
''} ''}
${optionalString treeSitter ''
mkdir -p $out/lib
''}
local requires local requires
for pkg in $explicitRequires; do for pkg in $explicitRequires; do
@ -133,6 +138,9 @@ runCommand
${optionalString nativeComp '' ${optionalString nativeComp ''
linkPath "$1" "share/emacs/native-lisp" "share/emacs/native-lisp" linkPath "$1" "share/emacs/native-lisp" "share/emacs/native-lisp"
''} ''}
${optionalString treeSitter ''
linkPath "$1" "lib" "lib"
''}
} }
# Iterate over the array of inputs (avoiding nix's own interpolation) # Iterate over the array of inputs (avoiding nix's own interpolation)
@ -164,6 +172,9 @@ runCommand
${optionalString nativeComp '' ${optionalString nativeComp ''
(add-to-list 'native-comp-eln-load-path "$out/share/emacs/native-lisp/") (add-to-list 'native-comp-eln-load-path "$out/share/emacs/native-lisp/")
''} ''}
${optionalString treeSitter ''
(add-to-list 'treesit-extra-load-path "$out/lib/")
''}
EOF EOF
# Generate a subdirs.el that statically adds all subdirectories to load-path. # Generate a subdirs.el that statically adds all subdirectories to load-path.