mirror of
https://github.com/jasonwilliams/vscode-helix.git
synced 2024-08-17 04:10:46 +03:00
Fix bug with bracket matching and improve it with counts
This commit is contained in:
parent
e17dcb808f
commit
4ec1caf239
@ -3,6 +3,7 @@ import { Action } from '../action_types';
|
||||
import { enterInsertMode, setModeCursorStyle } from '../modes';
|
||||
import { Mode } from '../modes_types';
|
||||
import { parseKeysExact, parseKeysRegex } from '../parse_keys';
|
||||
import { searchBackwardBracket, searchForwardBracket } from '../search_utils';
|
||||
import { removeTypeSubscription } from '../type_subscription';
|
||||
import { delete_ } from './operators';
|
||||
|
||||
@ -55,8 +56,20 @@ export const matchActions: Action[] = [
|
||||
const [startCharNew, endCharNew] = getMatchPairs(replacement);
|
||||
const num = helixState.resolveCount();
|
||||
|
||||
const forwardPosition = searchFowardForChar(endCharOrig, editor.selection.active, num);
|
||||
const backwardPosition = searchBackwardForChar(startCharOrig, editor.selection.active, num);
|
||||
const forwardPosition = searchForwardBracket(
|
||||
editor.document,
|
||||
startCharOrig,
|
||||
endCharOrig,
|
||||
editor.selection.active,
|
||||
num,
|
||||
);
|
||||
const backwardPosition = searchBackwardBracket(
|
||||
editor.document,
|
||||
startCharOrig,
|
||||
endCharOrig,
|
||||
editor.selection.active,
|
||||
num,
|
||||
);
|
||||
|
||||
if (forwardPosition === undefined || backwardPosition === undefined) return;
|
||||
|
||||
@ -80,8 +93,8 @@ export const matchActions: Action[] = [
|
||||
const [startChar, endChar] = getMatchPairs(char);
|
||||
const num = helixState.resolveCount();
|
||||
|
||||
const forwardPosition = searchFowardForChar(endChar, editor.selection.active, num);
|
||||
const backwardPosition = searchBackwardForChar(startChar, editor.selection.active, num);
|
||||
const forwardPosition = searchForwardBracket(editor.document, startChar, endChar, editor.selection.active, num);
|
||||
const backwardPosition = searchBackwardBracket(editor.document, startChar, endChar, editor.selection.active, num);
|
||||
|
||||
if (forwardPosition === undefined || backwardPosition === undefined) return;
|
||||
|
||||
@ -98,58 +111,6 @@ export const matchActions: Action[] = [
|
||||
}),
|
||||
];
|
||||
|
||||
const searchFowardForChar = (char: string, fromPosition: vscode.Position, num: number): vscode.Position | undefined => {
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (!editor) return;
|
||||
const document = editor.document;
|
||||
// num starts at 1 so we should drop down to 0, as 1 is the default
|
||||
// even if count wasn't specified
|
||||
let count = --num;
|
||||
|
||||
for (let i = fromPosition.line; i < document.lineCount; ++i) {
|
||||
const lineText = document.lineAt(i).text;
|
||||
const fromIndex = i === fromPosition.line ? fromPosition.character : 0;
|
||||
|
||||
for (let j = fromIndex; j < lineText.length; ++j) {
|
||||
if (lineText[j] === char && count === 0) {
|
||||
return new vscode.Position(i, j);
|
||||
} else if (lineText[j] === char) {
|
||||
--count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
const searchBackwardForChar = (
|
||||
char: string,
|
||||
fromPosition: vscode.Position,
|
||||
num: number,
|
||||
): vscode.Position | undefined => {
|
||||
const editor = vscode.window.activeTextEditor;
|
||||
if (!editor) return;
|
||||
const document = editor.document;
|
||||
// num starts at 1 so we should drop down to 0, as 1 is the default
|
||||
// even if count wasn't specified
|
||||
let count = --num;
|
||||
|
||||
for (let i = fromPosition.line; i >= 0; --i) {
|
||||
const lineText = document.lineAt(i).text;
|
||||
const fromIndex = i === fromPosition.line ? fromPosition.character : lineText.length - 1;
|
||||
|
||||
for (let j = fromIndex; j >= 0; --j) {
|
||||
if (lineText[j] === char && count === 0) {
|
||||
return new vscode.Position(i, j);
|
||||
} else if (lineText[j] === char) {
|
||||
--count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
const getMatchPairs = (char: string) => {
|
||||
let startChar: string;
|
||||
let endChar: string;
|
||||
|
@ -304,8 +304,9 @@ function createInnerBracketHandler(
|
||||
openingChar: string,
|
||||
closingChar: string,
|
||||
): (vimState: HelixState, document: vscode.TextDocument, position: vscode.Position) => vscode.Range | undefined {
|
||||
return (vimState, document, position) => {
|
||||
const bracketRange = getBracketRange(document, position, openingChar, closingChar);
|
||||
return (helixState, document, position) => {
|
||||
const count = helixState.resolveCount();
|
||||
const bracketRange = getBracketRange(document, position, openingChar, closingChar, count);
|
||||
|
||||
if (bracketRange) {
|
||||
return new vscode.Range(
|
||||
@ -324,8 +325,9 @@ function createOuterBracketHandler(
|
||||
openingChar: string,
|
||||
closingChar: string,
|
||||
): (vimState: HelixState, document: vscode.TextDocument, position: vscode.Position) => vscode.Range | undefined {
|
||||
return (vimState, document, position) => {
|
||||
const bracketRange = getBracketRange(document, position, openingChar, closingChar);
|
||||
return (helixState, document, position) => {
|
||||
const count = helixState.resolveCount();
|
||||
const bracketRange = getBracketRange(document, position, openingChar, closingChar, count);
|
||||
|
||||
if (bracketRange) {
|
||||
return new vscode.Range(bracketRange.start, bracketRange.end.with({ character: bracketRange.end.character + 1 }));
|
||||
@ -340,6 +342,7 @@ function getBracketRange(
|
||||
position: vscode.Position,
|
||||
openingChar: string,
|
||||
closingChar: string,
|
||||
offset?: number,
|
||||
): vscode.Range | undefined {
|
||||
const lineText = document.lineAt(position.line).text;
|
||||
const currentChar = lineText[position.character];
|
||||
@ -348,13 +351,19 @@ function getBracketRange(
|
||||
let end;
|
||||
if (currentChar === openingChar) {
|
||||
start = position;
|
||||
end = searchForwardBracket(document, openingChar, closingChar, positionUtils.rightWrap(document, position));
|
||||
end = searchForwardBracket(document, openingChar, closingChar, positionUtils.rightWrap(document, position), offset);
|
||||
} else if (currentChar === closingChar) {
|
||||
start = searchBackwardBracket(document, openingChar, closingChar, positionUtils.leftWrap(document, position));
|
||||
start = searchBackwardBracket(
|
||||
document,
|
||||
openingChar,
|
||||
closingChar,
|
||||
positionUtils.leftWrap(document, position),
|
||||
offset,
|
||||
);
|
||||
end = position;
|
||||
} else {
|
||||
start = searchBackwardBracket(document, openingChar, closingChar, position);
|
||||
end = searchForwardBracket(document, openingChar, closingChar, position);
|
||||
start = searchBackwardBracket(document, openingChar, closingChar, position, offset);
|
||||
end = searchForwardBracket(document, openingChar, closingChar, position, offset);
|
||||
}
|
||||
|
||||
if (start && end) {
|
||||
@ -507,17 +516,18 @@ function createOuterWordHandler(
|
||||
* This should ensure that we're fetching the nearest bracket pair.
|
||||
**/
|
||||
function createInnerMatchHandler(): (
|
||||
vimState: HelixState,
|
||||
helixState: HelixState,
|
||||
document: vscode.TextDocument,
|
||||
position: vscode.Position,
|
||||
) => vscode.Range | undefined {
|
||||
return (_, document, position) => {
|
||||
return (helixState, document, position) => {
|
||||
const count = helixState.resolveCount();
|
||||
// Get all ranges from our position then reduce down to the shortest one
|
||||
const bracketRange = [
|
||||
getBracketRange(document, position, '(', ')'),
|
||||
getBracketRange(document, position, '{', '}'),
|
||||
getBracketRange(document, position, '<', '>'),
|
||||
getBracketRange(document, position, '[', ']'),
|
||||
getBracketRange(document, position, '(', ')', count),
|
||||
getBracketRange(document, position, '{', '}', count),
|
||||
getBracketRange(document, position, '<', '>', count),
|
||||
getBracketRange(document, position, '[', ']', count),
|
||||
].reduce((acc, range) => {
|
||||
if (range) {
|
||||
if (!acc) {
|
||||
|
@ -55,15 +55,18 @@ export function searchForwardBracket(
|
||||
openingChar: string,
|
||||
closingChar: string,
|
||||
fromPosition: vscode.Position,
|
||||
offset?: number,
|
||||
): vscode.Position | undefined {
|
||||
let n = 0;
|
||||
let n = offset ? offset - 1 : 0;
|
||||
|
||||
for (let i = fromPosition.line; i < document.lineCount; ++i) {
|
||||
const lineText = document.lineAt(i).text;
|
||||
const fromIndex = i === fromPosition.line ? fromPosition.character : 0;
|
||||
|
||||
for (let j = fromIndex; j < lineText.length; ++j) {
|
||||
if (lineText[j] === openingChar) {
|
||||
// If closing and opening are the same, don't bother deducting n
|
||||
// However if they are different, we need to deduct n when we see an opening char
|
||||
if (lineText[j] === openingChar && openingChar !== closingChar) {
|
||||
++n;
|
||||
} else if (lineText[j] === closingChar) {
|
||||
if (n === 0) {
|
||||
@ -83,15 +86,18 @@ export function searchBackwardBracket(
|
||||
openingChar: string,
|
||||
closingChar: string,
|
||||
fromPosition: vscode.Position,
|
||||
offset?: number,
|
||||
): vscode.Position | undefined {
|
||||
let n = 0;
|
||||
let n = offset ? offset - 1 : 0;
|
||||
|
||||
for (let i = fromPosition.line; i >= 0; --i) {
|
||||
const lineText = document.lineAt(i).text;
|
||||
const fromIndex = i === fromPosition.line ? fromPosition.character : lineText.length - 1;
|
||||
|
||||
for (let j = fromIndex; j >= 0; --j) {
|
||||
if (lineText[j] === closingChar) {
|
||||
// If closing and opening are the same, don't bother deducting n
|
||||
// However if they are different, we need to deduct n when we see an opening char
|
||||
if (lineText[j] === closingChar && closingChar !== openingChar) {
|
||||
++n;
|
||||
} else if (lineText[j] === openingChar) {
|
||||
if (n === 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user