From 794ad41ddbda6ccfdc447a49522c65eab171fdd9 Mon Sep 17 00:00:00 2001 From: Ryan Breen Date: Fri, 3 Feb 2017 11:09:33 -0500 Subject: [PATCH 1/4] delete matching brackets when the opening bracket is deleted --- src/matching/matcher.ts | 28 +++++++++++++++++++++++++++- src/mode/modeHandler.ts | 2 ++ test/mode/modeInsert.test.ts | 18 ++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/matching/matcher.ts b/src/matching/matcher.ts index b7d2a6ade0d..cbdd364dcb9 100644 --- a/src/matching/matcher.ts +++ b/src/matching/matcher.ts @@ -1,4 +1,5 @@ -import { Position } from './../motion/position'; +import { Position, PositionDiff } from './../motion/position'; +import * as vscode from 'vscode'; /** * PairMatcher finds the position matching the given character, respecting nested @@ -62,4 +63,29 @@ export class PairMatcher { // TODO(bell) return undefined; } + + /** + * Given a current position, find an immediate following bracket and return the range. If + * no matching bracket is found immediately following the opening bracket, return undefined. + */ + static immediateMatchingBracket(currentPosition: Position): vscode.Range | undefined { + let deleteRange = new vscode.Range(currentPosition, currentPosition.getLeftThroughLineBreaks()); + let deleteText = vscode.window.activeTextEditor.document.getText(deleteRange); + let matchRange: vscode.Range | undefined; + let isNextMatch = false; + + if ("{[(<".indexOf(deleteText) > -1) { + let matchPosition = currentPosition.add(new PositionDiff(0, 1)); + if (matchPosition) { + matchRange = new vscode.Range(matchPosition, matchPosition.getLeftThroughLineBreaks()); + isNextMatch = vscode.window.activeTextEditor.document.getText(matchRange) === PairMatcher.pairings[deleteText].match; + } + } + + if (isNextMatch && matchRange) { + return matchRange; + } + + return undefined; + } } \ No newline at end of file diff --git a/src/mode/modeHandler.ts b/src/mode/modeHandler.ts index 809bf02b5b8..cf21cc52a45 100644 --- a/src/mode/modeHandler.ts +++ b/src/mode/modeHandler.ts @@ -1291,6 +1291,8 @@ export class ModeHandler implements vscode.Disposable { break; case "deleteText": + let matchRange = PairMatcher.immediateMatchingBracket(command.position); + if (matchRange) { edit.delete(matchRange); } edit.delete(new vscode.Range(command.position, command.position.getLeftThroughLineBreaks())); break; diff --git a/test/mode/modeInsert.test.ts b/test/mode/modeInsert.test.ts index 2c3b25be60e..2636b4da328 100644 --- a/test/mode/modeInsert.test.ts +++ b/test/mode/modeInsert.test.ts @@ -174,6 +174,24 @@ suite("Mode Insert", () => { assertEqualLines([" "]); }); + test("will remove closing bracket", async() => { + await modeHandler.handleMultipleKeyEvents([ + 'i', + '(', + '' + ]); + + assertEqualLines(["()"]); + + await modeHandler.handleMultipleKeyEvents([ + 'a', + '', + '' + ]); + + assertEqualLines([""]); + }); + newTest({ title: "Can perform to exit and perform one command in normal", start: ['testtest|'], From 99e1b0d0432e3d079b6f714dc1923ca6cacb0b8a Mon Sep 17 00:00:00 2001 From: Ryan Breen Date: Fri, 3 Feb 2017 16:08:51 -0500 Subject: [PATCH 2/4] check for autoClosingBrackets before deleting a closing bracket --- src/matching/matcher.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/matching/matcher.ts b/src/matching/matcher.ts index cbdd364dcb9..368b095772e 100644 --- a/src/matching/matcher.ts +++ b/src/matching/matcher.ts @@ -69,6 +69,9 @@ export class PairMatcher { * no matching bracket is found immediately following the opening bracket, return undefined. */ static immediateMatchingBracket(currentPosition: Position): vscode.Range | undefined { + // Don't delete bracket unless autoClosingBrackets is set + if (!vscode.workspace.getConfiguration().get("editor.autoClosingBrackets")) { return undefined; } + let deleteRange = new vscode.Range(currentPosition, currentPosition.getLeftThroughLineBreaks()); let deleteText = vscode.window.activeTextEditor.document.getText(deleteRange); let matchRange: vscode.Range | undefined; From 75e2cae798c384c48e9a94c7075117dd7bbff05c Mon Sep 17 00:00:00 2001 From: Ryan Breen Date: Sat, 4 Feb 2017 09:52:38 -0500 Subject: [PATCH 3/4] adding quote characters to bracket deletion --- src/matching/matcher.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/matching/matcher.ts b/src/matching/matcher.ts index 368b095772e..29e6855bcf6 100644 --- a/src/matching/matcher.ts +++ b/src/matching/matcher.ts @@ -15,8 +15,13 @@ export class PairMatcher { "]" : { match: "[", nextMatchIsForward: false, matchesWithPercentageMotion: true }, // These characters can't be used for "%"-based matching, but are still // useful for text objects. - "<" : { match: ">", nextMatchIsForward: true }, + "<" : { match: ">", nextMatchIsForward: true }, ">" : { match: "<", nextMatchIsForward: false }, + // These are useful for deleting closing and opening quotes, but don't seem to negatively + // affect how text objects such as `ci"` work, which was my worry. + '"' : { match: '"', nextMatchIsForward: true }, + "'" : { match: "'", nextMatchIsForward: true }, + "`" : { match: "`", nextMatchIsForward: true }, }; static nextPairedChar(position: Position, charToMatch: string, closed: boolean = true): Position | undefined { @@ -77,7 +82,7 @@ export class PairMatcher { let matchRange: vscode.Range | undefined; let isNextMatch = false; - if ("{[(<".indexOf(deleteText) > -1) { + if ("{[(\"'`".indexOf(deleteText) > -1) { let matchPosition = currentPosition.add(new PositionDiff(0, 1)); if (matchPosition) { matchRange = new vscode.Range(matchPosition, matchPosition.getLeftThroughLineBreaks()); From 04a81ae2e31e4e683f901dbe73c5409ab274186d Mon Sep 17 00:00:00 2001 From: Ryan Breen Date: Sun, 5 Feb 2017 09:04:29 -0500 Subject: [PATCH 4/4] minor tweaks for using const and removing unnecessary branch --- src/matching/matcher.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/matching/matcher.ts b/src/matching/matcher.ts index 29e6855bcf6..1577511c6ba 100644 --- a/src/matching/matcher.ts +++ b/src/matching/matcher.ts @@ -77,17 +77,15 @@ export class PairMatcher { // Don't delete bracket unless autoClosingBrackets is set if (!vscode.workspace.getConfiguration().get("editor.autoClosingBrackets")) { return undefined; } - let deleteRange = new vscode.Range(currentPosition, currentPosition.getLeftThroughLineBreaks()); - let deleteText = vscode.window.activeTextEditor.document.getText(deleteRange); + const deleteRange = new vscode.Range(currentPosition, currentPosition.getLeftThroughLineBreaks()); + const deleteText = vscode.window.activeTextEditor.document.getText(deleteRange); let matchRange: vscode.Range | undefined; let isNextMatch = false; if ("{[(\"'`".indexOf(deleteText) > -1) { - let matchPosition = currentPosition.add(new PositionDiff(0, 1)); - if (matchPosition) { - matchRange = new vscode.Range(matchPosition, matchPosition.getLeftThroughLineBreaks()); - isNextMatch = vscode.window.activeTextEditor.document.getText(matchRange) === PairMatcher.pairings[deleteText].match; - } + const matchPosition = currentPosition.add(new PositionDiff(0, 1)); + matchRange = new vscode.Range(matchPosition, matchPosition.getLeftThroughLineBreaks()); + isNextMatch = vscode.window.activeTextEditor.document.getText(matchRange) === PairMatcher.pairings[deleteText].match; } if (isNextMatch && matchRange) {