Skip to content

Commit

Permalink
Base continued body in indentation on the indentation of the line before
Browse files Browse the repository at this point in the history
FIX: Improve the way indentation for the current body is preserved
when inenting new lines.

Issue codemirror/dev#1370
  • Loading branch information
marijnh committed Apr 29, 2024
1 parent cc69f68 commit 0468622
Showing 1 changed file with 28 additions and 14 deletions.
42 changes: 28 additions & 14 deletions src/python.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,28 @@ import {delimitedIndent, indentNodeProp, TreeIndentContext,
import {globalCompletion, localCompletionSource} from "./complete"
export {globalCompletion, localCompletionSource}

function innerBody(context: TreeIndentContext) {
let {node, pos} = context
let lineIndent = context.lineIndent(pos, -1)
let found = null
for (;;) {
let before = node.childBefore(pos)
if (!before) {
break
} else if (before.name == "Comment") {
pos = before.from
} else if (before.name == "Body") {
if (context.baseIndentFor(before) + context.unit <= lineIndent) found = before
node = before
} else if (before.type.is("Statement")) {
node = before
} else {
break
}
}
return found
}

function indentBody(context: TreeIndentContext, node: SyntaxNode) {
let base = context.baseIndentFor(node)
let line = context.lineAt(context.pos, -1), to = line.from + line.text.length
Expand All @@ -31,7 +53,10 @@ export const pythonLanguage = LRLanguage.define({
parser: parser.configure({
props: [
indentNodeProp.add({
Body: context => indentBody(context, context.node) ?? context.continue(),
Body: context => {
let inner = innerBody(context)
return indentBody(context, inner || context.node) ?? context.continue()
},
IfStatement: cx => /^\s*(else:|elif )/.test(cx.textAfter) ? cx.baseIndent : cx.continue(),
"ForStatement WhileStatement": cx => /^\s*else:/.test(cx.textAfter) ? cx.baseIndent : cx.continue(),
TryStatement: cx => /^\s*(except |finally:|else:)/.test(cx.textAfter) ? cx.baseIndent : cx.continue(),
Expand All @@ -40,19 +65,8 @@ export const pythonLanguage = LRLanguage.define({
"ArrayExpression ArrayComprehensionExpression": delimitedIndent({closing: "]"}),
"String FormatString": () => null,
Script: context => {
if (context.pos + /\s*/.exec(context.textAfter)![0].length >= context.node.to) {
let endBody = null
for (let cur: SyntaxNode | null = context.node, to = cur.to;;) {
cur = cur.lastChild
if (!cur || cur.to != to) break
if (cur.type.name == "Body") endBody = cur
}
if (endBody) {
let bodyIndent = indentBody(context, endBody)
if (bodyIndent != null) return bodyIndent
}
}
return context.continue()
let inner = innerBody(context)
return (inner && indentBody(context, inner)) ?? context.continue()
}
}),
foldNodeProp.add({
Expand Down

2 comments on commit 0468622

@VsevolodX
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be optional?
When using Cypress tests, the type() command adds additional indentation, for two function definitions like:

def function():
    print("first one is correct")

    def function2():
        print("indentation wasn't intended")

It wasn't the issue before. Might as well happen to Chimp.

@marijnh
Copy link
Member Author

@marijnh marijnh commented on 0468622 May 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know what the type command is, or what Chimp refers to, but I think it's reasonable behavior to require a backspace to dedent when leaving an indented scope.

Please sign in to comment.