This commit is contained in:
jasonwilliams 2024-01-17 22:25:49 +00:00
parent efe599c656
commit 644edf8cc5
5 changed files with 87 additions and 20 deletions

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "vscode-helix-emulation",
"version": "0.4.1",
"version": "0.5.4",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "vscode-helix-emulation",
"version": "0.4.1",
"version": "0.5.4",
"license": "MIT",
"devDependencies": {
"@types/http-errors": "^1.8.0",

View File

@ -1,6 +1,6 @@
{
"name": "vscode-helix-emulation",
"version": "0.5.3",
"version": "0.5.4",
"displayName": "Helix For VS Code",
"description": "Helix emulation for Visual Studio Code",
"publisher": "jasew",

View File

@ -87,6 +87,18 @@ export const actions: Action[] = [
vscode.commands.executeCommand('deleteRight');
}),
parseKeysExact(['>'], [Mode.Normal, Mode.Visual], (_) => {
vscode.commands.executeCommand('editor.action.indentLines');
}),
parseKeysExact(['<'], [Mode.Normal, Mode.Visual], (_) => {
vscode.commands.executeCommand('editor.action.outdentLines');
}),
parseKeysExact(['='], [Mode.Normal, Mode.Visual], (_) => {
vscode.commands.executeCommand('editor.action.formatSelection');
}),
// replace
parseKeysRegex(/^r(.)/, /^r/, [Mode.Normal], (helixState, editor, match) => {
const position = editor.selection.active;

View File

@ -49,6 +49,17 @@ export function escapeHandler(vimState: HelixState): void {
} else if (vimState.mode === Mode.SearchInProgress || vimState.mode === Mode.Select) {
enterNormalMode(vimState);
vimState.searchState.clearSearchString(vimState);
// To match Helix UI go back to the last active position on escape
if (vimState.searchState.lastActivePosition) {
editor.selection = new vscode.Selection(
vimState.searchState.lastActivePosition,
vimState.searchState.lastActivePosition,
);
vimState.editorState.activeEditor?.revealRange(
editor.selection,
vscode.TextEditorRevealType.InCenterIfOutsideViewport,
);
}
} else if (vimState.mode === Mode.View) {
enterNormalMode(vimState);
}

View File

@ -13,6 +13,29 @@ export class SearchState {
searchHistoryIndex: number = this.searchHistory.length - 1; // Add this line
/** Have we just come out of select mode? */
selectModeActive: boolean = false;
/** Last active position before search */
lastActivePosition: vscode.Position | undefined;
// https://github.com/helix-editor/helix/issues/4978
getFlags(): string {
if (this.searchString.startsWith('(?i)')) {
return 'gi';
} else if (this.searchString.startsWith('(?-i)')) {
return 'g';
}
return this.searchString === this.searchString.toLowerCase() ? 'gi' : 'g';
}
getNormalisedSearchString(): string {
if (this.searchString.startsWith('(?i)')) {
return this.searchString.slice(4);
} else if (this.searchString.startsWith('(?-i)')) {
return this.searchString.slice(5);
}
return this.searchString;
}
clearSearchString(helixState: HelixState): void {
this.searchString = '';
@ -25,22 +48,33 @@ export class SearchState {
this.enter(helixState);
return;
}
// If we've just started a search, set a marker where we were so we can go back on escape
if (this.searchString === '') {
this.lastActivePosition = helixState.editorState.activeEditor?.selection.active;
}
this.searchString += char;
helixState.commandLine.setText(this.searchString, helixState);
if (helixState.mode === Mode.Select) {
this.findInstancesInRange(helixState, this.searchString);
this.findInstancesInRange(helixState);
} else {
this.findInstancesInDocument(helixState, this.searchString);
this.findInstancesInDocument(helixState);
}
}
addText(helixState: HelixState, text: string): void {
// If we've just started a search, set a marker where we were so we can go back on escape
if (this.searchString === '') {
this.lastActivePosition = helixState.editorState.activeEditor?.selection.active;
}
this.searchString += text;
helixState.commandLine.setText(this.searchString, helixState);
if (helixState.mode === Mode.Select) {
this.findInstancesInRange(helixState, this.searchString);
this.findInstancesInRange(helixState);
} else {
this.findInstancesInDocument(helixState, this.searchString);
this.findInstancesInDocument(helixState);
}
}
@ -49,9 +83,9 @@ export class SearchState {
this.searchString = this.searchString.slice(0, -1);
helixState.commandLine.setText(this.searchString, helixState);
if (this.searchString && helixState.mode === Mode.Select) {
this.findInstancesInRange(helixState, this.searchString);
this.findInstancesInRange(helixState);
} else if (this.searchString) {
this.findInstancesInDocument(helixState, this.searchString);
this.findInstancesInDocument(helixState);
}
}
@ -83,28 +117,38 @@ export class SearchState {
enterNormalMode(helixState);
}
findInstancesInDocument(helixState: HelixState, searchString: string): void {
findInstancesInDocument(helixState: HelixState): void {
const editor = helixState.editorState.activeEditor;
if (editor) {
const document = editor.document;
const foundRanges: vscode.Range[] = [];
const searchRegex = new RegExp(searchString, 'g');
const flags = this.getFlags();
const searchRegex = new RegExp(this.getNormalisedSearchString(), flags);
const match = searchRegex.exec(document.getText());
let startPos: vscode.Position | undefined;
let endPos: vscode.Position | undefined;
if (match) {
const startPos = document.positionAt(match.index);
const endPos = document.positionAt(match.index + match[0].length);
foundRanges.push(new vscode.Range(startPos, endPos));
startPos = document.positionAt(match.index);
endPos = document.positionAt(match.index + match[0].length);
editor.selection = new vscode.Selection(startPos, endPos);
// We should also move the viewport to our match if there is one
editor.revealRange(new vscode.Range(startPos, endPos));
} else {
// If we can't find a match view the last saved position
if (this.lastActivePosition) {
editor.selection = new vscode.Selection(this.lastActivePosition, this.lastActivePosition);
editor.revealRange(new vscode.Range(this.lastActivePosition, this.lastActivePosition));
}
}
editor.selections = foundRanges.map((range) => new vscode.Selection(range.start, range.end));
}
}
findInstancesInRange(helixState: HelixState, searchString: string): void {
findInstancesInRange(helixState: HelixState): void {
const editor = helixState.editorState.activeEditor;
if (editor) {
const document = editor.document;
const foundRanges: vscode.Range[] = [];
const searchRegex = new RegExp(searchString, 'g');
const flags = this.getFlags();
const searchRegex = new RegExp(this.getNormalisedSearchString(), flags);
let match;
while ((match = searchRegex.exec(document.getText()))) {
const startPos = document.positionAt(match.index);
@ -124,7 +168,7 @@ export class SearchState {
this.searchString = this.searchHistory[this.searchHistoryIndex] || '';
this.searchHistoryIndex = Math.max(this.searchHistoryIndex - 1, 0); // Add this line
helixState.commandLine.setText(this.searchString, helixState);
this.findInstancesInDocument(helixState, this.searchString);
this.findInstancesInDocument(helixState);
}
}
@ -133,7 +177,7 @@ export class SearchState {
this.searchString = this.searchHistory[this.searchHistoryIndex] || '';
this.searchHistoryIndex = Math.min(this.searchHistoryIndex + 1, this.searchHistory.length - 1); // Add this line
helixState.commandLine.setText(this.searchString, helixState);
this.findInstancesInDocument(helixState, this.searchString);
this.findInstancesInDocument(helixState);
}
}
}