raviqqe / schemat

Code formatter for Scheme, Lisp, and any S-expressions
The Unlicense
21 stars 5 forks source link

Break nested tree-like S-expressions #66

Open aminya opened 10 months ago

aminya commented 10 months ago

The formatter does not limit the number of characters on a line. I am using Schemat to format auto-generated S-expressions. They look like this:

(root (sub1 (sub2 (sub3) (sub4) (sub5) (sub5 (sub1 (sub6))) (sub5))))

I expect the formatted code to be like

(root
  (sub1
    (sub2
      (sub3)
      (sub4)
      (sub5)
      (sub5
        (sub1
          (sub6)))
      (sub5))))

However, it currently keeps the code as is.

raviqqe commented 10 months ago

Currently, Schemat doesn't support this due to its design.

Schemat is designed after gofmt which calculates proper indentations based on lines and columns of tokens in the input (the original source codes written by users.) The benefit of this is that we do not have to provide any configuration system for the formatter. Its downside is that we can't introduce any "opinionated" things (e.g. maximum line length) into the formatter. Also, given an AST of source codes, we can't define a single format.

How critical is it to format those things automatically in your workflow?

aminya commented 10 months ago

Thanks for the explanation.

I don't mind if the format breaks these parameters into separate lines using a default non-configurable limit.

Regarding your question, formatting these expressions is the only reason why I switched from scheme-format to this library. I am using this to make the code more readable during debugging.

raviqqe commented 10 months ago

I don't mind if the format breaks these parameters into separate lines using a default non-configurable limit.

I see. But if there is one, someone wants to configure it... 😅

Regarding your question, formatting these expressions is the only reason why I switched from scheme-format to this library. I am using this to make the code more readable during debugging.

I'm not sure if I understand your use case completely. But as I mentioned before, the format of source codes is based on the original one.

So this is formatted:

(root (sub1 (sub2 (sub3) (sub4) (sub5) (sub5 (sub1 (sub6))) (sub5))))

to the same one:

(root (sub1 (sub2 (sub3) (sub4) (sub5) (sub5 (sub1 (sub6))) (sub5))))

But this is formatted:

(root
  (sub1
    (sub2
      (sub3) (sub4) (sub5) (sub5 (sub1 (sub6))) (sub5))))

to:

(root
  (sub1
    (sub2
      (sub3)
      (sub4)
      (sub5)
      (sub5 (sub1 (sub6)))
      (sub5))))

So in short, if you insert newlines to the first few arguments of procedure calls. You can expand the rest arguments into separate lines too. Does it work for your use case?

raviqqe commented 10 months ago

It's a bit out of scope. I'm also thinking aligning spaces better for list elements in the middle:

For example, this is formatted as it is right now:

(let ((foo bar)
    (baz qux))
  body)

But it should be:

(let ((foo bar)
      (baz qux))
  body)
aminya commented 10 months ago

The code that generates these expressions doesn't add new lines:

https://github.com/tree-sitter/tree-sitter/blob/660481dbf71413eba5a928b0b0ab8da50c1109e0/lib/src/subtree.c#L867-L896

However, I just verified that patching the code by adding \n before the starting ( parenthesis results in better-formatted code with schemat.