microsoft / language-server-protocol

Defines a common protocol for language servers.
https://microsoft.github.io/language-server-protocol/
Creative Commons Attribution 4.0 International
11.11k stars 780 forks source link

client->server request: Join Lines #992

Open matklad opened 4 years ago

matklad commented 4 years ago

Meta: I am in the process of formalizing protocol extensions, used by rust-analyzer. I will be filing issues for generally useful extensions. Here's the doc where we will document our extensions.

joinLines

Server Capability: { "joinLines": boolean }

This request is send from client to server to handle "Join Lines" editor action.

Method: experimental/JoinLines

Request:

interface JoinLinesParams {
    textDocument: TextDocumentIdentifier,
    /// Currently active selections/cursor offsets.
    /// This is an array to support multiple cursors.
    ranges: Range[],
}

Response:

TextEdit[]

Example

fn main() {
    /*cursor here*/let x = {
        92
    };
}

experimental/joinLines yields (curly braces are automagiacally removed)

fn main() {
    let x = 92;
}

Unresolved Question

dbaeumer commented 4 years ago

@jrieken FYI.

rwols commented 4 years ago

I'm not sure if I would like a text-oriented operation to be dependent on a language server. Why can't I use the regular join lines followed by a code action?

matklad commented 4 years ago

Using code action is certainly possible (you don't even need regular join lines, you can fold everything into code action). However in my experience as a user of IntelliJ, dwim "text-oriented" commands (enter, open line, join lines), if implemented correctly, can create a significantly better flow of development. Here's a nice example from Enter in Kotlin:

hello

I am pretty sure that there will be users who'd love this, and users who'd hate this. My gut feeling is that the first group is bigger.

From the protocol point of view, I'd think that we should unlock opportunities to precisely tweak user experience, rather than prescribe a specific way of doing things. Severs are free to not use the opportunities, users are free to disable specific features they feel are getting in the way.

rwols commented 4 years ago

I get that it's cool to have that functionality, but your above GIF would be implementable by a simple snippet.

matklad commented 4 years ago

but your above GIF would be implementable by a simple snippet.

I strongly disagree here: snippets indeed can be used to insert the same text, but it’s not the point. The point is dwim experience during basic editing operations, and that, by definition, can not be replaced with explicit user actions.

See also https://github.com/JetBrains/kotlin/tree/master/idea/src/org/jetbrains/kotlin/idea/joinLines which defined Kotlin’s custom behavior for join lines. There’s quite a bit of code there, and it can’t be replaced by simple snippets/code actions/etc.

It can be argued that having those features is not important/detrimental, but that would have to be a different argument than “we already can simulate them well enough”.

puremourning commented 4 years ago

I don't know if it matters to you but i'm almost 100% certain i would not implement this in my client.