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

Implement "Indent Model" #4182

Open
gilescope opened this issue Apr 28, 2020 · 7 comments
Open

Implement "Indent Model" #4182

gilescope opened this issue Apr 28, 2020 · 7 comments
Labels
A-formatting formatting of r-a output/formatting on save C-enhancement Category: enhancement E-hard fun A technically challenging issue with high impact S-unactionable Issue requires feedback, design decisions or is blocked on other work

Comments

@gilescope
Copy link
Contributor

I didn't know that backspace could be improved. How wrong I was! I hope JetBrains roll out Clion backspace handling across all their products. I'd also love to see it in Rust Analyzer.

There's already special enter key handling so backspace should be possible...

I think the rules are that the first backspace takes you up a level in indentation, but then the second gobbles up all the whitespace to the start of the line and the line brake so that it appends onto the end of the previous line. This turns out to be what I wanted to do so much of the time - it feels so natural.

Small things make such a difference. Well done Clion for bringing a better backsapce to the world.

@matklad matklad changed the title The way Clion does backspace is to die for Implement "Indent Model" Apr 28, 2020
@matklad matklad added E-hard fun A technically challenging issue with high impact labels Apr 28, 2020
@matklad
Copy link
Member

matklad commented Apr 28, 2020

Yeah, open line / newline / backspace all can benefit from indentation info...

There are two pieces to the puzzle:

  • implement indentation model, so that we know what the indentation should be. I wonder whether this is actually blocked on formatting? It seems like we can start coding something up just for indent, and then re-rail it onto proper formatting engine...
  • implement editor-side hooks. We already have a hook for enter, the one for backspace can be added similarly

Heck, I think we should have this sooner rater than later, as it seems like our onEnter does not stress the editing as much as it should.

@flodiebold
Copy link
Member

I have to say that the behavior described in the issue seems like something that should be handled by the editor and not be language-specific, but maybe I'm misunderstanding it 🤔

@matklad
Copy link
Member

matklad commented Apr 28, 2020

It has to be language specific I think. For example, here's some Kotlin code

fun <T> frobnicate(a: T, b: T)
        where T : Comparable<T>,
              T : Runnable {

    frobnicate(a,
               b
    )
}

Here, the T's should be aligned according to code style, but b should be just indented. The backspace behavior is different for two:

indent

Also, unrelated, but the gutter icons in IntelliJ are soooo much better than code lens :( Like this little recursion swirly it's just cute, and we can't have that in VS Code TT

@Timmmm
Copy link
Contributor

Timmmm commented Aug 10, 2020

I think it would be a bad idea to implement this in VSCode for the same reason that messing with multiline commends was a bad idea:

  1. Users won't expect it, and it produces editing inconsistencies with editing different languages.
  2. Messing with text editing in an extension causes performance issues in VSCode at the moment.

@bjorn3
Copy link
Member

bjorn3 commented Aug 10, 2020

  1. Users won't expect it, and it produces editing inconsistencies with editing different languages.

VSCode already does this. For Rust it often produces unexpected or plain wrong results like the following though:

let a = b
    .c();<|>

Pressing enter gives:

let a = b
    .c();
    <|>

That is too much indentation. Even when you already deindented the next line pressing enter decides that it needs to indent anyway:

let a = b
    .c();
<|>

gives

let a = b
    .c();

    <|>

This is annoying.

@Timmmm
Copy link
Contributor

Timmmm commented Oct 19, 2020

VSCode already does this.

Not sure exactly what you mean by "this", but it does seem that VSCode does some limited language-specific indentation. It is controlled by onEnterRules, e.g. Python, PHP.

It is regex based, and the actions are limited to the following, plus appending text (e.g. /// for comments)

	export enum IndentAction {
		/**
		 * Insert new line and copy the previous line's indentation.
		 */
		None = 0,
		/**
		 * Insert new line and indent once (relative to the previous line's indentation).
		 */
		Indent = 1,
		/**
		 * Insert two new lines:
		 *  - the first one indented which will hold the cursor
		 *  - the second one at the same indentation level
		 */
		IndentOutdent = 2,
		/**
		 * Insert new line and outdent once (relative to the previous line's indentation).
		 */
		Outdent = 3
	}

I don't think it is quite powerful enough to be useful in your example because you can only look back one line.

On reflection I think you are right that it would be nice to fix it, but I don't think the best way is by intercepting ever keypress in the language server because of the performance issues we've already seen.

@lnicola lnicola added the S-unactionable Issue requires feedback, design decisions or is blocked on other work label Jan 22, 2021
@kjeremy
Copy link
Contributor

kjeremy commented Feb 4, 2021

As of vscode 1.53.0 OnEnterRule now supports: OnEnterRule.previousLineText so we can get at the previous line.

@Veykril Veykril added the A-formatting formatting of r-a output/formatting on save label Nov 11, 2022
@Veykril Veykril added the C-enhancement Category: enhancement label Feb 9, 2023
bors added a commit that referenced this issue Feb 10, 2023
…emBits

fix: Suppress extra indent after the end of field and function chains

(spurred on by <#4182 (comment)>)

Caveat that this doesn't work for after tail expressions, although there shouldn't be anything after those anyways.

This also complicates when to reload the language configuration by nature of now always having a language configuration applicable.

Examples of indentation fixes:

```rs
fn main() {
    println!("Hello!"); // < enter here!
    // ... indents down here

    fs::read_to_string("soup") // < enter here!
    // ... still indents down here :(
        .map(|_| ())
        .map(|_| ()) // < enter here!
        // ... still indents down here :D
        .map_err(|_| ())
        .unwrap(); // < enter here!
    // ... indents down here :D

    // ... and subsequent enters stay at the same indent

    0.0f64
        .to_radians()
        .to_radians()
        .to_radians() // force semi on a new line
        ; // < enter here!
    // ... indents down here :D
}

fn tail_end() -> i32 {
    0i32.wrapping_abs()
        .wrapping_abs()
        .wrapping_abs()
        .wrapping_abs() // < enter here!
        // ... still indents here 🤷
}
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-formatting formatting of r-a output/formatting on save C-enhancement Category: enhancement E-hard fun A technically challenging issue with high impact S-unactionable Issue requires feedback, design decisions or is blocked on other work
Projects
None yet
Development

No branches or pull requests

8 participants