diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 9e051fe7a..c10e16129 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -16,17 +16,8 @@ "taskName": "build", "args": [], "isBuildCommand": true, - "isWatching": false, - "problemMatcher": "$tsc-watch" - }, - - { - "taskName": "yolo", - "args": ["nothing"], - "isBuildCommand": true, - "isWatching": false, + "isBackground": false, "problemMatcher": "$tsc-watch" } - ] } \ No newline at end of file diff --git a/LICENSE b/LICENSE index a7f081e84..b087a264f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015 VSCode-Extension +Copyright (c) 2015 VSCodeVim Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/extension.ts b/extension.ts index 39a9b1605..892012e77 100644 --- a/extension.ts +++ b/extension.ts @@ -213,66 +213,54 @@ export async function activate(context: vscode.ExtensionContext) { }); overrideCommand(context, 'type', async args => { - taskQueue.enqueueTask({ - promise: async () => { - const mh = await getAndUpdateModeHandler(); + taskQueue.enqueueTask(async () => { + const mh = await getAndUpdateModeHandler(); - if (compositionState.isInComposition) { - compositionState.composingText += args.text; - } else { - await mh.handleKeyEvent(args.text); - } - }, - isRunning: false, + if (compositionState.isInComposition) { + compositionState.composingText += args.text; + } else { + await mh.handleKeyEvent(args.text); + } }); }); overrideCommand(context, 'replacePreviousChar', async args => { - taskQueue.enqueueTask({ - promise: async () => { - const mh = await getAndUpdateModeHandler(); + taskQueue.enqueueTask(async () => { + const mh = await getAndUpdateModeHandler(); - if (compositionState.isInComposition) { - compositionState.composingText = - compositionState.composingText.substr( - 0, - compositionState.composingText.length - args.replaceCharCnt - ) + args.text; - } else { - await vscode.commands.executeCommand('default:replacePreviousChar', { - text: args.text, - replaceCharCnt: args.replaceCharCnt, - }); - mh.vimState.cursorPosition = Position.FromVSCodePosition( - mh.vimState.editor.selection.start - ); - mh.vimState.cursorStartPosition = Position.FromVSCodePosition( - mh.vimState.editor.selection.start - ); - } - }, - isRunning: false, + if (compositionState.isInComposition) { + compositionState.composingText = + compositionState.composingText.substr( + 0, + compositionState.composingText.length - args.replaceCharCnt + ) + args.text; + } else { + await vscode.commands.executeCommand('default:replacePreviousChar', { + text: args.text, + replaceCharCnt: args.replaceCharCnt, + }); + mh.vimState.cursorPosition = Position.FromVSCodePosition( + mh.vimState.editor.selection.start + ); + mh.vimState.cursorStartPosition = Position.FromVSCodePosition( + mh.vimState.editor.selection.start + ); + } }); }); overrideCommand(context, 'compositionStart', async args => { - taskQueue.enqueueTask({ - promise: async () => { - compositionState.isInComposition = true; - }, - isRunning: false, + taskQueue.enqueueTask(async () => { + compositionState.isInComposition = true; }); }); overrideCommand(context, 'compositionEnd', async args => { - taskQueue.enqueueTask({ - promise: async () => { - const mh = await getAndUpdateModeHandler(); - let text = compositionState.composingText; - compositionState = new CompositionState(); - await mh.handleMultipleKeyEvents(text.split('')); - }, - isRunning: false, + taskQueue.enqueueTask(async () => { + const mh = await getAndUpdateModeHandler(); + let text = compositionState.composingText; + compositionState = new CompositionState(); + await mh.handleMultipleKeyEvents(text.split('')); }); }); @@ -284,29 +272,26 @@ export async function activate(context: vscode.ExtensionContext) { }); registerCommand(context, 'vim.remap', async (args: ICodeKeybinding) => { - taskQueue.enqueueTask({ - promise: async () => { - const mh = await getAndUpdateModeHandler(); - if (args.after) { - for (const key of args.after) { - await mh.handleKeyEvent(AngleBracketNotation.Normalize(key)); - } - return; + taskQueue.enqueueTask(async () => { + const mh = await getAndUpdateModeHandler(); + if (args.after) { + for (const key of args.after) { + await mh.handleKeyEvent(AngleBracketNotation.Normalize(key)); } + return; + } - if (args.commands) { - for (const command of args.commands) { - // Check if this is a vim command by looking for : - if (command.command.slice(0, 1) === ':') { - await runCmdLine(command.command.slice(1, command.command.length), mh); - await mh.updateView(mh.vimState); - } else { - await vscode.commands.executeCommand(command.command, command.args); - } + if (args.commands) { + for (const command of args.commands) { + // Check if this is a vim command by looking for : + if (command.command.slice(0, 1) === ':') { + await runCmdLine(command.command.slice(1, command.command.length), mh); + await mh.updateView(mh.vimState); + } else { + await vscode.commands.executeCommand(command.command, command.args); } } - }, - isRunning: false, + } }); }); @@ -447,11 +432,8 @@ function registerCommand( async function handleKeyEvent(key: string): Promise { const mh = await getAndUpdateModeHandler(); - taskQueue.enqueueTask({ - promise: async () => { - await mh.handleKeyEvent(key); - }, - isRunning: false, + taskQueue.enqueueTask(async () => { + await mh.handleKeyEvent(key); }); } @@ -474,15 +456,12 @@ async function handleActiveEditorChange(): Promise { return; } - taskQueue.enqueueTask({ - promise: async () => { - if (vscode.window.activeTextEditor !== undefined) { - const mh = await getAndUpdateModeHandler(); + taskQueue.enqueueTask(async () => { + if (vscode.window.activeTextEditor !== undefined) { + const mh = await getAndUpdateModeHandler(); - mh.updateView(mh.vimState, { drawSelection: false, revealRange: false }); - } - }, - isRunning: false, + mh.updateView(mh.vimState, { drawSelection: false, revealRange: false }); + } }); } diff --git a/src/configuration/configuration.ts b/src/configuration/configuration.ts index bc4ffda4e..d6bed653b 100644 --- a/src/configuration/configuration.ts +++ b/src/configuration/configuration.ts @@ -361,25 +361,19 @@ function overlapSetting(args: { set: function(value) { this['_' + propertyKey] = value; - taskQueue.enqueueTask({ - promise: async () => { - if (value === undefined || Globals.isTesting) { - return; - } + taskQueue.enqueueTask(async () => { + if (value === undefined || Globals.isTesting) { + return; + } - let codeValue = value; + let codeValue = value; - if (args.codeValueMapping) { - codeValue = args.codeValueMapping[value]; - } + if (args.codeValueMapping) { + codeValue = args.codeValueMapping[value]; + } - await vscode.workspace - .getConfiguration('editor') - .update(args.codeName, codeValue, true); - }, - isRunning: false, - queue: 'config', - }); + await vscode.workspace.getConfiguration('editor').update(args.codeName, codeValue, true); + }, 'config'); }, enumerable: true, configurable: true, diff --git a/src/mode/modeHandler.ts b/src/mode/modeHandler.ts index 9c6b23caf..93ab9279f 100644 --- a/src/mode/modeHandler.ts +++ b/src/mode/modeHandler.ts @@ -581,16 +581,15 @@ export class ModeHandler implements vscode.Disposable { return; } - taskQueue.enqueueTask({ - promise: () => this.handleSelectionChange(e), - isRunning: false, - + taskQueue.enqueueTask( + () => this.handleSelectionChange(e), + undefined, /** * We don't want these to become backlogged! If they do, we'll update * the selection to an incorrect value and see a jittering cursor. */ - highPriority: true, - }); + true + ); } ); diff --git a/src/taskQueue.ts b/src/taskQueue.ts index 503c333bc..b8e3d05c5 100644 --- a/src/taskQueue.ts +++ b/src/taskQueue.ts @@ -1,26 +1,34 @@ import * as _ from 'lodash'; -export interface IEnqueuedTask { +interface IEnqueuedTask { promise: () => Promise; isRunning: boolean; - queue?: string; - highPriority?: boolean; + queue: string; + isHighPriority: boolean; } -/** - * TaskQueue - * - * Enqueue promises here. They will be run sequentially. - */ class TaskQueue { private _taskQueue: { [key: string]: { tasks: IEnqueuedTask[]; - highPriorityCount: number; }; } = {}; - private async _runTasks(queueName: string): Promise { + private isRunning(queueName: string): boolean { + return ( + this._taskQueue[queueName] && + _.filter(this._taskQueue[queueName].tasks, x => x.isRunning).length > 0 + ); + } + + private numHighPriority(queueName: string): number { + if (!this._taskQueue[queueName]) { + return 0; + } + return _.filter(this._taskQueue[queueName].tasks, x => x.isHighPriority).length; + } + + private async runTasks(queueName: string): Promise { while (this._taskQueue[queueName].tasks.length > 0) { let task: IEnqueuedTask = this._taskQueue[queueName].tasks[0]; @@ -29,73 +37,54 @@ class TaskQueue { await task.promise(); task.isRunning = false; } catch (e) { - console.log(e); - console.log(e.stack); + console.error(e); } finally { - this.removeTask(task); - - if (task.highPriority) { - this._taskQueue[queueName].highPriorityCount--; - } + this.dequeueTask(task); } } } - public get tasks(): number { - let result = 0; - - for (const list in this._taskQueue) { - if (this._taskQueue.hasOwnProperty(list)) { - result += this._taskQueue[list].tasks.length; - } - } - - return result; - } - /** - * Removes a task from the task queue. + * Dequeues a task from the task queue. * - * (Keep in mind that if the task is already running, the semantics of - * promises don't allow you to stop it.) + * Note: If the task is already running, the semantics of + * promises don't allow you to stop it. */ - public removeTask(task: IEnqueuedTask): void { - let queueName = task.queue || 'default'; - this._taskQueue[queueName].tasks.splice( - _.findIndex(this._taskQueue[queueName].tasks, t => t === task), - 1 - ); + private dequeueTask(task: IEnqueuedTask): void { + _.remove(this._taskQueue[task.queue].tasks, t => t === task); } /** * Adds a task to the task queue. */ - public enqueueTask(task: IEnqueuedTask): void { - let queueName = task.queue || 'default'; - let otherTaskRunning = - this._taskQueue[queueName] && - _.filter(this._taskQueue[queueName].tasks, x => x.isRunning).length > 0; + public enqueueTask( + action: () => Promise, + queueName: string = 'default', + isHighPriority: boolean = false + ): void { + let task: IEnqueuedTask = { + promise: action, + queue: queueName, + isHighPriority: isHighPriority, + isRunning: false, + }; - if (this._taskQueue[queueName]) { - if (task.highPriority) { - // Insert task as the last high priotity task. - - const numHighPriority = this._taskQueue[queueName].highPriorityCount; - - this._taskQueue[queueName].tasks.splice(numHighPriority, 0, task); - this._taskQueue[queueName].highPriorityCount++; - } else { - this._taskQueue[queueName].tasks.push(task); - } - } else { + if (!this._taskQueue[queueName]) { this._taskQueue[queueName] = { - tasks: [task], - highPriorityCount: 0, + tasks: [], }; } - if (!otherTaskRunning) { - this._runTasks(queueName); + if (isHighPriority) { + // Insert task as the last high priotity task. + const numHighPriority = this.numHighPriority(queueName); + this._taskQueue[queueName].tasks.splice(numHighPriority, 0, task); + } else { + this._taskQueue[queueName].tasks.push(task); + } + + if (!this.isRunning(queueName)) { + this.runTasks(queueName); } } }