Skip to content

Commit

Permalink
Add test cases of reindenting an existing line and update the code
Browse files Browse the repository at this point in the history
  • Loading branch information
whitphx committed May 16, 2024
1 parent 6c32e8f commit f3c90cb
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 10 deletions.
28 changes: 18 additions & 10 deletions src/commands/tab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class TabToTabStop extends EmacsCommand {

const indentChars = insertSpaces ? tabSize : 1;

const editsAndMoves = textEditor.selections.map((selection) => {
const indentOps = textEditor.selections.map((selection) => {
let prevNonEmptyLine: vscode.TextLine | undefined;
for (let i = selection.active.line - 1; i >= 0; i--) {
const line = textEditor.document.lineAt(i);
Expand All @@ -29,30 +29,38 @@ export class TabToTabStop extends EmacsCommand {
const newIndentChars = newIndentUnits * indentChars;

const curLine = textEditor.document.lineAt(selection.active.line);
const charsToInsert = Math.max(newIndentChars - curLine.firstNonWhitespaceCharacterIndex, 0);
const charsToMoveCurAfterIndent = Math.max(
const charsOffsetAfterIndent = Math.max(
selection.active.character - curLine.firstNonWhitespaceCharacterIndex,
0,
);

return {
line: selection.active.line,
charsToInsert,
cursorChars: newIndentChars + charsToMoveCurAfterIndent,
newIndentChars,
newCursorChars: newIndentChars + charsOffsetAfterIndent,
};
});

// Update the indents
const indentChar = insertSpaces ? " " : "\t";
textEditor.edit((editBuilder) => {
editsAndMoves.forEach((editAndMove) => {
const lineHead = new vscode.Position(editAndMove.line, 0);
editBuilder.insert(lineHead, indentChar.repeat(editAndMove.charsToInsert));
indentOps.forEach((indentOp) => {
const line = textEditor.document.lineAt(indentOp.line);
const lineHead = line.range.start;
const charsToInsertOrDelete = indentOp.newIndentChars - line.firstNonWhitespaceCharacterIndex;
if (charsToInsertOrDelete >= 0) {
editBuilder.insert(lineHead, indentChar.repeat(charsToInsertOrDelete));
} else {
editBuilder.delete(new vscode.Range(lineHead, new vscode.Position(indentOp.line, -charsToInsertOrDelete)));
}
});
});
textEditor.selections = editsAndMoves.map((editAndMove) => {
const active = new vscode.Position(editAndMove.line, editAndMove.cursorChars);
// Update the cursor positions
textEditor.selections = indentOps.map((indentOp) => {
const active = new vscode.Position(indentOp.line, indentOp.newCursorChars);
return new vscode.Selection(active, active);
});

this.emacsController.exitMarkMode();
}

Expand Down
35 changes: 35 additions & 0 deletions src/test/suite/commands/tab.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,4 +198,39 @@ print("hello")`;
assertCursorsEqual(activeTextEditor, [0, 0]);
});
});

suite("reindent existing lines", () => {
const initialText = `def f():
print("hello")`;

setup(async () => {
activeTextEditor = await setupWorkspace(initialText, { language });
activeTextEditor.options.tabSize = tabSize;
emulator = new EmacsEmulator(activeTextEditor);
});

teardown(cleanUpWorkspace);

test("reindent works and the cursor is moved to the indent head when the cursor was at the beginning fo the line", async () => {
setEmptyCursors(activeTextEditor, [1, 0]);
await emulator.runCommand("tabToTabStop");
assertTextEqual(
activeTextEditor,
`def f():
print("hello")`,
);
assertCursorsEqual(activeTextEditor, [1, 4]);
});

test("reindent works and the cursor is not moved when the cursor was after the indent head", async () => {
setEmptyCursors(activeTextEditor, [1, 8]);
await emulator.runCommand("tabToTabStop");
assertTextEqual(
activeTextEditor,
`def f():
print("hello")`,
);
assertCursorsEqual(activeTextEditor, [1, 4]);
});
});
});

0 comments on commit f3c90cb

Please sign in to comment.