From d66900710df036b47973cc3b5a957015e09ed6bd Mon Sep 17 00:00:00 2001 From: frelodev Date: Fri, 6 Sep 2024 18:45:25 +0200 Subject: [PATCH] feat: tree for workspaces and buffers --- package.json | 19 ++++++++++++ src/commands.ts | 29 +++++++++++------- src/extension.ts | 5 ++++ src/tree.ts | 76 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 119 insertions(+), 10 deletions(-) create mode 100644 src/tree.ts diff --git a/package.json b/package.json index 29081e0..ba6648b 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,25 @@ ], "main": "./out/extension.js", "contributes": { + "viewsContainers": { + "activitybar": [ + { + "id": "codemp-tree-container", + "title": "codemp", + "icon": "resources/codemp.svg" + } + ] + }, + + "views": { + "codemp-tree-container": [ + { + "id": "codemp-tree-view", + "name": "tree" + } + ] + }, + "commands": [ { "command": "codemp.connect", diff --git a/src/commands.ts b/src/commands.ts index b2fdb5a..fa676a6 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -1,13 +1,16 @@ import * as vscode from 'vscode'; import * as codemp from 'codemp'; import * as mapping from "./mapping"; -import { LOGGER } from './extension'; +import { LOGGER, provider } from './extension'; -let CACHE = new codemp.OpCache(); -let client: codemp.Client | null = null; -let workspace: codemp.Workspace | null = null; -let mine : boolean; +// TODO this "global state" should probably live elsewher but we need lo update it from these commands +export let client: codemp.Client | null = null; +export let workspace: codemp.Workspace | null = null; +export let workspace_list: string[] = []; + +let CACHE = new codemp.OpCache(); // TODO do we still need this after "mine" flag? + export async function connect() { let config = vscode.workspace.getConfiguration('codemp'); @@ -22,8 +25,10 @@ export async function connect() { if (!password) { return vscode.window.showErrorMessage("missing password in settings: configure it first!"); } - + vscode.window.showInformationMessage("Connected to codemp"); client = await codemp.connect(server, username, password); + provider.refresh(); + listWorkspaces(); // dont await, run in background } @@ -72,6 +77,7 @@ export async function join() { await controller.send(cursor); }); vscode.window.showInformationMessage("Connected to workspace"); + provider.refresh(); } @@ -80,6 +86,7 @@ export async function createBuffer() { if (workspace === null) throw "join a workspace first" workspace.create(bufferName); vscode.window.showInformationMessage(`new buffer created :${bufferName}`); + provider.refresh(); } @@ -114,6 +121,7 @@ export async function attach() { editBuilder .replace(range, bufferContent) }); + let mine = false; // this toggles off send callback while we're updating the buffer TODO does it work? is it reliable? vscode.workspace.onDidChangeTextDocument(async (event: vscode.TextDocumentChangeEvent) => { if(mine) { return } if (event.document.uri !== file_uri) return; // ? @@ -147,7 +155,6 @@ export async function attach() { } }); - } export async function sync() { @@ -173,7 +180,8 @@ export async function sync() { export async function listBuffers() { if (workspace === null) throw "join a workspace first" let buffers = workspace.filetree(); - vscode.window.showInformationMessage(buffers.join("\n")) + vscode.window.showInformationMessage(buffers.join("\n")); + provider.refresh(); } @@ -188,6 +196,7 @@ export async function createWorkspace(){ return; } await client.create_workspace(workspace_id); + provider.refresh(); } export async function listWorkspaces(){ @@ -195,8 +204,8 @@ export async function listWorkspaces(){ vscode.window.showInformationMessage("Connect first"); return; } - let result = await client.list_workspaces(true, true); - vscode.window.showInformationMessage(result.join("\n")) + workspace_list = await client.list_workspaces(true, true); + provider.refresh(); } diff --git a/src/extension.ts b/src/extension.ts index d782ce6..a836c94 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,6 +1,9 @@ import * as vscode from 'vscode'; import * as codemp from 'codemp'; import * as commands from './commands'; +import { CodempTreeProvider } from './tree'; + +export let provider = new CodempTreeProvider(); export let LOGGER = vscode.window.createOutputChannel("codemp", { log: true }); @@ -8,6 +11,8 @@ export let LOGGER = vscode.window.createOutputChannel("codemp", { log: true }); 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); // register commands: the commandId parameter must match the command field in package.json for (let cmd of [ diff --git a/src/tree.ts b/src/tree.ts new file mode 100644 index 0000000..a9176ee --- /dev/null +++ b/src/tree.ts @@ -0,0 +1,76 @@ +import * as vscode from 'vscode'; +import * as codemp from 'codemp'; +import { client, workspace, workspace_list } from './commands'; + +export class CodempTreeProvider implements vscode.TreeDataProvider { + + constructor() {} + + private _emitter: vscode.EventEmitter = new vscode.EventEmitter(); + readonly onDidChangeTreeData: vscode.Event = this._emitter.event; + + refresh(): void { + this._emitter.fire(); + } + + getTreeItem(element: CodempTreeItem): vscode.TreeItem { + return element; + } + + async getChildren(element?: CodempTreeItem): Promise { + if (element) { + switch (element.type) { + case Type.Root: + if (client === null) { return [] }; + return workspace_list.map((x) => new CodempTreeItem(x, Type.Workspace)); + case Type.Workspace: + if (workspace === null) { return [] }; + if (element.label == workspace.id()) { + return [ + new CodempTreeItem("Buffers", Type.BufferContainer), + new CodempTreeItem("Users", Type.UserContainer) + ]; + } else { + return []; + } + case Type.BufferContainer: + if (workspace === null) { return [] }; + return workspace.filetree().map((x) => new CodempTreeItem(x, Type.Buffer)); + case Type.UserContainer: + if (workspace === null) { return [] }; + return [new CodempTreeItem("TODO", Type.User)]; // TODO keep track of users + case Type.Buffer: + return []; + case Type.User: + return []; + } + } else { + if(client === null) { + return [ + new CodempTreeItem("Connect", Type.Root) + ]; + } + return [ + new CodempTreeItem("Codemp", Type.Root) + ]; + } + + } +} + +class CodempTreeItem extends vscode.TreeItem { + type: Type; + constructor(label: string | vscode.TreeItemLabel, type: Type){ + super(label, vscode.TreeItemCollapsibleState.Expanded); + this.type=type; + } +} + +enum Type{ + Root, + Workspace, + BufferContainer, + UserContainer, + Buffer, + User, +}