From 30356f90c3c3a26b826965f2a408ed960f747958 Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Fri, 31 Jan 2020 16:35:02 +0100 Subject: [PATCH 1/5] Copy to and paste from system clipboard --- package.json | 5 +++++ src/Actions/Register.ts | 45 ++++++++++++++++++++++++++++++++--------- src/Configuration.ts | 6 ++++++ 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 5e1b9d4b..46fcc636 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,11 @@ "default": true, "description": "Set to `false` to keep VSCode's keybinding when searching." }, + "amVim.useSystemClipboard": { + "type": "boolean", + "default": false, + "description": "Set to `true` to copy to and paste from the system clipboard." + }, "amVim.vimStyleNavigationInListView": { "type": "boolean", "default": true, diff --git a/src/Actions/Register.ts b/src/Actions/Register.ts index 09af5c77..d2d1d5c5 100644 --- a/src/Actions/Register.ts +++ b/src/Actions/Register.ts @@ -1,4 +1,4 @@ -import { window, Position, Range } from 'vscode'; +import { env, window, Position, Range } from 'vscode'; import { StaticReflect } from '../LanguageExtensions/StaticReflect'; import { SymbolMetadata } from '../Symbols/Metadata'; import { ActionMoveCursor } from './MoveCursor'; @@ -10,6 +10,7 @@ import { MotionLine } from '../Motions/Line'; import { TextObject } from '../TextObjects/TextObject'; import { UtilRange } from '../Utils/Range'; import { UtilText } from '../Utils/Text'; +import { Configuration } from '../Configuration'; export class Register { readonly text: string; @@ -57,6 +58,12 @@ export class ActionRegister { }) .join(''); + if (Configuration.useSystemClipboard === true) { + // Write to clipboard but then continue to allow + // for saving `isLinewise` state + env.clipboard.writeText(text); + } + ActionRegister.stash = new Register({ text: text, isLinewise: args.isLinewise, @@ -122,6 +129,12 @@ export class ActionRegister { }) .join(''); + if (Configuration.useSystemClipboard === true) { + // Write to clipboard but then continue to allow + // for saving `isLinewise` state + env.clipboard.writeText(text); + } + ActionRegister.stash = new Register({ text: text, isLinewise: args.textObject.isLinewise, @@ -170,16 +183,23 @@ export class ActionRegister { } @StaticReflect.metadata(SymbolMetadata.Action.isChange, true) - static putAfter(args: { n?: number }): Thenable { + static async putAfter(args: { n?: number }): Promise { args.n = args.n === undefined ? 1 : args.n; - if (!ActionRegister.stash) { + const activeTextEditor = window.activeTextEditor; + + if (!activeTextEditor) { return Promise.resolve(false); } - const activeTextEditor = window.activeTextEditor; + if (Configuration.useSystemClipboard === true) { + ActionRegister.stash = new Register({ + text: await env.clipboard.readText(), + isLinewise: false, + }); + } - if (!activeTextEditor) { + if (!ActionRegister.stash) { return Promise.resolve(false); } @@ -220,16 +240,23 @@ export class ActionRegister { } @StaticReflect.metadata(SymbolMetadata.Action.isChange, true) - static putBefore(args: { n?: number }): Thenable { + static async putBefore(args: { n?: number }): Promise { args.n = args.n === undefined ? 1 : args.n; - if (!ActionRegister.stash) { + const activeTextEditor = window.activeTextEditor; + + if (!activeTextEditor) { return Promise.resolve(false); } - const activeTextEditor = window.activeTextEditor; + if (Configuration.useSystemClipboard === true) { + ActionRegister.stash = new Register({ + text: await env.clipboard.readText(), + isLinewise: false, + }); + } - if (!activeTextEditor) { + if (!ActionRegister.stash) { return Promise.resolve(false); } diff --git a/src/Configuration.ts b/src/Configuration.ts index d39bbb1b..6bbd1a71 100644 --- a/src/Configuration.ts +++ b/src/Configuration.ts @@ -18,6 +18,11 @@ export class Configuration { return this._smartRelativeLineNumbers; } + private static _useSystemClipboard: boolean; + static get useSystemClipboard(): boolean { + return this._useSystemClipboard; + } + static init(): void { if (this.isReady) { return; @@ -43,6 +48,7 @@ export class Configuration { 'smartRelativeLineNumbers', false, ); + this._useSystemClipboard = this.getExtensionSetting('useSystemClipboard', false); UtilWord.updateCharacterKindCache( this.getEditorSetting('wordSeparators', '`~!@#$%^&*()-=+[{]}\\|;:\'",.<>/?'), From e0d0ebfef7e02624625fa35f1d4e3709d195d26f Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Fri, 31 Jan 2020 16:55:30 +0100 Subject: [PATCH 2/5] Don't use async method --- src/Actions/Register.ts | 184 +++++++++++++++++++++------------------- 1 file changed, 98 insertions(+), 86 deletions(-) diff --git a/src/Actions/Register.ts b/src/Actions/Register.ts index d2d1d5c5..cab91fd8 100644 --- a/src/Actions/Register.ts +++ b/src/Actions/Register.ts @@ -183,7 +183,7 @@ export class ActionRegister { } @StaticReflect.metadata(SymbolMetadata.Action.isChange, true) - static async putAfter(args: { n?: number }): Promise { + static putAfter(args: { n?: number }): Thenable { args.n = args.n === undefined ? 1 : args.n; const activeTextEditor = window.activeTextEditor; @@ -191,56 +191,62 @@ export class ActionRegister { if (!activeTextEditor) { return Promise.resolve(false); } + const systemClipboardPromise = + Configuration.useSystemClipboard === true + ? env.clipboard.readText() + : Promise.resolve(undefined); + + return systemClipboardPromise.then((result) => { + if (Configuration.useSystemClipboard === true && result) { + ActionRegister.stash = new Register({ + text: result, + isLinewise: false, + }); + } - if (Configuration.useSystemClipboard === true) { - ActionRegister.stash = new Register({ - text: await env.clipboard.readText(), - isLinewise: false, - }); - } - - if (!ActionRegister.stash) { - return Promise.resolve(false); - } + if (!ActionRegister.stash) { + return Promise.resolve(false); + } - const stash = ActionRegister.stash; + const stash = ActionRegister.stash; - const putPositions = activeTextEditor.selections.map((selection) => { - return stash.isLinewise - ? new Position(selection.active.line + 1, 0) - : selection.active.translate(0, +1); - }); + const putPositions = activeTextEditor.selections.map((selection) => { + return stash.isLinewise + ? new Position(selection.active.line + 1, 0) + : selection.active.translate(0, +1); + }); - const textToPut = stash.text.repeat(args.n); + const textToPut = stash.text.repeat(args.n); - return ActionSelection.shrinkToActives() - .then(() => { - return activeTextEditor.edit((editBuilder) => { - putPositions.forEach((position) => { - editBuilder.insert(position, textToPut); + return ActionSelection.shrinkToActives() + .then(() => { + return activeTextEditor.edit((editBuilder) => { + putPositions.forEach((position) => { + editBuilder.insert(position, textToPut); + }); }); + }) + .then(() => { + if (stash.isLinewise) { + return ActionMoveCursor.byMotions({ + motions: [MotionCharacter.down(), MotionLine.firstNonBlank()], + }); + } else if (stash.lineCount > 1) { + return ActionMoveCursor.byMotions({ + motions: [MotionCharacter.right()], + }); + } else { + const characters = textToPut.length; + return ActionMoveCursor.byMotions({ + motions: [MotionCharacter.right({ n: characters })], + }); + } }); - }) - .then(() => { - if (stash.isLinewise) { - return ActionMoveCursor.byMotions({ - motions: [MotionCharacter.down(), MotionLine.firstNonBlank()], - }); - } else if (stash.lineCount > 1) { - return ActionMoveCursor.byMotions({ - motions: [MotionCharacter.right()], - }); - } else { - const characters = textToPut.length; - return ActionMoveCursor.byMotions({ - motions: [MotionCharacter.right({ n: characters })], - }); - } - }); + }); } @StaticReflect.metadata(SymbolMetadata.Action.isChange, true) - static async putBefore(args: { n?: number }): Promise { + static putBefore(args: { n?: number }): Thenable { args.n = args.n === undefined ? 1 : args.n; const activeTextEditor = window.activeTextEditor; @@ -248,57 +254,63 @@ export class ActionRegister { if (!activeTextEditor) { return Promise.resolve(false); } + const systemClipboardPromise = + Configuration.useSystemClipboard === true + ? env.clipboard.readText() + : Promise.resolve(undefined); + + return systemClipboardPromise.then((result) => { + if (Configuration.useSystemClipboard === true && result) { + ActionRegister.stash = new Register({ + text: result, + isLinewise: false, + }); + } - if (Configuration.useSystemClipboard === true) { - ActionRegister.stash = new Register({ - text: await env.clipboard.readText(), - isLinewise: false, - }); - } - - if (!ActionRegister.stash) { - return Promise.resolve(false); - } + if (!ActionRegister.stash) { + return Promise.resolve(false); + } - const stash = ActionRegister.stash; + const stash = ActionRegister.stash; - const putPositions = activeTextEditor.selections.map((selection) => { - return stash.isLinewise ? selection.active.with(undefined, 0) : selection.active; - }); + const putPositions = activeTextEditor.selections.map((selection) => { + return stash.isLinewise ? selection.active.with(undefined, 0) : selection.active; + }); - const textToPut = stash.text.repeat(args.n); + const textToPut = stash.text.repeat(args.n); - return ActionSelection.shrinkToActives() - .then(() => { - return activeTextEditor.edit((editBuilder) => { - putPositions.forEach((position) => { - editBuilder.insert(position, textToPut); + return ActionSelection.shrinkToActives() + .then(() => { + return activeTextEditor.edit((editBuilder) => { + putPositions.forEach((position) => { + editBuilder.insert(position, textToPut); + }); }); + }) + .then(() => { + if (stash.isLinewise) { + return ActionMoveCursor.byMotions({ + motions: [ + MotionCharacter.up({ + n: UtilText.getLineCount(textToPut) - 1, + }), + MotionLine.firstNonBlank(), + ], + }); + } else if (stash.lineCount > 1) { + return ActionMoveCursor.byMotions({ + motions: [ + MotionDirection.prev({ + n: textToPut.length - args.n!, + }), + ], + }); + } else { + return ActionMoveCursor.byMotions({ + motions: [MotionCharacter.left()], + }); + } }); - }) - .then(() => { - if (stash.isLinewise) { - return ActionMoveCursor.byMotions({ - motions: [ - MotionCharacter.up({ - n: UtilText.getLineCount(textToPut) - 1, - }), - MotionLine.firstNonBlank(), - ], - }); - } else if (stash.lineCount > 1) { - return ActionMoveCursor.byMotions({ - motions: [ - MotionDirection.prev({ - n: textToPut.length - args.n!, - }), - ], - }); - } else { - return ActionMoveCursor.byMotions({ - motions: [MotionCharacter.left()], - }); - } - }); + }); } } From e7c4dc84c82a8958c66520c71abc90bf17b7303d Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Fri, 31 Jan 2020 17:01:19 +0100 Subject: [PATCH 3/5] Optimize adding new register --- src/Actions/Register.ts | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/src/Actions/Register.ts b/src/Actions/Register.ts index cab91fd8..32f613c4 100644 --- a/src/Actions/Register.ts +++ b/src/Actions/Register.ts @@ -197,11 +197,18 @@ export class ActionRegister { : Promise.resolve(undefined); return systemClipboardPromise.then((result) => { - if (Configuration.useSystemClipboard === true && result) { - ActionRegister.stash = new Register({ - text: result, - isLinewise: false, - }); + if (Configuration.useSystemClipboard === true) { + const existingStash = ActionRegister.stash || {}; + + // Don't add a new register if: + // - there is nothing returned from the system clipboard promise + // - the existing register has the text already + if (result && existingStash.text !== result) { + ActionRegister.stash = new Register({ + text: result, + isLinewise: false, + }); + } } if (!ActionRegister.stash) { @@ -260,11 +267,18 @@ export class ActionRegister { : Promise.resolve(undefined); return systemClipboardPromise.then((result) => { - if (Configuration.useSystemClipboard === true && result) { - ActionRegister.stash = new Register({ - text: result, - isLinewise: false, - }); + if (Configuration.useSystemClipboard === true) { + const existingStash = ActionRegister.stash || {}; + + // Don't add a new register if: + // - there is nothing returned from the system clipboard promise + // - the existing register has the text already + if (result && existingStash.text !== result) { + ActionRegister.stash = new Register({ + text: result, + isLinewise: false, + }); + } } if (!ActionRegister.stash) { From 4dd608af364bd690be7d72083190e5ba004cecb4 Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Wed, 27 May 2020 16:55:42 +0200 Subject: [PATCH 4/5] Switch promises to async/await --- src/Actions/Action.ts | 2 +- src/Actions/Register.ts | 222 +++++++++++++++++++--------------------- 2 files changed, 107 insertions(+), 117 deletions(-) diff --git a/src/Actions/Action.ts b/src/Actions/Action.ts index bc489904..15310623 100644 --- a/src/Actions/Action.ts +++ b/src/Actions/Action.ts @@ -1,3 +1,3 @@ export interface Action { - (args?: {}): Thenable; + (args?: {}): Thenable | Promise; } diff --git a/src/Actions/Register.ts b/src/Actions/Register.ts index 32f613c4..bc88f921 100644 --- a/src/Actions/Register.ts +++ b/src/Actions/Register.ts @@ -37,7 +37,7 @@ export class ActionRegister { return ActionRegister.stash; } - static yankRanges(args: { ranges: Range[]; isLinewise: boolean }): Thenable { + static async yankRanges(args: { ranges: Range[]; isLinewise: boolean }): Promise { const activeTextEditor = window.activeTextEditor; if (!activeTextEditor) { @@ -61,7 +61,7 @@ export class ActionRegister { if (Configuration.useSystemClipboard === true) { // Write to clipboard but then continue to allow // for saving `isLinewise` state - env.clipboard.writeText(text); + await env.clipboard.writeText(text); } ActionRegister.stash = new Register({ @@ -101,7 +101,7 @@ export class ActionRegister { }); } - static yankByTextObject(args: { textObject: TextObject }): Thenable { + static async yankByTextObject(args: { textObject: TextObject }): Promise { const activeTextEditor = window.activeTextEditor; if (!activeTextEditor) { @@ -132,7 +132,7 @@ export class ActionRegister { if (Configuration.useSystemClipboard === true) { // Write to clipboard but then continue to allow // for saving `isLinewise` state - env.clipboard.writeText(text); + await env.clipboard.writeText(text); } ActionRegister.stash = new Register({ @@ -183,148 +183,138 @@ export class ActionRegister { } @StaticReflect.metadata(SymbolMetadata.Action.isChange, true) - static putAfter(args: { n?: number }): Thenable { + static async putAfter(args: { n?: number }): Promise { args.n = args.n === undefined ? 1 : args.n; const activeTextEditor = window.activeTextEditor; if (!activeTextEditor) { - return Promise.resolve(false); + return false; } - const systemClipboardPromise = - Configuration.useSystemClipboard === true - ? env.clipboard.readText() - : Promise.resolve(undefined); - - return systemClipboardPromise.then((result) => { - if (Configuration.useSystemClipboard === true) { - const existingStash = ActionRegister.stash || {}; - - // Don't add a new register if: - // - there is nothing returned from the system clipboard promise - // - the existing register has the text already - if (result && existingStash.text !== result) { - ActionRegister.stash = new Register({ - text: result, - isLinewise: false, - }); - } - } - if (!ActionRegister.stash) { - return Promise.resolve(false); + if (Configuration.useSystemClipboard === true) { + const text = await env.clipboard.readText(); + const existingStash = ActionRegister.stash || {}; + + // Don't add a new register if: + // - there is nothing returned from the system clipboard + // - the existing register has the text already + if (text && existingStash.text !== text) { + ActionRegister.stash = new Register({ + text, + isLinewise: false, + }); } + } - const stash = ActionRegister.stash; + if (!ActionRegister.stash) { + return Promise.resolve(false); + } - const putPositions = activeTextEditor.selections.map((selection) => { - return stash.isLinewise - ? new Position(selection.active.line + 1, 0) - : selection.active.translate(0, +1); - }); + const stash = ActionRegister.stash; - const textToPut = stash.text.repeat(args.n); + const putPositions = activeTextEditor.selections.map((selection) => { + return stash.isLinewise + ? new Position(selection.active.line + 1, 0) + : selection.active.translate(0, +1); + }); + + const textToPut = stash.text.repeat(args.n); - return ActionSelection.shrinkToActives() - .then(() => { - return activeTextEditor.edit((editBuilder) => { - putPositions.forEach((position) => { - editBuilder.insert(position, textToPut); - }); + return ActionSelection.shrinkToActives() + .then(() => { + return activeTextEditor.edit((editBuilder) => { + putPositions.forEach((position) => { + editBuilder.insert(position, textToPut); }); - }) - .then(() => { - if (stash.isLinewise) { - return ActionMoveCursor.byMotions({ - motions: [MotionCharacter.down(), MotionLine.firstNonBlank()], - }); - } else if (stash.lineCount > 1) { - return ActionMoveCursor.byMotions({ - motions: [MotionCharacter.right()], - }); - } else { - const characters = textToPut.length; - return ActionMoveCursor.byMotions({ - motions: [MotionCharacter.right({ n: characters })], - }); - } }); - }); + }) + .then(() => { + if (stash.isLinewise) { + return ActionMoveCursor.byMotions({ + motions: [MotionCharacter.down(), MotionLine.firstNonBlank()], + }); + } else if (stash.lineCount > 1) { + return ActionMoveCursor.byMotions({ + motions: [MotionCharacter.right()], + }); + } else { + const characters = textToPut.length; + return ActionMoveCursor.byMotions({ + motions: [MotionCharacter.right({ n: characters })], + }); + } + }); } @StaticReflect.metadata(SymbolMetadata.Action.isChange, true) - static putBefore(args: { n?: number }): Thenable { + static async putBefore(args: { n?: number }): Promise { args.n = args.n === undefined ? 1 : args.n; const activeTextEditor = window.activeTextEditor; if (!activeTextEditor) { - return Promise.resolve(false); + return false; } - const systemClipboardPromise = - Configuration.useSystemClipboard === true - ? env.clipboard.readText() - : Promise.resolve(undefined); - - return systemClipboardPromise.then((result) => { - if (Configuration.useSystemClipboard === true) { - const existingStash = ActionRegister.stash || {}; - - // Don't add a new register if: - // - there is nothing returned from the system clipboard promise - // - the existing register has the text already - if (result && existingStash.text !== result) { - ActionRegister.stash = new Register({ - text: result, - isLinewise: false, - }); - } - } - if (!ActionRegister.stash) { - return Promise.resolve(false); + if (Configuration.useSystemClipboard === true) { + const text = await env.clipboard.readText(); + const existingStash = ActionRegister.stash || {}; + + // Don't add a new register if: + // - there is nothing returned from the system clipboard + // - the existing register has the text already + if (text && existingStash.text !== text) { + ActionRegister.stash = new Register({ + text, + isLinewise: false, + }); } + } - const stash = ActionRegister.stash; + if (!ActionRegister.stash) { + return Promise.resolve(false); + } - const putPositions = activeTextEditor.selections.map((selection) => { - return stash.isLinewise ? selection.active.with(undefined, 0) : selection.active; - }); + const stash = ActionRegister.stash; - const textToPut = stash.text.repeat(args.n); + const putPositions = activeTextEditor.selections.map((selection) => { + return stash.isLinewise ? selection.active.with(undefined, 0) : selection.active; + }); + + const textToPut = stash.text.repeat(args.n); - return ActionSelection.shrinkToActives() - .then(() => { - return activeTextEditor.edit((editBuilder) => { - putPositions.forEach((position) => { - editBuilder.insert(position, textToPut); - }); + return ActionSelection.shrinkToActives() + .then(() => { + return activeTextEditor.edit((editBuilder) => { + putPositions.forEach((position) => { + editBuilder.insert(position, textToPut); }); - }) - .then(() => { - if (stash.isLinewise) { - return ActionMoveCursor.byMotions({ - motions: [ - MotionCharacter.up({ - n: UtilText.getLineCount(textToPut) - 1, - }), - MotionLine.firstNonBlank(), - ], - }); - } else if (stash.lineCount > 1) { - return ActionMoveCursor.byMotions({ - motions: [ - MotionDirection.prev({ - n: textToPut.length - args.n!, - }), - ], - }); - } else { - return ActionMoveCursor.byMotions({ - motions: [MotionCharacter.left()], - }); - } }); - }); + }) + .then(() => { + if (stash.isLinewise) { + return ActionMoveCursor.byMotions({ + motions: [ + MotionCharacter.up({ + n: UtilText.getLineCount(textToPut) - 1, + }), + MotionLine.firstNonBlank(), + ], + }); + } else if (stash.lineCount > 1) { + return ActionMoveCursor.byMotions({ + motions: [ + MotionDirection.prev({ + n: textToPut.length - args.n!, + }), + ], + }); + } else { + return ActionMoveCursor.byMotions({ + motions: [MotionCharacter.left()], + }); + } + }); } } From 9ef7479217ff454831ce7569a1e122c38e8f7354 Mon Sep 17 00:00:00 2001 From: Karl Horky Date: Wed, 27 May 2020 17:03:36 +0200 Subject: [PATCH 5/5] Restore extra promise wrapping for better diff --- src/Actions/Register.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Actions/Register.ts b/src/Actions/Register.ts index bc88f921..d0725b1b 100644 --- a/src/Actions/Register.ts +++ b/src/Actions/Register.ts @@ -189,7 +189,7 @@ export class ActionRegister { const activeTextEditor = window.activeTextEditor; if (!activeTextEditor) { - return false; + return Promise.resolve(false); } if (Configuration.useSystemClipboard === true) { @@ -254,7 +254,7 @@ export class ActionRegister { const activeTextEditor = window.activeTextEditor; if (!activeTextEditor) { - return false; + return Promise.resolve(false); } if (Configuration.useSystemClipboard === true) {