Skip to content

Revise Python indent behaviour#4

Closed
microbit-matt-hillsdon wants to merge 1 commit intocodemirror:mainfrom
microbit-matt-hillsdon:indent-rethink
Closed

Revise Python indent behaviour#4
microbit-matt-hillsdon wants to merge 1 commit intocodemirror:mainfrom
microbit-matt-hillsdon:indent-rethink

Conversation

@microbit-matt-hillsdon
Copy link
Copy Markdown
Contributor

I've been testing the Python authoring experience and comparing to VS Code. I think the VS Code indentation generally feels more usual for Python. There are a few cases where CM feels like it is getting in the way and fighting a user's indentation changes and a few where it's not helpful in what feel to me to be clear-cut scenarios.

I've attempted to align the behaviour as I explored this. Details and exceptions noted below. Just a draft PR for now for discussion. Happy to move discussion wherever you'd prefer.

I think it captures the behaviours that I'm interested in. I'm not so confident in the implementation yet. I'll test it some more over the coming days but would love some feedback. Hopefully the tests provide some cases to try out that illustrate differences. I appreciate that indentation preferences can be subjective but I'm interested in exploring whether these changes make sense for lang-python.

Demos:

I've focussed on the automatic indent when typing code and I'm hazy on other uses of indent within CodeMirror. Will my approach here cause issues with other indent-related features?

CC @mattpauldavies based on recent interest in Python indentation.


Details of the change:

This aims to follow VS Code's behaviour and biases towards not changing
the indent as the user may be in the middle of rearranging code.

As an exception, we implement dedent behaviour for return and raise.
VS Code doesn't do this as they don't have a way to tell if you're in
the middle of the expression after the return or raise.

Significant changes:

  • Adds dedent behaviour for constructs that must end a body.
  • Adds delimited indents for argument lists, parameter lists and
    parathesized expressions. The latter is necessary for tuple indents to
    work properly as a tuple isn't parsed as such when first being written.
  • Doesn't fight manual dedents. Previously trying to dedent then leave a
    blank line or two before the next statement would result in a reindent.
  • Removes dedent for else and similar to match VS Code. VS Code has
    attempted to add these in the past but has had to revert because of
    users finding them more annoying than helpful. The implementation here
    was double-dedenting if the user dedented manually and wrote a valid
    if/else statement.

This aims to follow VS Code's behaviour and biases towards not changing
the indent as the user may be in the middle of rearranging code.

As an exception, we implement dedent behaviour for return and raise.
VS Code doesn't do this as they don't have a way to tell if you're in
the middle of the expression after the return or raise.

Significant changes:

- Adds dedent behaviour for constructs that must end a body.
- Adds delimited indents for argument lists, parameter lists and
  parathesized expressions. The latter is necessary for tuple indents to
  work properly as a tuple isn't parsed as such when first being written.
- Doesn't fight manual dedents. Previously trying to dedent then leave a
  blank line or two before the next statement would result in a reindent.
- Removes dedent for else and similar to match VS Code. VS Code has
  attempted to add these in the past but has had to revert because of
  users finding them more annoying than helpful. The implementation here
  was double-dedenting if the user dedented manually and wrote a valid
  else statement.
@marijnh
Copy link
Copy Markdown
Member

marijnh commented Jul 27, 2021

I'll spend more time looking into this later, but at a glance, I don't think the use of currentIndent is solid—try pressing enter after something like...

def foo():
  foo(bar,
      baz)

That will align the cursor with baz. Using the indentation of the line that context.pos is on is generally problematic—in insertNewlineAndIndent the indent context's simulateBreak feature is used, which is ignored when you go straight through the doc, and more generally, there is no indentation for the new line yet, so trying to compute that to use as a baseline isn't generally meaningful.

@microbit-matt-hillsdon
Copy link
Copy Markdown
Contributor Author

Thanks @marijnh. I'll give that some thought tomorrow. For the example you give, it indents under baz which does match VS Code. That doesn't feel unexpected to me, but doubtless some of this is the behaviours you're used to.

I'm interested in using current indent because I'm worried we otherwise end up fighting the user's intentional indent changes. I think this is the worst example, where the user intends to end the block, leave a blank line and start a new block of code but the indentation is forced into alignment with the body:

reindent

Absent a clear indication of the end of the block I think you probably need to consider the current indent.

marijnh added a commit that referenced this pull request Aug 11, 2021
FIX: Indentation on deindented blank lines after a block will no longer
return to the block's indentation level.

Issue #4
@marijnh
Copy link
Copy Markdown
Member

marijnh commented Aug 14, 2021

Does the behavior in @codemirror/lang-python 0.19.2 address your concerns?

@microbit-matt-hillsdon
Copy link
Copy Markdown
Contributor Author

Does the behavior in @codemirror/lang-python 0.19.2 address your concerns?

That looks interesting, thank you. I'm away for the next week, but I'll take a proper look when I'm back and follow up here.

@mattpauldavies
Copy link
Copy Markdown
Contributor

For what it's worth, I've been testing @codemirror/lang-python 0.19.2 today and it looks to be pretty much bang on! Amazing work as ever, @marijnh 🙌

@marijnh
Copy link
Copy Markdown
Member

marijnh commented Aug 16, 2021

Cool. Going to close this, feel free to report any further mess-ups that you find.

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

Successfully merging this pull request may close these issues.

3 participants