Skip to content
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

Feature request: new line indenting #52

Closed
monroth opened this issue May 17, 2021 · 18 comments
Closed

Feature request: new line indenting #52

monroth opened this issue May 17, 2021 · 18 comments

Comments

@monroth
Copy link

monroth commented May 17, 2021

Currently, when you enter new line, it indents it on same level as previous line.
So, if you enter new line
(declare (optimize (safety 3) (debug 3)))
between (safety 3) and (debug 3), it will indent it as

  (declare (optimize (safety 3) 
  (debug 3)))

If it is possible, it would be nice if it would automatically indent it correctly, like

  (declare (optimize (safety 3) 
                     (debug 3)))

Or if we had such an option

@nobody-famous
Copy link
Owner

I've been wanting to fix this for a while. I'll look into it again. There's an editor.formatOnType setting, but it's not working. I also don't know if it formats the entire document, which would be bad.

@mseddon
Copy link

mseddon commented Jul 2, 2022

@nobody-famous

I have a bit of free time coming up, and happy to work on that, or help @n00p3 with #54.

formatOnType doesn't format the entire document, but basically allows you to insert edits after user input, although I'd need to discuss a bit with you about how your current LSP setup works etc (I haven't actually used the LSP features of vscode yet, and I recall doing some wild contortions for calva to make it work cleanly- though I think a simpler approach is probably possible here). Lack of sane lexical information from vscode does make it a bit fiddly. If you are on libera.net I'm often tucked away in #commonlisp or #lisp. Feel free to pm me. If not, I'm slowly working my way through the source so I'll be better positioned in a bit to pick it up anyway.

@nobody-famous
Copy link
Owner

@mseddon If you want to take a crack at it, go for it. I think it'll be easier now that everything's server side. I don't think it'll require any changes on the client side. The formatting code now handles range formatting, so it should be possible to reuse that code to get the edits.

@nobody-famous
Copy link
Owner

I've looked into it a bit more. The formatOnType feature is apparently quite annoying. It's disabled by default and it looks like very few people turn it on because, well, it's annoying. The "right" solution is to use what they call "OnEnterRules". Unfortunately, where enter gets handled is not in async code so can't call the language server to do the work. It's regex based, which means it can't match parenthesis. There's an issue against vscode that's still open from 2019 about this. microsoft/vscode#66235

@nobody-famous
Copy link
Owner

Since I was poking around with it, I went ahead and implemented it. The new version seems to mostly be doing the right thing. I'll need to test it some more to see if there's anything it's messing up.

@mseddon
Copy link

mseddon commented Jul 16, 2022

@nobody-famous the async nature of formatOnType really is horrible to work with, and while formatOnType used to be fairly innocuous, it has recently started being incredibly opinionated with a lot of languages. I hadn't come across OnEnterRules I don't think. What is really silly is with a well specified tmSyntax, vscode will maintain a nested representation, however I haven't found a way to access that information from an extension. Even with formatOnType, I was not able to prevent a slight delay after pressing return before the indentation kicks in, so I had to provide a 'good enough' solution rather than something that felt decent, since Lisp just requires auto indentation to prevent insanity.

@PEZ is there a better way to approach this these days?

@nobody-famous
Copy link
Owner

The formatOnType doesn't get called until after the static analysis stuff like the OnEnterRules have done their thing. I've got edge cases in my solution I need to deal with at some point because it ends up double indenting things. The format on type code needs to figure out what the vscode static stuff did and adjust that. Since it's doing throw away work, there's a bit of a pause.

The problem with Common Lisp is that it's not possible to statically analyze it. Not accurately, anyway. The slime source code is a good example. They have a lot of functions that are defined by macros instead of defun, so the only way to know they're functions is to run the macros. I originally wrote this extension just to be a formatter, but I ended up needing to talk to a running image to do the formatting. It snowballed from there.

For other languages, it's fine to leave it to statistic analysis, but lisp has to query the image. Letting the OnEnterRules call the server would be the best solution because it allows for dynamic analysis without doing extra work. It sounds like that won't happen anytime soon because they're concerned about potential performance issues.

@PEZ
Copy link

PEZ commented Jul 17, 2022

@mseddon, things haven't really improved around this. Calva is relying on the infrastructure you added for this. It works great, btw. 😄

@mseddon
Copy link

mseddon commented Jul 19, 2022

@nobody-famous this is why I had to resort to some fairly fun contortions for Calva. Effectively I had a mirrored, lexically analysed copy of the document, and implemented emacs-like paredit navigation like forward-sexpr etc. From there I had heuristics to format the code by examining the surrounding context- crude, but enough to be useful. It was not a particularly fun task however, and has obvious limitations wrt macro expansion as you allude to. It's surprisingly hard to coax vscode into formatting Lisp it seems.

@lewisl
Copy link

lewisl commented Jul 31, 2023

Still seems really broken for me. here is what I get:

    (let ((elt (node-elt bst)))
                             (if (eql obj elt)

Every time I type anything, auto-indent starts the next line past the end of the previous line, which is about the worst thing it could do.

I've tried different language specific settings here, but these have no effect at all:

    "[Common Lisp]": {
        "editor.tabSize": 2,
        "editor.indentSize": "tabSize",
        "editor.autoIndent": "none",
    },

"none", "full", "advanced"--> all do the same thing.

I also tried the editor.autoIndent setting and it also does nothing:

    "editor.autoIndent": "none",

So, something seems to be overriding what happens based on settings. I have searched for indentation and indent in settings.json and nothing pops out at me.

I'd be happy to go with VS Code defaults if there is such a thing... or if there is an alive. specific setting?

@nobody-famous
Copy link
Owner

I'll look into, that means I broke something. It shouldn't be doing that. The formatter seems to be getting confused.
Does format document do the right thing? It only does this while typing?

@lewisl
Copy link

lewisl commented Aug 1, 2023 via email

@nobody-famous
Copy link
Owner

Are you using other lisp extensions? I'm not able to recreate it so far, so I'm wondering if another extension might also be handling the format on type command and it's double indenting or something. If that's the case, I could add an option to Alive to ignore format on type and let the other extension handle it.

@lewisl
Copy link

lewisl commented Aug 2, 2023 via email

@lewisl
Copy link

lewisl commented Aug 2, 2023 via email

@lewisl
Copy link

lewisl commented Aug 2, 2023 via email

@nobody-famous
Copy link
Owner

Ok. I've seen similar things from VSCode where I had to nuke a directory and clone from github again to get it to behave.

@lewisl
Copy link

lewisl commented Aug 7, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants