From b91c5645ce9fb131763e85a779fd94d0764182e8 Mon Sep 17 00:00:00 2001 From: Theo Lemay Date: Sat, 12 Nov 2022 18:24:13 -0500 Subject: [PATCH] Revert "fix(scrolling): fix c-u/c-y/c-f/c-b by deletion (#885)" --- package.json | 53 +++++++++++--- src/commands_controller.ts | 73 ++++++++++++++++++- src/document_change_manager.ts | 23 +++++- src/extension.ts | 2 + src/main_controller.ts | 3 +- .../suite/vscode-integartion-specific.test.ts | 2 +- src/utils.ts | 11 ++- vim/vscode-scrolling.vim | 30 ++++++++ 8 files changed, 177 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index 1119aa712..03596ed3d 100644 --- a/package.json +++ b/package.json @@ -125,6 +125,11 @@ "default": false, "markdownDescription": "Use neovim installed in WSL. If you enable this setting, specify the path to the neovim executable installed in WSL `neovimExecutablePaths.linux` setting" }, + "vscode-neovim.revealCursorScrollLine": { + "type": "boolean", + "default": false, + "markdownDescription": "If 'true' reveals the cursor when scrolling by line and if it is outside view port" + }, "vscode-neovim.logPath": { "type": "string", "default": "", @@ -291,13 +296,41 @@ "command": "vscode-neovim.send-cmdline", "title": "Neovim: Send key in cmdline" }, + { + "command": "vscode-neovim.ctrl-b", + "title": "Neovim: ctrl-b" + }, + { + "command": "vscode-neovim.ctrl-d", + "title": "Neovim: ctrl-d" + }, { "command": "vscode-neovim.ctrl-e", "title": "Neovim: ctrl-e" }, + { + "command": "vscode-neovim.ctrl-f", + "title": "Neovim: ctrl-f" + }, + { + "command": "vscode-neovim.ctrl-u", + "title": "Neovim: ctrl-u" + }, { "command": "vscode-neovim.ctrl-y", "title": "Neovim: ctrl-y" + }, + { + "command": "vscode-neovim.shift-m", + "title": "Neovim: shift-m" + }, + { + "command": "vscode-neovim.shift-l", + "title": "Neovim: shift-l" + }, + { + "command": "vscode-neovim:shift-h", + "title": "Neovim: shift-h" } ], "keybindings": [ @@ -672,16 +705,14 @@ "args": "" }, { - "command": "vscode-neovim.send", + "command": "vscode-neovim.ctrl-b", "key": "ctrl+b", - "when": "editorTextFocus && neovim.init && neovim.mode != insert && neovim.ctrlKeysNormal", - "args": "" + "when": "editorTextFocus && neovim.init && neovim.mode != insert && neovim.ctrlKeysNormal" }, { - "command": "vscode-neovim.send", + "command": "vscode-neovim.ctrl-d", "key": "ctrl+d", - "when": "editorTextFocus && neovim.init && neovim.mode != insert && neovim.ctrlKeysNormal", - "args": "" + "when": "editorTextFocus && neovim.init && neovim.mode != insert && neovim.ctrlKeysNormal" }, { "command": "vscode-neovim.ctrl-e", @@ -689,10 +720,9 @@ "when": "editorTextFocus && neovim.init && neovim.mode != insert && neovim.ctrlKeysNormal" }, { - "command": "vscode-neovim.send", + "command": "vscode-neovim.ctrl-f", "key": "ctrl+f", - "when": "editorTextFocus && neovim.init && neovim.mode != insert && neovim.ctrlKeysNormal", - "args": "" + "when": "editorTextFocus && neovim.init && neovim.mode != insert && neovim.ctrlKeysNormal" }, { "command": "vscode-neovim.send", @@ -713,10 +743,9 @@ "args": "" }, { - "command": "vscode-neovim.send", + "command": "vscode-neovim.ctrl-u", "key": "ctrl+u", - "when": "editorTextFocus && neovim.init && neovim.mode != insert && neovim.ctrlKeysNormal", - "args": "" + "when": "editorTextFocus && neovim.init && neovim.mode != insert && neovim.ctrlKeysNormal" }, { "command": "vscode-neovim.send", diff --git a/src/commands_controller.ts b/src/commands_controller.ts index 8eb42de34..9bf3f5cb7 100644 --- a/src/commands_controller.ts +++ b/src/commands_controller.ts @@ -4,9 +4,27 @@ import { NeovimClient } from "neovim"; import { NeovimExtensionRequestProcessable } from "./neovim_events_processable"; export class CommandsController implements Disposable, NeovimExtensionRequestProcessable { + private client: NeovimClient; + private disposables: Disposable[] = []; - public constructor(private client: NeovimClient) { + private revealCursorScrollLine: boolean; + + public constructor(client: NeovimClient, revealCursorScrollLine: boolean) { + this.client = client; + this.revealCursorScrollLine = revealCursorScrollLine; + this.disposables.push( + vscode.commands.registerCommand("vscode-neovim.ctrl-f", () => this.scrollPage("page", "down")), + ); + this.disposables.push( + vscode.commands.registerCommand("vscode-neovim.ctrl-b", () => this.scrollPage("page", "up")), + ); + this.disposables.push( + vscode.commands.registerCommand("vscode-neovim.ctrl-d", () => this.scrollPage("halfPage", "down")), + ); + this.disposables.push( + vscode.commands.registerCommand("vscode-neovim.ctrl-u", () => this.scrollPage("halfPage", "up")), + ); this.disposables.push(vscode.commands.registerCommand("vscode-neovim.ctrl-e", () => this.scrollLine("down"))); this.disposables.push(vscode.commands.registerCommand("vscode-neovim.ctrl-y", () => this.scrollLine("up"))); } @@ -25,12 +43,63 @@ export class CommandsController implements Disposable, NeovimExtensionRequestPro this.revealLine(at, !!updateCursor); break; } + case "move-cursor": { + const [to] = args as ["top" | "middle" | "bottom"]; + this.goToLine(to); + break; + } + case "scroll": { + const [by, to] = args as ["page" | "halfPage", "up" | "down"]; + this.scrollPage(by, to); + break; + } + case "scroll-line": { + const [to] = args as ["up" | "down"]; + this.scrollLine(to); + break; + } + case "insert-line": { + const [type] = args as ["before" | "after"]; + await this.client.command("startinsert"); + await vscode.commands.executeCommand( + type === "before" ? "editor.action.insertLineBefore" : "editor.action.insertLineAfter", + ); + break; + } } } /// SCROLL COMMANDS /// + private scrollPage = (by: "page" | "halfPage", to: "up" | "down"): void => { + vscode.commands.executeCommand("editorScroll", { to, by, revealCursor: true }); + }; + private scrollLine = (to: "up" | "down"): void => { - vscode.commands.executeCommand("editorScroll", { to, by: "line", revealCursor: true }); + vscode.commands.executeCommand("editorScroll", { to, by: "line", revealCursor: this.revealCursorScrollLine }); + }; + + private goToLine = (to: "top" | "middle" | "bottom"): void => { + const e = vscode.window.activeTextEditor; + if (!e) { + return; + } + const topVisible = e.visibleRanges[0].start.line; + const bottomVisible = e.visibleRanges[0].end.line; + const lineNum = + to === "top" + ? topVisible + : to === "bottom" + ? bottomVisible + : Math.floor(topVisible + (bottomVisible - topVisible) / 2); + const line = e.document.lineAt(lineNum); + e.selections = [ + new vscode.Selection( + lineNum, + line.firstNonWhitespaceCharacterIndex, + lineNum, + line.firstNonWhitespaceCharacterIndex, + ), + ]; }; // zz, zt, zb and others diff --git a/src/document_change_manager.ts b/src/document_change_manager.ts index 3d95ce7d6..795cd94c6 100644 --- a/src/document_change_manager.ts +++ b/src/document_change_manager.ts @@ -78,6 +78,10 @@ export class DocumentChangeManager implements Disposable, NeovimExtensionRequest * Dot repeat workaround */ private dotRepeatChange: DotRepeatChange | undefined; + /** + * A hint for dot-repeat indicating of how the insert mode was started + */ + private dotRepeatStartModeInsertHint?: "o" | "O"; /** * True when we're currently applying edits, so incoming changes will go into pending events queue */ @@ -115,8 +119,12 @@ export class DocumentChangeManager implements Disposable, NeovimExtensionRequest return (this.textDocumentChangePromise.get(doc)?.length || 0) > 0; } - public async handleExtensionRequest(): Promise { - // skip + public async handleExtensionRequest(name: string, args: unknown[]): Promise { + if (name === "insert-line") { + const [type] = args as ["before" | "after"]; + this.dotRepeatStartModeInsertHint = type === "before" ? "O" : "o"; + this.logger.debug(`${LOG_PREFIX}: Setting start insert mode hint - ${this.dotRepeatStartModeInsertHint}`); + } } public async syncDotRepeatWithNeovim(): Promise { @@ -160,6 +168,13 @@ export class DocumentChangeManager implements Disposable, NeovimExtensionRequest ); } let editStr = ""; + if (dotRepeatChange.startMode) { + editStr += `${dotRepeatChange.startMode}`; + // remove EOL from first change + if (dotRepeatChange.text.startsWith(dotRepeatChange.eol)) { + dotRepeatChange.text = dotRepeatChange.text.slice(dotRepeatChange.eol.length); + } + } if (dotRepeatChange.rangeLength) { editStr += [...new Array(dotRepeatChange.rangeLength).keys()].map(() => "").join(""); } @@ -468,17 +483,19 @@ export class DocumentChangeManager implements Disposable, NeovimExtensionRequest } const eol = doc.eol === EndOfLine.LF ? "\n" : "\r\n"; + const startModeHint = this.dotRepeatStartModeInsertHint; const activeEditor = window.activeTextEditor; // Store dot repeat if (activeEditor && activeEditor.document === doc && this.main.modeManager.isInsertMode) { + this.dotRepeatStartModeInsertHint = undefined; const cursor = activeEditor.selection.active; for (const change of contentChanges) { if (isCursorChange(change, cursor, eol)) { if (this.dotRepeatChange && isChangeSubsequentToChange(change, this.dotRepeatChange)) { this.dotRepeatChange = accumulateDotRepeatChange(change, this.dotRepeatChange); } else { - this.dotRepeatChange = normalizeDotRepeatChange(change, eol); + this.dotRepeatChange = normalizeDotRepeatChange(change, eol, startModeHint); } } } diff --git a/src/extension.ts b/src/extension.ts index a4838a51c..26e833e18 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -18,6 +18,7 @@ export async function activate(context: vscode.ExtensionContext): Promise const useCtrlKeysNormalMode = settings.get("useCtrlKeysForNormalMode", true); const useCtrlKeysInsertMode = settings.get("useCtrlKeysForInsertMode", true); const useWsl = isWindows && settings.get("useWSL", false); + const revealCursorScrollLine = settings.get("revealCursorScrollLine", false); const neovimWidth = settings.get("neovimWidth", 1000); const neovimViewportHeightExtend = settings.get("neovimViewportHeightExtend", 1); const customInit = getNeovimInitPath() ?? ""; @@ -45,6 +46,7 @@ export async function activate(context: vscode.ExtensionContext): Promise useWsl: ext.extensionKind === vscode.ExtensionKind.Workspace ? false : useWsl, neovimViewportWidth: neovimWidth, neovimViewportHeightExtend: neovimViewportHeightExtend, + revealCursorScrollLine: revealCursorScrollLine, logConf: { logPath, outputToConsole, diff --git a/src/main_controller.ts b/src/main_controller.ts index c15050787..3711e4108 100644 --- a/src/main_controller.ts +++ b/src/main_controller.ts @@ -42,6 +42,7 @@ export interface ControllerSettings { clean: boolean; neovimViewportWidth: number; neovimViewportHeightExtend: number; + revealCursorScrollLine: boolean; logConf: { level: "none" | "error" | "warn" | "debug"; logPath: string; @@ -171,7 +172,7 @@ export class MainController implements vscode.Disposable { const channel = await this.client.channelId; await this.client.setVar("vscode_channel", channel); - this.commandsController = new CommandsController(this.client); + this.commandsController = new CommandsController(this.client, this.settings.revealCursorScrollLine); this.disposables.push(this.commandsController); this.modeManager = new ModeManager(this.logger); diff --git a/src/test/suite/vscode-integartion-specific.test.ts b/src/test/suite/vscode-integartion-specific.test.ts index a67dc11e3..547b4bddf 100644 --- a/src/test/suite/vscode-integartion-specific.test.ts +++ b/src/test/suite/vscode-integartion-specific.test.ts @@ -100,7 +100,7 @@ describe("VSCode integration specific stuff", () => { ); const editor = await vscode.window.showTextDocument(doc, vscode.ViewColumn.One); await wait(1000); - await sendVSCodeKeys("", 0); + await vscode.commands.executeCommand("vscode-neovim.ctrl-f"); await wait(1500); let visibleRange = editor.visibleRanges[0]; diff --git a/src/utils.ts b/src/utils.ts index 3f2599435..8eaeb04d2 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -43,6 +43,10 @@ export interface DotRepeatChange { * Change text */ text: string; + /** + * Set if it was the first change and started either through o or O + */ + startMode?: "o" | "O"; /** * Text eol */ @@ -347,11 +351,16 @@ export function getNeovimInitPath(): string | undefined { return getSystemSpecificSetting("neovimInitVimPaths", legacySettingInfo); } -export function normalizeDotRepeatChange(change: TextDocumentContentChangeEvent, eol: string): DotRepeatChange { +export function normalizeDotRepeatChange( + change: TextDocumentContentChangeEvent, + eol: string, + startMode?: "o" | "O", +): DotRepeatChange { return { rangeLength: change.rangeLength, rangeOffset: change.rangeOffset, text: change.text, + startMode, eol, }; } diff --git a/vim/vscode-scrolling.vim b/vim/vscode-scrolling.vim index 92834cc1f..d351d3199 100644 --- a/vim/vscode-scrolling.vim +++ b/vim/vscode-scrolling.vim @@ -14,3 +14,33 @@ nnoremap z- call reveal('bottom', 1) xnoremap z- call reveal('bottom', 1) nnoremap zb call reveal('bottom', 0) xnoremap zb call reveal('bottom', 0) + + +function s:moveCursor(to) + " Native VSCode commands don't register jumplist. Fix by registering jumplist in Vim e.g. for subsequent use of + normal! m' + call VSCodeExtensionNotify('move-cursor', a:to) +endfunction + +nnoremap H call moveCursor('top') +xnoremap H call moveCursor('top') +nnoremap M call moveCursor('middle') +xnoremap M call moveCursor('middle') +nnoremap L call moveCursor('bottom') +xnoremap L call moveCursor('bottom') + +" Disabled due to scroll problems (the ext binds them directly) +" nnoremap VSCodeExtensionCall('scroll', 'halfPage', 'down') +" xnoremap VSCodeExtensionCall('scroll', 'halfPage', 'down') +" nnoremap VSCodeExtensionCall('scroll', 'halfPage', 'up') +" xnoremap VSCodeExtensionCall('scroll', 'halfPage', 'up') + +" nnoremap VSCodeExtensionCall('scroll', 'page', 'down') +" xnoremap VSCodeExtensionCall('scroll', 'page', 'down') +" nnoremap VSCodeExtensionCall('scroll', 'page', 'up') +" xnoremap VSCodeExtensionCall('scroll', 'page', 'up') + +" nnoremap VSCodeExtensionNotify('scroll-line', 'down') +" xnoremap VSCodeExtensionNotify('scroll-line', 'down') +" nnoremap VSCodeExtensionNotify('scroll-line', 'up') +" xnoremap VSCodeExtensionNotify('scroll-line', 'up')