diff --git a/client/vscode/src/extension.js b/client/vscode/src/extension.js index 27a6217..176e42b 100644 --- a/client/vscode/src/extension.js +++ b/client/vscode/src/extension.js @@ -2,17 +2,108 @@ const vscode = require("vscode"); const codemp = require("./codemp.node"); var CLIENT = null +var CONTROLLER +var OP_CACHE = new Set() async function activate(context) { - // This must match the command property in the package.json - const commandID = "codemp.connect"; - let disposable = vscode.commands.registerCommand(commandID, connect); - context.subscriptions.push(disposable); + context.subscriptions.push( + vscode.commands.registerCommand("codemp.connect", connect), + vscode.commands.registerCommand("codemp.share", share), + vscode.commands.registerCommand("codemp.join", join), + ) } async function connect() { - CLIENT = await codemp.connect("http://fantabos.co:50051") - vscode.window.showInformationMessage("Connected to CodeMP!"); + let host = await vscode.window.showInputBox({prompt: "server host (default to http://fantabos.co:50051)"}) + if (host === undefined) return // user cancelled with ESC + if (host.length == 0) host = "http://fantabos.co:50051" + CLIENT = await codemp.connect(host) + vscode.window.showInformationMessage(`Connected to codemp @[${host}]`); +} + +async function share() { + if (CLIENT === null) { + vscode.window.showErrorMessage("No connected client"); + } + + let path = await vscode.window.showInputBox({prompt: "buffer uri (default to file path)"}) + if (path === undefined) return // user cancelled with ESC + if (path.length == 0) path = doc.uri.toString() + + let doc = vscode.window.activeTextEditor.document; + + try { + if (!await CLIENT.create(path, doc.getText())) { + vscode.window.showErrorMessage("Could not share buffer"); + } + + await _attach(path) + + vscode.window.showInformationMessage(`Shared document on buffer "${path}"`); + } catch (err) { + vscode.window.showErrorMessage("Error sharing: " + err) + } +} + +async function join() { + if (CLIENT === null) { + vscode.window.showErrorMessage("No connected client"); + } + + let path = await vscode.window.showInputBox({prompt: "buffer uri"}) + + try { + let controller = await _attach(path) + + vscode.window.showInformationMessage(`Joined buffer "${path}"`); + + let editor = vscode.window.activeTextEditor + + let range = new vscode.Range( + editor.document.positionAt(0), + editor.document.positionAt(editor.document.getText().length) + ) + let content = controller.content() + OP_CACHE.add((range, content)) + editor.edit(editBuilder => editBuilder.replace(range, content)) + } catch (err) { + vscode.window.showErrorMessage("error joining " + err) + } +} + +async function _attach(path) { + let doc = vscode.window.activeTextEditor.document; + CONTROLLER = await CLIENT.attach(path) + vscode.workspace.onDidChangeTextDocument(async (e) => { + if (e.document != doc) return + for (let change of e.contentChanges) { + if (OP_CACHE.has((change.range, change.text))) { + OP_CACHE.delete((change.range, change.text)) + continue + } + try { + await CONTROLLER.apply(change.rangeOffset, change.text, change.rangeOffset + change.rangeLength) + } catch (err) { + vscode.window.showErrorMessage("failed sending change: " + err) + } + } + }) + let editor = vscode.window.activeTextEditor + CONTROLLER.set_callback((start, end) => { + // TODO only change affected document range + let content = CONTROLLER.content() + let range = new vscode.Range( + editor.document.positionAt(0), + editor.document.positionAt(editor.document.getText().length) + ) + try { + OP_CACHE.add((range, content)) + editor.edit(editBuilder => editBuilder.replace(range, content)) + } catch (err) { + vscode.window.showErrorMessage("could not set buffer: " + err) + } + }) + return CONTROLLER } module.exports = {