From a102a7f60f58c9d5a0c610b9b3be7ce6a5a1c983 Mon Sep 17 00:00:00 2001 From: frelodev Date: Tue, 24 Sep 2024 23:29:15 +0200 Subject: [PATCH] fix: stop ignoring changes when text editor is not visible --- src/commands.ts | 100 +++++++++++++++++++++-------------------------- src/extension.ts | 14 +++++++ 2 files changed, 59 insertions(+), 55 deletions(-) diff --git a/src/commands.ts b/src/commands.ts index dc17313..e466394 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -39,7 +39,6 @@ export async function connect() { } } - export async function join(selected: vscode.TreeItem | undefined) { if (client === null) throw "connect first"; let workspace_id: string | undefined; @@ -73,9 +72,9 @@ export async function join(selected: vscode.TreeItem | undefined) { mapping.colors_cache.set(event.user, mapp); provider.refresh(); } - let editor = mapping.bufferMapper.by_buffer(event.buffer); + let editor = mapping.bufferMapper.visible_by_buffer(event.buffer); mapp.update(event,editor); - /*if(event.buffer!=mapp.buffer) */provider.refresh(); + /*if(event.buffer!=mapp.buffer)*/ provider.refresh(); } }); @@ -108,6 +107,38 @@ export async function createBuffer() { provider.refresh(); } +export async function apply_changes_to_buffer(path: string, controller: codemp.BufferController | undefined | null, force?: boolean) { + if (workspace === null) throw "can't apply changes while not in a workspace"; + if (!controller) controller = workspace.buffer_by_name(path); + if (!controller) return; + let editor = mapping.bufferMapper.visible_by_buffer(path); + if (editor === undefined) return; + + if (locks.get(path) && !force) return; + locks.set(path, true); + while (true) { + let event = await controller.try_recv(); + if (event === null) break; + LOGGER.debug(`buffer.callback(event: [${event.start}, ${event.content}, ${event.end}])`) + + let range = new vscode.Range( + editor.document.positionAt(event.start), + editor.document.positionAt(event.end) + ) + + await editor.edit(editBuilder => { + editBuilder + .replace(range, event.content) + }); + + if (event.hash !== undefined) { + if (codemp.hash(editor.document.getText()) !== event.hash) + vscode.window.showErrorMessage("Client out of sync"); + } + } + locks.set(path, false); +} + export async function share(selected: vscode.TreeItem | undefined) { if (workspace === null) throw "join a workspace first" let buffer_name: string | undefined; @@ -123,7 +154,7 @@ export async function share(selected: vscode.TreeItem | undefined) { buffer_name = await vscode.window.showInputBox({ prompt: "path of buffer to attach to" }); } if (!buffer_name) return; // action cancelled by user - if (mapping.bufferMapper.by_buffer(buffer_name) !== undefined) { + if (mapping.bufferMapper.uri_by_buffer(buffer_name) !== undefined) { return vscode.window.showWarningMessage("buffer already attached"); } if (vscode.workspace.workspaceFolders === undefined) { @@ -175,29 +206,9 @@ export async function share(selected: vscode.TreeItem | undefined) { }); } }); - buffer.callback(async (controller: codemp.BufferController) => { - while (true) { - let event = await controller.try_recv(); - if (event === null) break; - LOGGER.debug(`buffer.callback(event: [${event.start}, ${event.content}, ${event.end}])`) - let editor = mapping.bufferMapper.by_buffer(buffer_name); - if (editor === undefined) { throw "Open an editor first" } - let range = new vscode.Range( - editor.document.positionAt(event.start), - editor.document.positionAt(event.end) - ) - locks.set(buffer_name, true); - await editor.edit(editBuilder => { - editBuilder - .replace(range, event.content) - }); - if(event.hash !== undefined){ - if(codemp.hash(editor.document.getText()) !== event.hash) vscode.window.showWarningMessage("Client out of sync"); - } - locks.set(buffer_name, false); - - } - }); + buffer.callback(async (controller: codemp.BufferController) => + await apply_changes_to_buffer(controller.get_path(), controller) + ); provider.refresh(); } @@ -215,7 +226,7 @@ export async function attach(selected: vscode.TreeItem | undefined) { buffer_name = await vscode.window.showInputBox({ prompt: "path of buffer to attach to" }); } if (!buffer_name) return; // action cancelled by user - if (mapping.bufferMapper.by_buffer(buffer_name) !== undefined) { + if (mapping.bufferMapper.visible_by_buffer(buffer_name) !== undefined) { return vscode.window.showWarningMessage("buffer already attached"); } if (vscode.workspace.workspaceFolders === undefined) { @@ -269,32 +280,11 @@ export async function attach(selected: vscode.TreeItem | undefined) { }); } }); - let consuming = false; - buffer.callback(async (controller: codemp.BufferController) => { - if (consuming) return; - consuming = true; - while (true) { - let event = await controller.try_recv(); - if (event === null) break; - LOGGER.debug(`buffer.callback(event: [${event.start}, ${event.content}, ${event.end}])`) - let editor = mapping.bufferMapper.by_buffer(buffer_name); - if (editor === undefined) { throw "Open an editor first" } - let range = new vscode.Range( - editor.document.positionAt(event.start), - editor.document.positionAt(event.end) - ) - locks.set(buffer_name, true); - await editor.edit(editBuilder => { - editBuilder - .replace(range, event.content) - }); - if(event.hash !== undefined){ - if(codemp.hash(editor.document.getText()) !== event.hash) vscode.window.showWarningMessage("Client out of sync"); - } - locks.set(buffer_name, false); - } - consuming = false; - }); + + buffer.callback(async (controller: codemp.BufferController) => + await apply_changes_to_buffer(controller.get_path(), controller) + ); + provider.refresh(); } @@ -308,7 +298,7 @@ export async function sync(selected: vscode.TreeItem | undefined) { } else { buffer_name = selected.label.label; // TODO ughh what is this api? } - editor = mapping.bufferMapper.by_buffer(buffer_name); + editor = mapping.bufferMapper.visible_by_buffer(buffer_name); if (editor === undefined) throw "no active editor to sync"; } else { editor = vscode.window.activeTextEditor; diff --git a/src/extension.ts b/src/extension.ts index 6b04881..b38b4c7 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -2,6 +2,7 @@ import * as vscode from 'vscode'; import * as codemp from 'codemp'; import * as commands from './commands'; import { CodempTreeProvider } from './tree'; +import * as mapping from './mapping'; export let provider = new CodempTreeProvider(); @@ -10,10 +11,20 @@ export let LOGGER = vscode.window.createOutputChannel("codemp", { log: true }); // extension is activated the very first time the command is executed export function activate(context: vscode.ExtensionContext) { // start codemp log poller + log_poller_task(new codemp.JsLogger()); // don't await it! run it in background forever let sub = vscode.window.registerTreeDataProvider('codemp-tree-view', provider); context.subscriptions.push(sub); + vscode.window.onDidChangeVisibleTextEditors(async (editors : readonly vscode.TextEditor[]) => { + if(commands.workspace===null) return; + for(let editor of editors){ + let path = mapping.bufferMapper.by_editor(editor.document.uri); + if (path===undefined) continue; + await commands.apply_changes_to_buffer(path, undefined, true); + } + }); + // register commands: the commandId parameter must match the command field in package.json for (let cmd of [ vscode.commands.registerCommand('codemp.connect', commands.connect), @@ -29,6 +40,7 @@ export function activate(context: vscode.ExtensionContext) { vscode.commands.registerCommand('codemp.listBuffers', commands.listBuffers), vscode.commands.registerCommand('codemp.sync', commands.sync), vscode.commands.registerCommand('codemp.refresh', commands.refresh), + vscode.commands.registerCommand('codemp.jump', commands.jump), ]) { context.subscriptions.push(cmd); } @@ -42,3 +54,5 @@ async function log_poller_task(logger: codemp.JsLogger) { console.log(message); } } + +