GithubHelp home page GithubHelp logo

emacs-tree-sitter / ts-fold Goto Github PK

View Code? Open in Web Editor NEW
222.0 7.0 28.0 1.23 MB

Code-folding using tree-sitter

License: GNU General Public License v3.0

Emacs Lisp 99.48% Makefile 0.45% Batchfile 0.03% Shell 0.05%
emacs folding tree-sitter

ts-fold's Introduction

License: GPL v3 JCS-ELPA

ts-fold

Code-folding using tree-sitter

CI

ts-fold builds on top of elisp-tree-sitter to provide code folding based on the tree-sitter syntax tree.

Table of Contents

πŸ’Ύ Installation

πŸ” Method 1. with straight.el and use-package:

(use-package ts-fold
  :straight (ts-fold :type git :host github :repo "emacs-tree-sitter/ts-fold"))

πŸ” Method 2. Manual

git clone https://github.com/emacs-tree-sitter/ts-fold /path/to/lib

then in Emacs:

(add-to-list 'load-path "/path/to/lib")
(require 'ts-fold)

or

(use-package ts-fold
  :load-path "/path/to/lib")

πŸ–₯ Usage

πŸ“‡ Commands

The following are the functions provided by ts-fold-mode

Commands for enabling ts-fold:

Commands Description
ts-fold-mode enable ts-fold-mode in the current buffer.
global-ts-fold-mode enable ts-fold-mode whenever tree-sitter is turned on and the major mode is supported by ts-fold.
ts-fold-indicators-mode enable ts-fold with indicators in the current buffer. See plugins section.
global-ts-fold-indicators-mode enable ts-fold with indicators globally. See plugins section.
ts-fold-line-comment-mode enable line comment folding.

Commands for using ts-fold.

Commands Description
ts-fold-close fold the current syntax node.
ts-fold-open open the outermost fold of the current syntax node. Keep the sub-folds close.
ts-fold-open-recursively open all folds inside the current syntax node.
ts-fold-close-all close all foldable syntax nodes in the current buffer.
ts-fold-open-all open all folded syntax nodes in the current buffer.
ts-fold-toggle toggle the syntax node at `point'.

If evil mode is loaded, then these commands are also added to the evil folding list.

πŸ”¨ Supported languages

⚠️ Please sort these two lists alphabetically!

These languages are fairly complete:

  • ActionScript / Arduino / Assembly
  • Bash / Beancount
  • C / C++ / C# / Clojure / CMake / CSS
  • Dart
  • Elisp / Elixir / Erlang
  • Fish
  • GDScript / GLSL / Go / Groovy (Jenkinsfile)
  • Haskell / Haxe / HLSL / HTML
  • Jai / Java / JavaScript / JSX / JSON / Jsonnet / Julia
  • Kotlin
  • LaTex / Lisp / Lua
  • Make / MATLAB / Markdown / Mermaid
  • Ninja / Nix / Noir
  • OCaml / Org
  • Perl / PHP / Python
  • R / Ruby / Rust / reStructuredText
  • Scala / Scheme / SQL / Svelte / Swift
  • TOML / TypeScript / TSX
  • Verilog / VHDL
  • XML
  • YAML
  • Zig

These languages are in development:

  • Ada
  • Agda
  • Elm
  • Fortran
  • Pascal
  • Smithy

P.S. We don't list trivial languages here. e.g., LLVM IR (.ll) files, etc. Please see the variable ts-fold-range-alist for the fully supported list!

πŸ“ Customization

Although ts-fold aims to have good folding out of the box for all supported definitions, people will indubitably have their own preferences or desired functionality. The following section outlines how to add your own folding definitions and folding functions to make ts-fold work for you. If there are any improvements you find for existing or new languages, please do raise a PR so that others may benefit from better folding in the future!

βšͺ Folding on new nodes

Ts-fold defines all its folding definitions in the variable ts-fold-range-alist which is an alist with the key of the alist being the mode and the value being another alist of fold definitions.

;; Example of ts-fold-range-alist's structure
'((c-mode     . c-folding-definitions) ;; <language>-folding-definitions is structured as shown below
  (css-mode   . css-folding-definitions)
  (go-mode    . go-folding-definitions)
  (scala-mode . scala-folding-definitions)
  ...)

;; Examle of a folding definition alist
(setq css-folding-definitions
    (block   . ts-fold-range-seq)
    (comment . ts-fold-range-c-like-comment))

So you can select whatever node that you want to fold on it.

To find what node you'll want to fold closed, refer to the tree-sitter documentation about viewing nodes. tree-sitter-debug and tree-sitter-query-builder are both very useful for this.

For the folding functions, ts-fold provides some default

  • ts-fold-range-seq - Folds from the start of the node to the end of the node leaving a buffer of one character on each side. Usually used for code blocks that have bracketing delimiters.

    int main() { // <-- start of tree-sitter block node
        printf("Hello, World\n");
        return 0;
    } // <-- end of tree-sitter block node
    
    // |
    // | '(block . ts-fold-range-seq)
    // V
    
    int main() {...} // Folded node
  • ts-fold-range-markers - Folds the node starting from a giving delimiter character. Useful if tree-sitter's node definition doesn't align with the start of the desired folding section.

    NOTE: This folding function requires a lambda (or an externally defined function wrapper) so that the delimiter can be specified. You usually don't need to worry about the node and offset variables, so just pass them through.

type Dog interface {
    Bark() (string, error)
    Beg() (bool, error)
}

/* | Note: The tree-sitter node starts at the word interface, not at the '{'.
 * | '(interface_type . (lambda (node offset)
 * |                      (ts-fold-range-markers node offset "{" "}")))
 * V
 */

type Dog interface {...}
  • ts-fold-range-block-comment - Folds multi-line comments that are of the form /*...*/. Should show a summary if the commentary plugin is turned on.

    /*
     * The main function that gets run after program is compiled
     * Doesn't take any parameters
     */
    int main() {
        printf("Hello, World\n");
        return 0;
    }
    
    // |
    // | '(comment . ts-fold-range-block-comment)
    // V
    
    /* <S> The main function that gets run after program is compiled */
    int main() {
        printf("Hello, World\n");
        return 0;
  • ts-fold-range-line-comment - For languages that have one line comment blocks with the comment delimiter starting each line. Condenses all the comment nodes into a single fold.

    Note: This folding function requires a lambda (or an externally defined function wrapper) so that the delimiter can be specified. You usually don't need to worry about the node and offset variables, so just pass them through.

    # show the long form of ls
    # and also display hidden files
    alias ll='ls -lah'
    
    # |
    # | (comment (lambda (node offset) (ts-fold-range-line-comment node offset "#"))))
    # V
    
    # show the long form of ls...
    alias ll='ls -lah'
  • ts-fold-range-c-like-comment - A shortcut for the large number of languages that have the c style comment structures /*...*/ and // .... Smartly picks the correct folding style for the comment on the line.

    /*
     * The main function that gets run after program is compiled
     * Doesn't take any parameters
     */
    int main() {
        // print hello world
        // and a new line
        printf("Hello, World\n");
        return 0;
    }
    
    // |
    // | '(comment . ts-fold-range-c-like-comment)
    // V
    
    /* <S> The main function that gets run after program is compiled */
    int main() {
        // <S> print hello world
        printf("Hello, World\n");
        return 0;

Now that you know what kinds of folds are easily available in ts-fold, you can go ahead and add new fold definitions to ts-fold-range-alist and be good to go!

❔ Example

Let's look at a quick example of adding a new folding definition. Let's say you want to add folding to go-mode's field_declaration_list. The folding definition that is needed will be '(field_declaration_list . ts-fold-range-seq). To add this to the ts-fold-range-alist, you can do something like the following.

(push '(field_declaration_list . ts-fold-range-seq) (alist-get 'go-mode ts-fold-range-alist))

Now the new fold definition should be usable by ts-fold!

↔ Offset

With the functions listed above you'll be able to define most folding behavior that you'll want for most languages. However, sometimes you'll have a language where the delimiter is a word instead of a single character bracket and you want to offset your fold by a certain amount to accommodate it. That's where offsets come in. When adding a fold definition to a a language's fold alist, you can either provide the folding function directly as you've seen so far:

'(block . ts-fold-range-seq)

Or you can provide the folding function with an offset:

'(block . (ts-fold-range-seq 1 -3))

When a range is provided, it provides extra room on the ends of a fold. The way this works is most easily shown using an example. Lets say we want to write a fold for bash's for...do...done construct to look something like this:

for i in 1 2 3 4 5
do
   echo "Welcome $i times"
done

# |
# | '(do_group . <some folding function>)
# V

for i in 1 2 3 4 5
do...done

The do...done block is represented in tree-sitter as the node named do_group. However, if we just use '(do_group . ts-fold-range-seq), then we'll get results like the following:

for i in 1 2 3 4 5
d...e

which is hard to read. Instead, we can use the definition '(do_group . (ts-fold-range-seq 1 -3)) to offset the fold a bit to get our desired result!

πŸ” Writing new fold functions

If the built in functions don't fit your needs, you can write your own fold parser! Folding functions take two parameters:

  • node - the targeted tree-sitter node; in this example, block will be the targeting node.
  • offset - (optional) a cons of two integers. This is handy when you have a similar rule with little of positioning adjustment.

Then the function needs to return a position range for the fold overlay in the form '(start-of-fold . end-of-fold). If nil is returned instead of a range, then no fold is created. This can be useful if you want to add extra conditional logic onto your fold.

As an example of a folding function, take a look at the definition of the basic ts-fold-range-seq.

(defun ts-fold-range-seq (node offset)
  "..."
  (let ((beg (1+ (tsc-node-start-position node)))  ; node beginning position
        (end (1- (tsc-node-end-position node))))   ; node end position
    (ts-fold--cons-add (cons beg end) offset)))    ; return fold range

πŸ”Œ Plugins

ts-fold comes with a couple of useful little additions that can be used or turned off as desired.

βš– Indicators Mode

This plugin adds interactive visual markers in the gutter that show where folds can be made. They can be clicked on to fold or unfold given nodes.

πŸ’Ύ Installation

ts-fold-indicator-mode is loaded when ts-fold-mode is and the functionality should be auto-loaded in, however if that's not working then you may want to explicitly declare the package in in your config.

  • use-package

    (use-package ts-fold-indicators
    :straight (ts-fold-indicators :type git :host github :repo "emacs-tree-sitter/ts-fold"))
  • (add-to-list 'load-path "/path/to/lib")
    (require ts-fold)

    or

    (use-package ts-fold-indicators
       :load-path "/path/to/lib")

πŸ–₯ Usage

You can then enable this manually by doing either of the following:

M-x ts-fold-indicators-mode

M-x global-ts-fold-indicators-mode

Please note that turning on ts-fold-indicators-mode automatically turns on ts-fold-mode as well. Though, turning off ts-fold-indicators-mode does not turn off ts-fold-mode

  • To enable this automatically whenever tree-sitter-mode is enabled, use the global indicator mode:

    (global-ts-fold-indicators-mode 1)

    Else, a hook can be added to tree-sitter directly.

    (add-hook 'tree-sitter-after-on-hook #'ts-fold-indicators-mode)
  • To switch to left/right fringe: (Default is left-fringe)

    (setq ts-fold-indicators-fringe 'right-fringe)
  • To lower/higher the fringe overlay's priority: (Default is 30)

    (setq ts-fold-indicators-priority 30)
  • To apply different faces depending on some conditions: (Default is nil)

    For example, to coordinate line-reminder with this plugin.

    (setq ts-fold-indicators-face-function
          (lambda (pos &rest _)
            ;; Return the face of it's function.
            (line-reminder--get-face (line-number-at-pos pos t))))
    
    (setq line-reminder-add-line-function
          (lambda (&rest _)
            (null (ts-fold--overlays-in 'ts-fold-indicators-window (selected-window)
                                        (line-beginning-position) (line-end-position)))))

πŸ“ Summary

This plugin automatically extracts summary from the comment/document string, so you can have a nice way to peek at what's inside the fold range.

πŸ–₯ Usage

  • If you don't want this to happen, do: (Default is t)

    (setq ts-fold-summary-show nil)
  • Summary are truncated by length: (Default is 60)

    (setq ts-fold-summary-max-length 60)
  • The exceeding string are replace by: (Default is "...")

    (setq ts-fold-summary-exceeded-string "...")
  • To change summary format: (Default is " <S> %s ")

    (setq ts-fold-summary-format " <S> %s ")

πŸ“ Customization

Just like with fold definitions, you can create your own summary definitions. Summary definitions are defined in ts-fold-summary-parsers-alist and has one summary function per major mode '(java-mode . fold-summary-function). The summary function takes in the doc string which is all the text from a doc node and then returns a string to be displayed in its stead. Unlike with the folding functions, there aren't a set of general summary functions to fall back on. However, there are lots of examples and helper functions present in ts-fold-summary.el. Let's look at one example here.

(defun ts-fold-summary-javadoc (doc-str)
  "Extract summary from DOC-STR in Javadoc."
  (ts-fold-summary--generic doc-str "*")) ;; strip the '*' and returns the first line

As can be seen ts-fold-summary--generic is a very helpful function since it removes the provided delimiter and returns the first line. often this will be enough.

🌫 Line-Comment folding

This plugin makes line comment into foldable range.

πŸ–₯ Usage

M-x ts-fold-line-comment-mode

πŸ”° Contribute

PRs Welcome Elisp styleguide Donate on paypal Become a patron

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.

πŸ”¬ Development

To run the test locally, you will need the following tools:

Install all dependencies and development dependencies:

$ eask install-deps --dev

To test the package's installation:

$ eask package
$ eask install

To test compilation:

$ eask compile

πŸͺ§ The following steps are optional, but we recommend you follow these lint results!

The built-in checkdoc linter:

$ eask lint checkdoc

The standard package linter:

$ eask lint package

πŸ“ P.S. For more information, find the Eask manual at https://emacs-eask.github.io/.

❓ How to add a folding parser?

When adding a new folding parser, add the folding definition function to ts-fold.el itself near where the other range functions live and then add the parser to ts-fold-parsers.el file. Finally, if you are adding support for a new language, remember to add it to the ts-fold-range-alist variable.

When creating a new parser, name it ts-fold-parsers-<language>.

When creating a new folding function, name it ts-fold-range-<language>-<feature> or something similar.

πŸ” Where can I look for tree-sitter node?

Here are some techniques for finding your desired nodes in tree-sitter.

To look for the correct node you have three options:

  • look at the tree-sitter-[lang]/grammar.js implementation. In the above example, block node is defined in the tree-sitter-c-sharp's grammar.js file
  • open a file of your language choice in emacs and M-x tree-sitter-debug-mode. This will display the whole s-expr representing your file
  • (message "%S" (tsc-node-to-sexp)) in your function to display what your function is seeing

Warning

Make sure you look into the correct repository. Repositories are managed under tree-sitter-langs's using git submodule. Some tree-sitter module aren't using the latest version!

❓ How to create a summary parser?

ts-fold-summary.el module is used to extract and display a short description from the comment/docstring.

To create a summary parser, you just have to create a function that could extract comment syntax correctly then register this function to ts-fold-summary-parsers-alist defined in ts-fold-summary.el. The display and shortening will be handled by the module itself.

Functions should be named with the prefix ts-fold-summary- followed by style name. For example, to create a summary parser for Javadoc style, then it should be named ts-fold-summary-javadoc.

⚜️ License

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.

See LICENSE for details.

ts-fold's People

Contributors

bbenchen avatar chookity-pokk avatar dependabot[bot] avatar jakejx avatar jcs090218 avatar junyi-hou avatar kaligule avatar mattiasdrp avatar meliache avatar mohammedzeglam-pg avatar nidish96 avatar norris-young avatar pedro-nonfree avatar rynffoll avatar samrjack avatar shouya avatar sraceves avatar treed avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

ts-fold's Issues

Line-Reminder compatibility doesn't work

I used the snippet from the README to try and get this to work with line-reminder, but anytime I try to save or edit the file I get the below error in my minibuffer. It seems line line-reminder doesn't have the line-reminder--change-lines or line-reminder--saved-lines calls anymore. I think they were replaced with line-reminder--line-status, but I don't know enough elisp to be certain.

cond: Symbol’s value as variable is void: line-reminder--change-lines

Fold starts from the next node

I try to use this package to fold julia code. It works well!

One issue I met is that the function folding starts from the function name. For example

function fn(a, b)
## many lines
end

becomes

function fn...end

I really want to keep the argument list so that the folding is like

function fn(a, b)...end

The argument list should be a sibling of the function name. Is there a way to make the fold start from the argument list?

Fold the nearest node in the line

Assume I have the following line and my cursor is at the beginning of the line.

image

Calling ts-fold-open does not open the fold, I have to move my cursor to the folding overlay to be able to open that. I am really accustomed to this flow from other folding modes, so it would be nice to have this kind of feature. I am currently using AndrewSwerlick's treesit.el fork1, let me know if this works on the original case but not in the fork. Currently I have no way of confirming this but assumed that the behavior is the same in upstream.

To fix this, I added the following function:

(defun ts-fold--first-foldable-node-at-line ()
  "Find the first foldable node in current line, after the current point."
  (catch 'return
    (dolist (pt (number-sequence (point) (cdr (bounds-of-thing-at-point 'line))))
      (when-let (fold (ts-fold--foldable-node-at-pos pt))
        (throw 'return fold)))))

and replaced all ts-fold--foldable-node-at-pos calls with this function. Probably a sub-optimal solution but it works for me.

Add an OCaml parser

I already have a working version for OCaml but I need to add more nodes to it

Add a hook to ts-fold

(I may write a lot of issues in the following days but don't mind them, I plan to push some PR to fix them ;-))

There is currently no hook attached to ts-fold so the way I load the modes looks like this:

(use-package ts-fold
  :load-path "custom/ts-fold/"
  :hook
  (tuareg-mode . ts-fold-mode)
  (c++-mode    . ts-fold-mode)
  (python-mode . ts-fold-mode)
  )

(use-package ts-fold-indicators
  :load-path "custom/ts-fold/"
  :config
  (setq ts-fold-indicators-fringe 'left-fringe)
  (setq ts-fold-indicators-priority 100)
  :hook
  (c++-mode . ts-fold-indicators-mode)
  (tree-sitter-after-on-hook . ts-fold-indicators-mode)
  )

when I'd like to just write (fold-mode . ts-fold-indicators-mode)

Because otherwise the indicators don't appear unless I start editing my file since ts-fold-indicators-mode is hooked to tree-sitter-after-on-hook

error when fold c++ file

got the error:

tsc-node-start-position: Wrong type argument: user-ptrp, nil 

when ran ts-fold-close-all on a C++ source file..

global-ts-fold-mode breaks evil folding for unsupported languages

If I enable global-ts-fold-mode and then try to use evil folding (evil-close-fold) with an unsupported major mode (eg sql-mode), I get

Error: (user-error "Ignored, tree-sitter-mode is not enable in the current buffer")

Is there some way this could be avoided?

Alternatively (or in addition), could ts-fold define (and autoload) a list of supported major modes?

My specific use case is a Spacemacs layer (which I hope to get merged upstream) that (optionally) enables ts-fold for all supported languages -- ideally we wouldn't have to maintain that list in the layer. I imagine this would benefit many non-Spacemacs users as well, for basically the same reason.

refactoring to use queries

Hello!
I am currently working on intergrating tree sitter into doom emacs and I was writing a code forlding plugin for it, after I had gotten most of it done someone notified me of this package which made a lot of that work redundant.

The only problem I have is that the way you handle the "getting" of the range. its not terribly idiomatic compared to some other examples evil-textobj-tree-sitter, emacs-tree-sitter proper as well as all of the nvim tree sitter efforts, this makes this package an outlier in this regard.

I was wondering if you could provide some insight into why you have gone this route and if you would be open to a refactor which I can then work on.

Thanks!
Jeet

Folding by custom sexp query

I'm considering adding a feature that allows custom folding through a tree-sitter sexp query (validated by the tree-siter-query-builder). With some initial attempts, I couldn't get it working. Would anyone be able to take a look and see if it's possible to implement this feature? (or at least let me know what goes wrong with my approach?)

My steps:

  • Appending custom queries by vconcat with range-patterns. Please see my code here
  • In Emacs init file, you add the following snippets:
(setq ts-fold-pattern-alist
      '((python-mode . (((argument_list) @name (\#match? @name "\"[^\\n]*\\n+[^\\n]*\""))))))
  • Update the tsc--stringify-patterns function of tsc.el to:
(defun tsc--stringify-patterns (patterns)
  "Convert PATTERNS into a query string that can be passed to `tsc--make-query'."
  (cond
   ((stringp patterns) patterns)
   ((sequencep patterns)
    ;; XXX: This is hacky.
    (thread-last (mapconcat (lambda (p) (format "%S" p)) patterns "\n")
      (replace-regexp-in-string (regexp-quote "\\?") "?")
      (replace-regexp-in-string (regexp-quote "\\.") ".")
      (replace-regexp-in-string (regexp-quote "\\n") "\n")
      (replace-regexp-in-string (regexp-quote "\\#") "#")))
   (t (error "Invalid patterns"))))

Outcome:

  • Parsing seems to work. If I add (message (format patterns)) before this (line)[https://github.com/emacs-tree-sitter/elisp-tree-sitter/blob/master/core/tsc.el#L242], I will get [(function_definition) @name (class_definition) @name (list) @name (dictionary) @name (comment) @name ((argument_list) @name (#match? @name "[^\n]*\n+[^\n]*")) @name]
  • But I got this error: Error: (tsc-query-invalid-node-type "" (11 . 1) 103). It seems tsc is returning invalid nodes, which confused me. The sexp query above works well with tree-siter-query-builder.

Any thoughts?

Not work in java

Works fine at python-mode, but doesn't works at all at java-mode.

Minor modes enabled in this buffer: Command-Log Display-Line-Numbers
Evil-Collection-Unimpaired Evil-Local Evil-Matchit Evil-Surround
Evil-Visualstar Font-Lock Lsp-Bridge Tree-Sitter-Hl Tree-Sitter
Ts-Fold-Indicators Ts-Fold Undo-Tree

The major mode is Java//lh mode defined in cc-mode.el:

Major mode for editing Java code.
To submit a problem report, enter β€˜M-x c-submit-bug-report’ from a
β€˜java-mode’ buffer.  This automatically sets up a mail buffer with
version information already added.  You just need to add a description
of the problem, including a reproducible test case, and send the
message.

To see what version of CC Mode you are running, enter β€˜M-x c-version’.

The hook β€˜c-mode-common-hook’ is run with no args at mode
initialization, then β€˜java-mode-hook’.

The Java//lh is very strange, I don't konw why it isn't java mode

Visual glitch with bigger font

Hello, thanks a lot for this great package 😊

When setting the default face size at 180 instead of the usual 100 the fringe indicators are rendered this way:

image

and I need to manually overload these values:

'ts-fold-indicators-fr-minus-tail
'ts-fold-indicators-fr-center
'ts-fold-indicators-fr-end-left
'ts-fold-indicators-fr-end-right

with some more (balanced) lines

  "........" "........" "........" "........" "........"
  "...XX..." "...XX..." "...XX..." "...XX..." "...XX..."

to get a visual fix:
image

I'm wondering what a more flexible fix would look like.

[feature request] ability to disable comment folding

I really like the function folding it does this package; but I would like to avoid multiline comment folding?

main() {
  # example 1
  echo 'hi'
  # example 2
  echo 'hi'
  # example 3
  # example 4
  # example 5
  echo 'hi'
  # example 3
  # example 4
  # example 5
  echo 'hi'
  echo 'hi'
  echo 'hi'
  # example 3
  # example 5
  echo 'hi'
}

main "${@}"

given the following example I see a lot of mess in the indicator part (and also, makes it more complex to do the folding that you really want, in my case: function folding):

image

and I would like something more basic, like having comments that don't make additional foldings:

image

Ruby spec files folding support

Folding works correctly in general .rb files, however, does not work in _spec.rb files for some reasons.
No errors in the log.

Testing on spacemacs build running on GNU Emacs 28.1 (build 1, x86_64-apple-darwin20.6.0, NS appkit-2022.60 Version 11.6 (Build 20G165)) of 2022-07-18 [2 times]

Error saying tree-sitter-mode not enabled

I am on Emacs 29.1 and have installed tree-sitter libs for txs, typescript. and javascript. When I load a buffer and try to run a ts-fold command (e.g. ts-fold-toggle) I get an error:

Ignored, tree-sitter-mode is not enabled in the current buffer

However, if I check to see if I'm running a tree sitter mode by doing C-: and evaluating (symbol-name major-mode), I get typescript-ts-mode.

I am not sure what may be going on here. Any guidance would be greatly appreciated.

global-ts-fold-indicators-mode does not work

My emacs got an error due to updated ts-fold package a few days ago.

Debugger entered--Lisp error: (error "No language registered for major mode β€˜fundamental...")
  error("No language registered for major mode `%s'" fundamental-mode)
  tree-sitter--setup()
  tree-sitter-mode()
  ts-fold-indicators-mode()
  ts-fold-mode(-1)
  ts-fold--tree-sitter-trigger()
  global-ts-fold-mode(1)
  global-ts-fold-indicators-mode(1)
  load-with-code-conversion("/Users/tomoya/.config/emacs/init.el" "/Users/tomoya/.config/emacs/init.el" t t)
  load("/Users/tomoya/.config/emacs/init" noerror nomessage)
  startup--load-user-init-file(#f(compiled-function () #<bytecode 0x80e71dfb90107fa>) #f(compiled-function () #<bytecode 0xe1b30db824d45f1>) t)
  command-line()
  normal-top-level()

This error has occurred (global-ts-fold-indicators-mode 1) configuration.
When I tried changing it to (add-hook 'tree-sitter-after-on-hook #'ts-fold-indicators-mode), the error disappeared.

P.S.
ts-fold is a very nice package for me, Thank you.

Move to emacs tree-sitter org?

Hi @ubolonton,

I am pinging you here to ask weather you would like me to move this package to emacs-tree-sitter so it could live under the same domain? I saw Spacemacs and Doom Emacs have added tree-sitter support, along with this package. I think it would be great so it doesn't live under my name jcs090218 when defining a recipe. And could be much organized (somehow)?

Short version: Do you think this package should live under emacs-tree-sitter org? LMKWYT?

Recommended installation method doesn't work

I tried to install ts-fold using the recommended method 1 from the readme:

(use-package ts-fold
  :straight (host github repo "jcs090218/ts-fold"))

This didn't work for me, I got the following error:

Wrong type argument: plistp, (github repo "jcs090218/ts-fold")

After consulting the straight documentation I came up with the following, which worked:

(use-package ts-fold
  :straight (ts-fold :type git :host github :repo "jcs090218/ts-fold"))  

Could someone please doublecheck that the second version works and the first one doesn't?
If this is correct, I am happy create a pull request.

Treesit.el Support

Hey @jcs090218 thanks for this great package, I think its a hugely important feature set in the emacs tree-sitter ecosystem. I'm curious what your plans are with regards to the new [built in treesit.el](https://github.com/emacs-mirror/emacs/blob/emacs-29/lisp/treesit.el) that is shipping with Emacs 29? Are you interested in having this package work with that?

I started experimenting with what that might mean in this PR and found the process of integrating with treesit.el to be pretty straight forward, but I wanted to understand how you were thinking about this before going any further.

If you're interested, I can go further with the PR. There are some unanswered questions, like would you want older versions to support the legacy emacs-tree-sitter package, and new versions to only support treesit.el, or one version that could swap between them etc. Interested to hear your thoughts.

Feature request: Simplifying the process of adding new fold parsing definitions

Hello, I've recently started using ts-fold and have really loved being able to define my own set of folds for languages I use quite often. One issue I've had with it though is how difficult it is to add my own definitions to the existing alist without defining the variable myself or modifying the package's source code. The main cause for pain is the use of the ts-fold-foldable-node-alist variable which has to get updated every time the ts-fold-range-alist variable gets updated. To that end I'm currently using the following function as a hack to update both variables for a major mode:

  (defun local/update-ts-fold-definitions (mode rules)
    "Update the provided MODE with the new set of folding RULES.
MODE should be a programming mode such as go-mode.
RULES should be a list of folding rules in the format of (ts-element . folding-function)"
    (setf (alist-get mode ts-fold-range-alist) rules)
    (setq ts-fold-foldable-node-alist
          (let (alist)
            (dolist (item ts-fold-range-alist)
              (let ((mode (car item))
                    nodes)
                (dolist (rule (cdr item))
                  (push (car rule) nodes))
                (push (cons mode nodes) alist)))
            alist)))

It works fine for now but I think it would be cleaner if ts-fold itself had a function for updating the fold definition alist variables. That way, it would be easier for people to only define the minimal information needed within their own configs for adding new folds as well as making code a lot easier to share.

Also, from a design perspective, I'm wondering about the necessity of duplicating the node information within ts-fold-foldable-node-alist. Was it for performance gains or some other reason? Just trying to get better at elisp myself so I'd appreciate the insight!

julia language support

Are there any plans to support julia? I've coded this function

(defun tree-sitter-fold-range-julia (node)
  (let* ((a (tsc-node-end-position (tsc-get-nth-named-child node 0)))
         (b (- (tsc-node-end-position node) 3))) ;; offset by three to include `end'
    (cons a b)))

for the tree-sitter-fold package to fold the function_definition, macro_definition, struct_definition and module_definition nodes; it works, but it sometimes fails to load (I don't know why).

Also, the code here looks much more comprehensive (and standardized); I also don't know enough elisp to understand it or contribute with my own julia parser. Since julia uses the function ... end syntax, I feel it shouldn't be too different from ruby (maybe?)

Thanks.

MELPA

Is there any interest in publishing ts-fold on MELPA?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.