Skip to content

junyi-hou/tree-sitter-fold

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 

Repository files navigation

Emacs-29

Please use the switch-to-treesit branch for emacs-29 and above with the builtin tree-sitter library treesit.

Introduction

tree-sitter-fold builds on top of emacs-tree-sitter to provide code folding base on the tree-sitter syntax tree.

Installation

  • with straight.el and use-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)
        

Usage

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.

Customization

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.

tree-sitter-fold-foldable-node-alist

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.

tree-sitter-fold-range-alist

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.

Supported languages

Contribution

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.

Note on installing additional grammars

Following the following steps to build additional grammar for emacs-tree-sitter.

  1. make sure tree-sitter CLI is installed and up-to-date. To check, run
    tree-sitter --version
        

    The new ABI requires 0.19.3 or newer version of tree-sitter. Node.js is also required to generate grammar parsers. See here for detailed instructions of how to install tree-sitter CLI tools.

  2. add new grammar repos to tree-sitter-langs-git-dir. In the case of R, 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")))
        
  3. 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)))
        
  4. 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)))
        
  5. 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.

License

MIT