emacs-tree-sitter / ts-fold

Code-folding using tree-sitter
GNU General Public License v3.0
234 stars 28 forks source link

Fold starts from the next node #104

Open linwaytin opened 11 months ago

linwaytin commented 11 months ago

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?

jcs090218 commented 11 months ago

The original implementation is in #33.

I've fixed this in #105.

linwaytin commented 11 months ago

Thank you! I noticed that the behavior of some other blocks are changed. Some are not working.

I would suggest that for if and for, we use

(defun ts-fold-range-julia-iffor (node offset)
  "Return the fold range for a NODE in Julia.

It excludes the NODE's first child and the `end' keyword.  For
argument OFFSET, see function `ts-fold-range-seq' for more
information."
  (when-let* ((condition (tsc-get-nth-named-child node 0))
              (beg (tsc-node-end-position condition))
              (end (tsc-node-end-position node))
              (end (- end 3)))
    (when ts-fold-on-next-line  ; display nicely
      (setq end (ts-fold--last-eol end)))
    (ts-fold--cons-add (cons beg end) offset)))

since both if and for have similar structure.

For let block, it seems more complicated to keep the variable declaration list (it can be arbitrarily long and all nodes are siblings).

jcs090218 commented 11 months ago

I would suggest that for if and for, we use

Would you like to open a PR for this? :) Thank you!

For let block, it seems more complicated to keep the variable declaration list (it can be arbitrarily long and all nodes are siblings).

👍

FYI, I need more experience with Julia. Therefore, it's better if others are willing to volunteer to create a parser for this!

linwaytin commented 11 months ago

Sure, I would like to contribute.

I just checked and found let is good, but struct is not good enough. In julia, it could be

struct Foo
end

or

struct Foo{T}
end

or

struct Foo <: S
end

or the combination of the last two.

I want to take care of all cases listed above, but the following does not work

(defun ts-fold-range-julia-struct (node offset)
  "Return the fold range for a NODE in Julia.

It excludes the NODE's first child and the `end' keyword.  For
argument OFFSET, see function `ts-fold-range-seq' for more
information."
  (when-let* ((identifier (ts-fold-find-children node "identifier"))
              (typeinfo (or (ts-fold-find-children node "subtype_clause")
                        (ts-fold-find-children node "type_parameter_list")))
              (beg (if typeinfo
                       (tsc-node-end-position (car typeinfo))
                       (tsc-node-end-position (car identifier))))
              (end (tsc-node-end-position node))
              (end (- end 3)))
    (when ts-fold-on-next-line  ; display nicely
      (setq end (ts-fold--last-eol end)))
    (ts-fold--cons-add (cons beg end) offset)))

I thought ts-fold-find-children can find the 1st identifier which should be the name of the struct, but it seems to have some unexpected behavior. On the other hand, if I comment out typeinfo line and change typeinfo in beg to nil, the behavior is more normal. It seems the (typeinfo (or .... line is incorrect and change the behavior of the whole function....

I am new to this library and tree-sitter, and not good at elisp. Could you please help with this problem? I can then send the PR together.