-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Python file indentation is wrong #763
Comments
Indent support requires an If anyone wants to take this up, there's https://github.com/nvim-treesitter/nvim-treesitter/blob/master/queries/python/indents.scm and the tree-sitter python grammar for reference. |
I think it's not easy (if feasible at all) with the current Tree-sitter only indentation logic. In most editors when I type:
I expect the whole In helix, TreeSitter fails to parse outdent = [
"else_clause"
] doesn't work. I can't see another way than parsing the current line ourselves at each return It's a chicken-and-egg problem. Note nvimTS has the same issue, which is really annoying, but easier to deal with because of smarttabs, a single |
That said, a single indent = [ ":", "list", "tuple", "dictionary", "set"] does a good job at indenting. |
I've only had helix for a few days so I may not be understanding this correctly. Is this not the indents config for Python? https://github.com/helix-editor/helix/blob/master/runtime/queries/python/indents.scm Yet I still don't get auto-indent. |
I get autoindentation if I press Enter when the marker is at | in the following: a = list(|)
->
a = list(
|
) but I do not get it with the if statement as hinted should happen in the the file @willparsons refers to above. if a == 1:|
->
if a == 1:
| |
any news on this? I'm looking forward to switching to helix |
The lack of auto-indentation is the only thing that keeps me from fully embracing Helix. For the most part it's great (especially because most things work out of the box), but auto-indent is really the level of convenience every text-editor should offer. Maybe I'm doing something wrong (I've installed Helix via Pacman and pylsp via pip and downloaded the languages.toml file from the repo), but for me not even Indentation after ":" is working, let alone aligning parentheses or operators in multiline clauses. Is the issue really as severe as @lisael is pointing out? Any hope for a feasible solution in the near to mid future? Incidentally, what does the "Auto Indent" on the languages page refer to exactly? That it's part of the auto-formatting? |
Had a bit of a look into this. Thought I'd document my understanding of the issue. def func():#<- this cursor position is within the "module" node, not the "function_definition" node
if True:#<- this cursor position is within the "module" node, not the "if_statement" node Where node refers to tree-sitter tree node. You can have a play in the playground with this. As a simplification the indents are calculated by traversing the tree and counting the number of nodes that have the capture type def func1(#):
def func2():#
x = 1 I suspect there isn't any way to fix this with the current way helix does indentation. Neovim seems to support some additional capture types, e.g., https://github.com/nvim-treesitter/nvim-treesitter/blob/master/queries/python/indents.scm |
One idea to solve this is:
Specifically when adding a new line, determine all nodes associated with one position back from the current cursor position. If any of those nodes are I'm not sure if any other languages would potentially benefit from this (yaml?). Another idea: The above is reasonably convoluted given that the rule could probably be simplified down to: if the character at the end of the line is a @WindSoilder did you have any more thoughts on how to resolve this after doing the original implementation in #837? |
@paul-scott Sorry, I don't have ideas, and actually I don't know much about I just think that once the relative |
No worries. When / if there is a solution for nvim it is possible that it gets solved specifically for nvim-treesitter in their wrapper / libraries rather than the upstream treesitter implementation. So while it would be useful to follow a similar approach, it could still use a bit of effort to implement for helix. Neovim also has other non-treesitter ways to do indentation which in my experience work quite well. In helix I believe we just have the option of treesitter-based or copy-the-indentation-of-the-previous-line-based indentation. So there is more motivation at the moment to get a better solution working in helix whether tree-sitter-based or otherwise. |
@paul-scott The
Let me know what you think and if I've overlooked anything. If you (or anyone else) want to implement it, I'll be happy to help with any questions. Otherwise, I'll do it at some point, but it'll probably take 2 or 3 months until I get to it. |
What you suggest sounds like it would be cleaner.
Yea that seems important in python.
Nothing obvious to me at this point. I'm sure there will be some challenges when it actually comes to implementing it. I'll have a go if I can find some spare time. |
One thing I noticed as well when
|
There's been a lot of complaints about the state of python indentation and the fallback actually works better until the solution proposed in #763 (comment) is implemented.
I believe related to this issue is that I think the underlying tree-sitter grammar for Python is not great for interactive use. Case in point: def foo():
try:
1 + At this point This relates to indentation because depending on the state of how it parses this, completely different rules apply. I reckon the underlying tree-sitter stuff for Python probably needs adjusting for the use here. |
@mitsuhiko good point, I want to mention another find. tree-sitter doesn't recognize the try statement until we put the corresponding Could we just also add an I could try that and see how feasible that is, and submit a PR if I succeed. |
The
|
My bad! I just realized I conflated two separate issues. When I was talking about |
After playing around with tree-sitter a bit more, the first proposed option of modifying tree-sitter would actually require allowing for "invalid" programs since a try-statement can't be standalone without an except or finally clause. Why As for the second mentioned approach, I initially tried (
(ERROR) @try_clause
(#match? @try_clause "try:.*")
) @indent @extend which handles try: correctly, but not: def fn(x):
try: If you try it out in the tree-sitter playground, you'll see that the To remedy this, maybe we could add more predicates such that we can single out specific subcaptures with a regex, like (
(ERROR) @try_clause
(#regex-capture? @try_clause "try:.*")
) @indent @extend These two solutions aside, another solution might be with a plugin system (#3806). We might want a plugin system to handle the retroactive dedenting too. Here is how neovim does it. |
Thanks for looking into this @zyklotomic. What I mean by adjusting the tree-sitter grammar is not to make it parse incorrect code without producing any I had a look at the playground and came up with some queries which seem to work pretty well. The PR is #5332, if you want to try it out and report any issues, that would be a great help. As for retroactive indenting/dedenting, I'm thinking if we can find a general, language-agnostic solution to this. It'd be nice if Helix could automatically rerun indent queries when the syntax tree changes and adjust the indent of existing lines. This will probably take some time though, as it has to be fast, accurate and it needs to detect when the user is trying to override the computed indent (for example when it is incorrect). |
I like the idea of wanting to find a language-agnostic solution, but I'm also wondering how pragmatic it would be. What other languages depend on indentation as syntax / and or benefit from these changes? |
I've definitely come across the need to retroactively update indentation in several languages. For example, in C/C++, labels are usually outdented: int main() {
start:
do_smth();
goto start;
}
I do agree that python is probably one of the languages where such a feature is the most important. |
Reproduction steps
o
to insert newlineEnvironment
zero config.
The text was updated successfully, but these errors were encountered: