Please use the switch-to-treesit
branch for emacs-29
and above with the builtin tree-sitter library treesit
.
tree-sitter-fold
builds on top of emacs-tree-sitter to provide code folding base on the tree-sitter syntax tree.
- with
straight.el
anduse-package
:(use-package tree-sitter-fold :straight (host github repo "junyi-hou/tree-sitter-fold"))
- manual:
git clone https://github.com/junyi-hou/tree-sitter-fold /path/to/lib
then in
emacs
:(add-to-list 'load-path "/path/to/lib") (require 'tree-sitter-fold)
tree-sitter-fold-close
: fold the current syntax node.
tree-sitter-fold-open
: open all folds inside the current syntax node.
tree-sitter-fold-open-recursively
: open the outmost fold of the current syntax node. Keep the sub-folds close.
tree-sitter-fold-close-all
: close all foldable syntax nodes in the current buffer.
tree-sitter-fold-open-all
: open all folded syntax nodes in the current buffer.
tree-sitter-fold
allows user-defined rules of how to fold syntax nodes. Two variables determine which node is foldable and how tree-sitter-fold
should fold those nodes. I only implement folding mechanisms for python
. Contribution on other types of folds and for other major modes are welcome.
This is an alist whose keys are major-mode
symbols, and the corresponding values are lists of tree-sitter-node-type
considered foldable in the major mode. tree-sitter-fold-close
will fold only if the node are one of the types defined in this list under the current major mode.
This variable determines how tree-sitter-fold
should fold each of the nodes defined in tree-sitter-fold-foldable-node-alist
. It is a nested alist, with the first key being the major mode, and second key being the tree-sitter-node-type
. The value should be a function that takes a tree-sitter-node
as the single argument, and return a cons cell of buffer position as the range should be folded by tree-sitter-fold
. See tree-sitter-fold-range-python
for an example.
- python
- R (need to compile tree-sitter-r grammar, see Note on installing additional grammars)
- Nix (need to compile tree-sitter-nix, see Note no installing additional grammars)
- Go (thanks to jakejx)
- contribution of other languages are welcome!
Enable tree-sitter-mode
first, then tree-sitter-query-builder
is useful to test out queries that determine what syntax nodes should be foldable and how to fold them. emacs-tree-sitter has an excellent documentation on how to write tree-sitter
queries.
Following the following steps to build additional grammar for emacs-tree-sitter
.
- make sure
tree-sitter CLI
is installed and up-to-date. To check, runtree-sitter --version
The new ABI requires
0.19.3
or newer version oftree-sitter
.Node.js
is also required to generate grammar parsers. See here for detailed instructions of how to install tree-sitter CLI tools. - add new grammar repos to
tree-sitter-langs-git-dir
. In the case ofR
, run;; make sure I do not re-add the submodule multiple times (unless (f-exists-p (concat tree-sitter-langs-git-dir "/repos/r")) (let ((default-directory tree-sitter-langs-git-dir)) (tree-sitter-langs--call "git" "submodule" "add" "https://github.com/r-lib/tree-sitter-r" "repos/r")))
- compile the new grammar parser by running
;; compile only if haven't done so (unless (--filter (string= (f-base it) "r") (f-entries (tree-sitter-langs--bin-dir))) ;; do not display compile information in a new buffer (cl-letf (((symbol-function 'tree-sitter-langs--buffer) (lambda (&rest _) nil))) (tree-sitter-langs-compile 'r)))
- register the respective major mode with the newly compiled grammar
(unless (assq 'ess-r-mode tree-sitter-major-mode-language-alist) (add-to-list 'tree-sitter-major-mode-language-alist '(ess-r-mode . r)))
- require the new grammar
(tree-sitter-require 'r)
I have those things together in a function gatsby:install-and-load-tree-sitter-r
at here and hook it to ess-r-mode-hook
.
MIT