mirror of
https://github.com/jasonwilliams/vscode-helix.git
synced 2024-09-11 16:56:32 +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 { enterInsertMode, setModeCursorStyle } from '../modes';
|
||||||
import { Mode } from '../modes_types';
|
import { Mode } from '../modes_types';
|
||||||
import { parseKeysExact, parseKeysRegex } from '../parse_keys';
|
import { parseKeysExact, parseKeysRegex } from '../parse_keys';
|
||||||
|
import { searchBackwardBracket, searchForwardBracket } from '../search_utils';
|
||||||
import { removeTypeSubscription } from '../type_subscription';
|
import { removeTypeSubscription } from '../type_subscription';
|
||||||
import { delete_ } from './operators';
|
import { delete_ } from './operators';
|
||||||
|
|
||||||
@ -55,8 +56,20 @@ export const matchActions: Action[] = [
|
|||||||
const [startCharNew, endCharNew] = getMatchPairs(replacement);
|
const [startCharNew, endCharNew] = getMatchPairs(replacement);
|
||||||
const num = helixState.resolveCount();
|
const num = helixState.resolveCount();
|
||||||
|
|
||||||
const forwardPosition = searchFowardForChar(endCharOrig, editor.selection.active, num);
|
const forwardPosition = searchForwardBracket(
|
||||||
const backwardPosition = searchBackwardForChar(startCharOrig, editor.selection.active, num);
|
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;
|
if (forwardPosition === undefined || backwardPosition === undefined) return;
|
||||||
|
|
||||||
@ -80,8 +93,8 @@ export const matchActions: Action[] = [
|
|||||||
const [startChar, endChar] = getMatchPairs(char);
|
const [startChar, endChar] = getMatchPairs(char);
|
||||||
const num = helixState.resolveCount();
|
const num = helixState.resolveCount();
|
||||||
|
|
||||||
const forwardPosition = searchFowardForChar(endChar, editor.selection.active, num);
|
const forwardPosition = searchForwardBracket(editor.document, startChar, endChar, editor.selection.active, num);
|
||||||
const backwardPosition = searchBackwardForChar(startChar, editor.selection.active, num);
|
const backwardPosition = searchBackwardBracket(editor.document, startChar, endChar, editor.selection.active, num);
|
||||||
|
|
||||||
if (forwardPosition === undefined || backwardPosition === undefined) return;
|
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) => {
|
const getMatchPairs = (char: string) => {
|
||||||
let startChar: string;
|
let startChar: string;
|
||||||
let endChar: string;
|
let endChar: string;
|
||||||
|
@ -304,8 +304,9 @@ function createInnerBracketHandler(
|
|||||||
openingChar: string,
|
openingChar: string,
|
||||||
closingChar: string,
|
closingChar: string,
|
||||||
): (vimState: HelixState, document: vscode.TextDocument, position: vscode.Position) => vscode.Range | undefined {
|
): (vimState: HelixState, document: vscode.TextDocument, position: vscode.Position) => vscode.Range | undefined {
|
||||||
return (vimState, document, position) => {
|
return (helixState, document, position) => {
|
||||||
const bracketRange = getBracketRange(document, position, openingChar, closingChar);
|
const count = helixState.resolveCount();
|
||||||
|
const bracketRange = getBracketRange(document, position, openingChar, closingChar, count);
|
||||||
|
|
||||||
if (bracketRange) {
|
if (bracketRange) {
|
||||||
return new vscode.Range(
|
return new vscode.Range(
|
||||||
@ -324,8 +325,9 @@ function createOuterBracketHandler(
|
|||||||
openingChar: string,
|
openingChar: string,
|
||||||
closingChar: string,
|
closingChar: string,
|
||||||
): (vimState: HelixState, document: vscode.TextDocument, position: vscode.Position) => vscode.Range | undefined {
|
): (vimState: HelixState, document: vscode.TextDocument, position: vscode.Position) => vscode.Range | undefined {
|
||||||
return (vimState, document, position) => {
|
return (helixState, document, position) => {
|
||||||
const bracketRange = getBracketRange(document, position, openingChar, closingChar);
|
const count = helixState.resolveCount();
|
||||||
|
const bracketRange = getBracketRange(document, position, openingChar, closingChar, count);
|
||||||
|
|
||||||
if (bracketRange) {
|
if (bracketRange) {
|
||||||
return new vscode.Range(bracketRange.start, bracketRange.end.with({ character: bracketRange.end.character + 1 }));
|
return new vscode.Range(bracketRange.start, bracketRange.end.with({ character: bracketRange.end.character + 1 }));
|
||||||
@ -340,6 +342,7 @@ function getBracketRange(
|
|||||||
position: vscode.Position,
|
position: vscode.Position,
|
||||||
openingChar: string,
|
openingChar: string,
|
||||||
closingChar: string,
|
closingChar: string,
|
||||||
|
offset?: number,
|
||||||
): vscode.Range | undefined {
|
): vscode.Range | undefined {
|
||||||
const lineText = document.lineAt(position.line).text;
|
const lineText = document.lineAt(position.line).text;
|
||||||
const currentChar = lineText[position.character];
|
const currentChar = lineText[position.character];
|
||||||
@ -348,13 +351,19 @@ function getBracketRange(
|
|||||||
let end;
|
let end;
|
||||||
if (currentChar === openingChar) {
|
if (currentChar === openingChar) {
|
||||||
start = position;
|
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) {
|
} 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;
|
end = position;
|
||||||
} else {
|
} else {
|
||||||
start = searchBackwardBracket(document, openingChar, closingChar, position);
|
start = searchBackwardBracket(document, openingChar, closingChar, position, offset);
|
||||||
end = searchForwardBracket(document, openingChar, closingChar, position);
|
end = searchForwardBracket(document, openingChar, closingChar, position, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start && end) {
|
if (start && end) {
|
||||||
@ -507,17 +516,18 @@ function createOuterWordHandler(
|
|||||||
* This should ensure that we're fetching the nearest bracket pair.
|
* This should ensure that we're fetching the nearest bracket pair.
|
||||||
**/
|
**/
|
||||||
function createInnerMatchHandler(): (
|
function createInnerMatchHandler(): (
|
||||||
vimState: HelixState,
|
helixState: HelixState,
|
||||||
document: vscode.TextDocument,
|
document: vscode.TextDocument,
|
||||||
position: vscode.Position,
|
position: vscode.Position,
|
||||||
) => vscode.Range | undefined {
|
) => 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
|
// Get all ranges from our position then reduce down to the shortest one
|
||||||
const bracketRange = [
|
const bracketRange = [
|
||||||
getBracketRange(document, position, '(', ')'),
|
getBracketRange(document, position, '(', ')', count),
|
||||||
getBracketRange(document, position, '{', '}'),
|
getBracketRange(document, position, '{', '}', count),
|
||||||
getBracketRange(document, position, '<', '>'),
|
getBracketRange(document, position, '<', '>', count),
|
||||||
getBracketRange(document, position, '[', ']'),
|
getBracketRange(document, position, '[', ']', count),
|
||||||
].reduce((acc, range) => {
|
].reduce((acc, range) => {
|
||||||
if (range) {
|
if (range) {
|
||||||
if (!acc) {
|
if (!acc) {
|
||||||
|
@ -55,15 +55,18 @@ export function searchForwardBracket(
|
|||||||
openingChar: string,
|
openingChar: string,
|
||||||
closingChar: string,
|
closingChar: string,
|
||||||
fromPosition: vscode.Position,
|
fromPosition: vscode.Position,
|
||||||
|
offset?: number,
|
||||||
): vscode.Position | undefined {
|
): vscode.Position | undefined {
|
||||||
let n = 0;
|
let n = offset ? offset - 1 : 0;
|
||||||
|
|
||||||
for (let i = fromPosition.line; i < document.lineCount; ++i) {
|
for (let i = fromPosition.line; i < document.lineCount; ++i) {
|
||||||
const lineText = document.lineAt(i).text;
|
const lineText = document.lineAt(i).text;
|
||||||
const fromIndex = i === fromPosition.line ? fromPosition.character : 0;
|
const fromIndex = i === fromPosition.line ? fromPosition.character : 0;
|
||||||
|
|
||||||
for (let j = fromIndex; j < lineText.length; ++j) {
|
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;
|
++n;
|
||||||
} else if (lineText[j] === closingChar) {
|
} else if (lineText[j] === closingChar) {
|
||||||
if (n === 0) {
|
if (n === 0) {
|
||||||
@ -83,15 +86,18 @@ export function searchBackwardBracket(
|
|||||||
openingChar: string,
|
openingChar: string,
|
||||||
closingChar: string,
|
closingChar: string,
|
||||||
fromPosition: vscode.Position,
|
fromPosition: vscode.Position,
|
||||||
|
offset?: number,
|
||||||
): vscode.Position | undefined {
|
): vscode.Position | undefined {
|
||||||
let n = 0;
|
let n = offset ? offset - 1 : 0;
|
||||||
|
|
||||||
for (let i = fromPosition.line; i >= 0; --i) {
|
for (let i = fromPosition.line; i >= 0; --i) {
|
||||||
const lineText = document.lineAt(i).text;
|
const lineText = document.lineAt(i).text;
|
||||||
const fromIndex = i === fromPosition.line ? fromPosition.character : lineText.length - 1;
|
const fromIndex = i === fromPosition.line ? fromPosition.character : lineText.length - 1;
|
||||||
|
|
||||||
for (let j = fromIndex; j >= 0; --j) {
|
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;
|
++n;
|
||||||
} else if (lineText[j] === openingChar) {
|
} else if (lineText[j] === openingChar) {
|
||||||
if (n === 0) {
|
if (n === 0) {
|
||||||
|
Loading…
Reference in New Issue
Block a user