Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,11 @@
"type": "boolean",
"default": false,
"description": "When creating a hanging indent, do not put the closing bracket on its own line."
},
"pythonIndent.closeHangingIndent": {
"type": "boolean",
"default": false,
"description": "Close a hanging indent when pressing Enter right before the closing bracket."
}
}
}
Expand Down
13 changes: 10 additions & 3 deletions src/indent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,20 @@ export function newlineAndIndent(
let toInsert = '\n';

try {
// TODO: Is this if test necessary? The keybindings in package.json already check this.
if (textEditor.document.languageId === 'python') {
const lines = textEditor.document.getText(
new vscode.Range(0, 0, position.line, position.character)).split("\n");
const remainder = textEditor.document.getText(
new vscode.Range(position.line, position.character, position.line, currentLine.length)).trim();
// Tell editsToMake to add a dedent if the curser is right before the closing bracket for a hanging indent.
const dedentIfHanging = "]})".includes(remainder[0]) && settings.closeHangingIndent;

const edits = editsToMake(
lines, currentLine, tabSize, position.line, position.character,
settings.trimLinesWithOnlyWhitespace,
settings.keepHangingBracketOnLine);
settings.keepHangingBracketOnLine,
dedentIfHanging);
toInsert = edits.insert;
edits.deletes.forEach(range => { edit.delete(range); });
hanging = edits.hanging;
Expand Down Expand Up @@ -64,9 +70,10 @@ export function editsToMake(
lineNum: number,
charNum: number,
trimLinesWithOnlyWhitespace: boolean,
keepHangingBracketOnLine: boolean
keepHangingBracketOnLine: boolean,
dedentIfHanging?: boolean
): { insert: string; deletes: vscode.Range[]; hanging: Hanging } {
let { nextIndentationLevel: indent, parseOutput: parseOut } = indentationInfo(lines, tabSize);
let { nextIndentationLevel: indent, parseOutput: parseOut } = indentationInfo(lines, tabSize, dedentIfHanging);
let deletes: vscode.Range[] = [];

// If cursor has whitespace to the right, followed by non-whitespace,
Expand Down
16 changes: 12 additions & 4 deletions src/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function indentationLevel(line: string): number {
return line.search(/\S|$/);
}

function nextIndentationLevel(parseOutput: IParseOutput, lines: string[], tabSize: number): number {
function nextIndentationLevel(parseOutput: IParseOutput, lines: string[], tabSize: number, dedentIfHanging?: boolean): number {
const row = lines.length - 1;
// openBracketStack: A stack of [row, col] pairs describing where open brackets are
// lastClosedRow: Either empty, or an array [rowOpen, rowClose] describing the rows
Expand Down Expand Up @@ -85,7 +85,11 @@ function nextIndentationLevel(parseOutput: IParseOutput, lines: string[], tabSiz
// Thus, nothing has happened that could have changed the
// indentation level since the previous line, so
// we should use whatever indent we are given.
return indentationLevel(lines[row]);
indentColumn = indentationLevel(lines[row]);
if (dedentIfHanging) {
// We're in a hanging indent, so we obey dedentIfHanging.
indentColumn -= tabSize;
}
} else if (justClosedBracket && closedBracketOpenedAfterLineWithCurrentOpen) {
// A bracket that was opened after the most recent open
// bracket was closed on the line we just finished typing.
Expand All @@ -108,6 +112,10 @@ function nextIndentationLevel(parseOutput: IParseOutput, lines: string[], tabSiz
// before the "9", because it would try to match it up with the
// open bracket instead of using the hanging indent.
indentColumn = indentationLevel(lines[last_closed_info.open]);
if (dedentIfHanging) {
// We're in a hanging indent, so we obey dedentIfHanging.
indentColumn -= tabSize;
}
} else {
// lastOpenBracketLocation[1] is the column where the bracket was,
// so need to bump up the indentation by one
Expand All @@ -117,9 +125,9 @@ function nextIndentationLevel(parseOutput: IParseOutput, lines: string[], tabSiz
return indentColumn;
}

export function indentationInfo(lines: string[], tabSize: number): { nextIndentationLevel: number; parseOutput: IParseOutput } {
export function indentationInfo(lines: string[], tabSize: number, dedentIfHanging?: boolean): { nextIndentationLevel: number; parseOutput: IParseOutput } {
const parseOutput = parse_lines(lines);
const nextIndent = nextIndentationLevel(parseOutput, lines, tabSize);
const nextIndent = nextIndentationLevel(parseOutput, lines, tabSize, dedentIfHanging);
return { nextIndentationLevel: nextIndent, parseOutput };
}

Expand Down
1 change: 1 addition & 0 deletions src/test/suite/indent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ def f():
]
];
simpleCases.forEach((inputOutput, index) => {
// TODO: add tests for new closeHangingIndent option. Probbaly other tests need edits, too.
let paramGrid: [boolean, boolean][] = [
[false, false], [false, true], [true, false], [true, true]];
test("simple case # " + (index + 1).toString(), async () => {
Expand Down