Lexical Binding: Before Emacs 24 emacs-lisp is dynamic binding. lexical binding is introduced in Emacs 24, enabling compile-time optimizations.
Native Compilation: Introduced in Emacs 28, native compilation used the GCC JIT compile to convert Emacs Lisp code to native machine code, dramatically improving execution speed.
Package Management
Lazy loading with use-package: use-package is now build into Emacs 29
Straight Package Manager
: works with use-package to handle package installations and version control.
Syntax Highlighting and Parsing
Tree-sitter Integration: Emacs 29 includes support for Tree-sitter, a parser generator that improves syntax highlighting and code navigation by using precise parse trees instead of regular expressions. This results in more accurate and faster syntax highlighting.
tree-sitter mode: new major modes that utilize tree-sitter for enhanced code parsing and highlighting, for example, use python-ts-mode to replace traditional python-mode.
Completion Frameworks
Historical Context: Initially, Emacs used ido for interactive file and buffer navigation, followed by heavier frameworks like helm and ivy for more advanced completions.
Modern Solutions: verticoconsultorderlessmarginaliaembark
Language Server Protocol (LSP)
eglot: Emacs’ build-in LSP client
I personally use
lsp-bridge
for completion and LSP
I’ve been searching for a good solution to use Emacs29 with tree-sitter config in nix-darwin for quite some time.
Emacs29 comes with built-in support for Tree-Sitter, a parser generator tool and an incremental parsing library, the only requirement is the grammar files, detail in this
masteringemacs article
.
While there are some proposed solutions out there, such as the one found on the
nixos discourse
, they didn’t quite hit the mark for me. The issue was that I’m using an overridden package definition of pkgs.emacs29-macport, which complicated things a bit.
The above treesit-grammars.with-all-grammars definition only installs the dynamic libraries. However, Emacs was still unable to find the files. The crux of the problem was that I needed to link the directory to a location that Tree-Sitter could locate.
After many trials and tribulations, I finally managed to come up with a functional solution.
Solution
pkg-emacs29-macport.nix: package definition of emacs
{pkgs?(import<nixpkgs>{})}:let# https://github.com/railwaycat/homebrew-emacsmacport/blob/master/Formula/emacs-mac.rbemacs29-macport=(pkgs.emacs29-macport.overrideAttrs(prevAttrs:{patches=(prevAttrs.patches)++[# patch for multi-tty support, see the following links for details# https://bitbucket.org/mituharu/emacs-mac/pull-requests/2/add-multi-tty-support-to-be-on-par-with/diff# https://ylluminarious.github.io/2019/05/23/how-to-fix-the-emacs-mac-port-for-multi-tty-access/(pkgs.fetchpatch{url="https://raw.githubusercontent.com/railwaycat/homebrew-emacsmacport/8b06f75ea28a68f9a490d9001ce33fd1b0d426aa/patches/emacs-mac-29-multi-tty.diff";sha256="sha256-OpSYG5ew8A1IL5rW/wPwmG2bzZa8iFF+xTYQGiWjzKg=";})# no-title-bars(pkgs.fetchpatch{url="https://raw.githubusercontent.com/railwaycat/homebrew-emacsmacport/667f0efc08506facfc6963ac1fd1d5b9b777e094/patches/emacs-26.2-rc1-mac-7.5-no-title-bar.patch";sha256="sha256-f2DRcUZq8Y18n6MJ6vtChN5hLGERduMB8B1mrrds6Ns=";})];})).override{# not necessary, but enforce these options to be truewithNativeCompilation=true;withTreeSitter=true;};buildEmacs=(pkgs.emacsPackagesForemacs29-macport).emacsWithPackages;treesitGrammars=(pkgs.emacsPackagesForemacs29-macport).treesit-grammars.with-all-grammars;in{emacs=buildEmacs(epkgs:withepkgs;[vtermtreesitGrammars]);treesitGrammars=treesitGrammars;}
config-emacs.nix: configuraiton of emacs
{pkgs,config,lib,...}:letemacs29=(pkgs.callPackage./pkg-emacs29-macport.nix{});in{home.packages=lib.mkBefore([emacs29.emacs]);home.file={# tree-sitter subdirectory of the directory specified by user-emacs-directory".config/emacs/.local/cache/tree-sitter".source="${emacs29.treesitGrammars}/lib";};}
Tree-sitter language grammars are distributed as dynamic libraries. In order to use a language grammar in Emacs, you need to make sure that the dynamic library is installed on the system. Emacs looks for language grammars in several places, in the following order:
first, in the list of directories specified by the variable treesit-extra-load-path;
then, in the tree-sitter subdirectory of the directory specified by user-emacs-directory (see The Init File);
and finally, in the system’s default locations for dynamic libraries.