fix: dont stop following when jumping across bufs

also refactor a bit globals

Co-authored-by: frelodev <frelodev@gmail.com>
This commit is contained in:
əlemi 2024-10-13 00:36:09 +02:00
parent 6bc6561769
commit 8586c07fe1
Signed by: alemi
GPG key ID: A4895B84D311642C
5 changed files with 67 additions and 73 deletions

View file

@ -1,7 +1,7 @@
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import * as codemp from 'codemp'; import * as codemp from 'codemp';
import * as mapping from "../mapping"; import * as mapping from "../mapping";
import { workspace } from "./workspaces"; import { workspaceState } from "./workspaces";
import { LOGGER, provider } from '../extension'; import { LOGGER, provider } from '../extension';
let singles: Map<string, boolean> = new Map(); let singles: Map<string, boolean> = new Map();
@ -16,7 +16,7 @@ export async function apply_changes_to_buffer(path: string, controller: codemp.B
singles.set(path, true); singles.set(path, true);
while (true) { while (true) {
if (workspace === null) { if (workspaceState.workspace === null) {
LOGGER.info(`left workspace, unregistering buffer controller '${path}' callback`); LOGGER.info(`left workspace, unregistering buffer controller '${path}' callback`);
controller.clear_callback(); controller.clear_callback();
return; return;
@ -36,7 +36,7 @@ export async function apply_changes_to_buffer(path: string, controller: codemp.B
.replace(range, event.content) .replace(range, event.content)
})) { })) {
vscode.window.showWarningMessage("Couldn't apply changes"); vscode.window.showWarningMessage("Couldn't apply changes");
await resync(path, workspace, editor, 100); await resync(path, workspaceState.workspace, editor, 100);
} }
locks.delete(path); locks.delete(path);
@ -44,12 +44,12 @@ export async function apply_changes_to_buffer(path: string, controller: codemp.B
if (codemp.hash(editor.document.getText()) !== event.hash) { if (codemp.hash(editor.document.getText()) !== event.hash) {
if (autoResync) { if (autoResync) {
vscode.window.showWarningMessage("Out of Sync, resynching..."); vscode.window.showWarningMessage("Out of Sync, resynching...");
await resync(path, workspace, editor, 20); await resync(path, workspaceState.workspace, editor, 20);
} else { } else {
controller.clear_callback(); controller.clear_callback();
const selection = await vscode.window.showWarningMessage('Out of Sync', 'Resync'); const selection = await vscode.window.showWarningMessage('Out of Sync', 'Resync');
if (selection !== undefined && workspace) { if (selection !== undefined && workspaceState.workspace) {
await resync(path, workspace, editor, 20); await resync(path, workspaceState.workspace, editor, 20);
controller.callback(async (controller: codemp.BufferController) => controller.callback(async (controller: codemp.BufferController) =>
await apply_changes_to_buffer(controller.get_path(), controller) await apply_changes_to_buffer(controller.get_path(), controller)
); );
@ -62,7 +62,7 @@ export async function apply_changes_to_buffer(path: string, controller: codemp.B
} }
export async function attach_to_remote_buffer(buffer_name: string, set_content?: boolean): Promise<codemp.BufferController | undefined> { export async function attach_to_remote_buffer(buffer_name: string, set_content?: boolean): Promise<codemp.BufferController | undefined> {
if (workspace === null) { if (workspaceState.workspace === null) {
vscode.window.showErrorMessage("join a Workspace first"); vscode.window.showErrorMessage("join a Workspace first");
return; return;
} }
@ -86,7 +86,7 @@ export async function attach_to_remote_buffer(buffer_name: string, set_content?:
let doc = await vscode.workspace.openTextDocument(path); let doc = await vscode.workspace.openTextDocument(path);
let editor = await vscode.window.showTextDocument(doc, { preserveFocus: false }) let editor = await vscode.window.showTextDocument(doc, { preserveFocus: false })
await editor.edit((editor) => editor.setEndOfLine(vscode.EndOfLine.LF)); // set LF for EOL sequence await editor.edit((editor) => editor.setEndOfLine(vscode.EndOfLine.LF)); // set LF for EOL sequence
let buffer: codemp.BufferController = await workspace.attach(buffer_name); let buffer: codemp.BufferController = await workspaceState.workspace.attach(buffer_name);
// wait for server changes // wait for server changes
// TODO poll never unblocks, so this dirty fix is necessary // TODO poll never unblocks, so this dirty fix is necessary
@ -148,7 +148,7 @@ export async function attach_to_remote_buffer(buffer_name: string, set_content?:
} }
export async function attach(selected: vscode.TreeItem | undefined) { export async function attach(selected: vscode.TreeItem | undefined) {
if (workspace === null) return vscode.window.showWarningMessage("Join a workspace first"); if (workspaceState.workspace === null) return vscode.window.showWarningMessage("Join a workspace first");
let buffer_name: string | undefined; let buffer_name: string | undefined;
if (selected !== undefined && selected.label !== undefined) { if (selected !== undefined && selected.label !== undefined) {
if (typeof (selected.label) === 'string') { if (typeof (selected.label) === 'string') {
@ -157,14 +157,14 @@ export async function attach(selected: vscode.TreeItem | undefined) {
buffer_name = selected.label.label; // TODO ughh what is this api? buffer_name = selected.label.label; // TODO ughh what is this api?
} }
} else { } else {
buffer_name = await vscode.window.showQuickPick(workspace.filetree(null, false), { placeHolder: "buffer to attach to:" }, undefined); buffer_name = await vscode.window.showQuickPick(workspaceState.workspace.filetree(null, false), { placeHolder: "buffer to attach to:" }, undefined);
} }
if (!buffer_name) return; if (!buffer_name) return;
await attach_to_remote_buffer(buffer_name); await attach_to_remote_buffer(buffer_name);
} }
export async function detach(selected: vscode.TreeItem | undefined) { export async function detach(selected: vscode.TreeItem | undefined) {
if (workspace === null) return vscode.window.showWarningMessage("Not in a workspace"); if (workspaceState.workspace === null) return vscode.window.showWarningMessage("Not in a workspace");
let buffer_name: string | undefined; let buffer_name: string | undefined;
if (selected !== undefined && selected.label !== undefined) { if (selected !== undefined && selected.label !== undefined) {
if (typeof (selected.label) === 'string') { if (typeof (selected.label) === 'string') {
@ -173,12 +173,12 @@ export async function detach(selected: vscode.TreeItem | undefined) {
buffer_name = selected.label.label; // TODO ughh what is this api? buffer_name = selected.label.label; // TODO ughh what is this api?
} }
} else { } else {
buffer_name = await vscode.window.showQuickPick(workspace.buffer_list(), { placeHolder: "buffer to detach from:" }, undefined); buffer_name = await vscode.window.showQuickPick(workspaceState.workspace.buffer_list(), { placeHolder: "buffer to detach from:" }, undefined);
} }
if (!buffer_name) return; if (!buffer_name) return;
let controller = workspace.buffer_by_name(buffer_name); let controller = workspaceState.workspace.buffer_by_name(buffer_name);
if (controller) controller.clear_callback(); if (controller) controller.clear_callback();
workspace.detach(buffer_name); workspaceState.workspace.detach(buffer_name);
mapping.bufferMapper.remove(buffer_name); mapping.bufferMapper.remove(buffer_name);
vscode.window.showInformationMessage(`Detached from buffer ${buffer_name}`) vscode.window.showInformationMessage(`Detached from buffer ${buffer_name}`)
provider.refresh(); provider.refresh();
@ -186,7 +186,7 @@ export async function detach(selected: vscode.TreeItem | undefined) {
export async function share() { export async function share() {
if (workspace === null) return vscode.window.showWarningMessage("Join a workspace first"); if (workspaceState.workspace === null) return vscode.window.showWarningMessage("Join a workspace first");
let buffer_name: string | undefined; let buffer_name: string | undefined;
if (vscode.window.activeTextEditor !== null) { if (vscode.window.activeTextEditor !== null) {
buffer_name = vscode.window.activeTextEditor?.document.uri.toString(); buffer_name = vscode.window.activeTextEditor?.document.uri.toString();
@ -198,12 +198,12 @@ export async function share() {
let workspacePath: string = vscode.workspace.workspaceFolders[0].uri.toString(); let workspacePath: string = vscode.workspace.workspaceFolders[0].uri.toString();
buffer_name = buffer_name.replace(workspacePath, "").substring(1); //vscode.workspace.asRelativePath doesn't work properly with other extensions like ssh, substring(1) to remove "/" buffer_name = buffer_name.replace(workspacePath, "").substring(1); //vscode.workspace.asRelativePath doesn't work properly with other extensions like ssh, substring(1) to remove "/"
console.log("After: " + buffer_name); console.log("After: " + buffer_name);
await workspace.create(buffer_name); await workspaceState.workspace.create(buffer_name);
await attach_to_remote_buffer(buffer_name, true); await attach_to_remote_buffer(buffer_name, true);
} }
export async function sync(selected: vscode.TreeItem | undefined) { export async function sync(selected: vscode.TreeItem | undefined) {
if (workspace === null) return vscode.window.showWarningMessage("Join a workspace first"); if (workspaceState.workspace === null) return vscode.window.showWarningMessage("Join a workspace first");
let editor; let editor;
let buffer_name; let buffer_name;
if (selected !== undefined && selected.label !== undefined) { if (selected !== undefined && selected.label !== undefined) {
@ -221,7 +221,7 @@ export async function sync(selected: vscode.TreeItem | undefined) {
if (buffer_name === undefined) return vscode.window.showWarningMessage("Buffer not synched with codemp"); if (buffer_name === undefined) return vscode.window.showWarningMessage("Buffer not synched with codemp");
} }
resync(buffer_name, workspace, editor); resync(buffer_name, workspaceState.workspace, editor);
} }
export async function resync(buffer_name: string, workspace: codemp.Workspace, editor: vscode.TextEditor, tries?: number) { export async function resync(buffer_name: string, workspace: codemp.Workspace, editor: vscode.TextEditor, tries?: number) {

View file

@ -1,7 +1,7 @@
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import * as codemp from 'codemp'; import * as codemp from 'codemp';
import * as mapping from "../mapping"; import * as mapping from "../mapping";
import { workspace, setWorkspace, follow, setFollow, executeJump } from "./workspaces"; import { executeJump, workspaceState } from "./workspaces";
import { LOGGER, provider } from '../extension'; import { LOGGER, provider } from '../extension';
@ -9,7 +9,6 @@ import { LOGGER, provider } from '../extension';
export let client: codemp.Client | null = null; export let client: codemp.Client | null = null;
export let workspace_list: string[] = []; export let workspace_list: string[] = [];
export let cursor_disposable: vscode.Disposable | null; export let cursor_disposable: vscode.Disposable | null;
let movedByFollow = false;
export async function connect() { export async function connect() {
let config = vscode.workspace.getConfiguration('codemp'); let config = vscode.workspace.getConfiguration('codemp');
@ -57,13 +56,12 @@ export async function join(selected: vscode.TreeItem | undefined) {
let ws = await vscode.window.showWorkspaceFolderPick({ placeHolder: "directory to open workspace into:" }); let ws = await vscode.window.showWorkspaceFolderPick({ placeHolder: "directory to open workspace into:" });
if (ws === undefined) return vscode.window.showErrorMessage("Open a Workspace folder first"); if (ws === undefined) return vscode.window.showErrorMessage("Open a Workspace folder first");
} }
setWorkspace(await client.join_workspace(workspace_id)); workspaceState.workspace = await client.join_workspace(workspace_id);
if (!workspace) return; let controller = workspaceState.workspace.cursor();
let controller = workspace.cursor();
controller.callback(async function (controller: codemp.CursorController) { controller.callback(async function (controller: codemp.CursorController) {
while (true) { while (true) {
let event = await controller.try_recv(); let event = await controller.try_recv();
if (workspace === null) { if (workspaceState.workspace === null) {
controller.clear_callback(); controller.clear_callback();
LOGGER.info("left workspace, stopping cursor controller"); LOGGER.info("left workspace, stopping cursor controller");
return; return;
@ -79,14 +77,11 @@ export async function join(selected: vscode.TreeItem | undefined) {
mapping.colors_cache.set(event.user, mapp); mapping.colors_cache.set(event.user, mapp);
provider.refresh(); provider.refresh();
} }
if (follow === event.user) {
movedByFollow = true;
executeJump(event.user);
}
let editor = mapping.bufferMapper.visible_by_buffer(event.buffer); let editor = mapping.bufferMapper.visible_by_buffer(event.buffer);
let refresh = event.buffer != mapp.buffer; let refresh = event.buffer != mapp.buffer;
mapp.update(event, editor); mapp.update(event, editor);
if (workspaceState.follow === event.user) executeJump(event.user);
if (refresh) provider.refresh(); if (refresh) provider.refresh();
} }
}); });
@ -94,8 +89,8 @@ export async function join(selected: vscode.TreeItem | undefined) {
let once = true; let once = true;
cursor_disposable = vscode.window.onDidChangeTextEditorSelection(async (event: vscode.TextEditorSelectionChangeEvent) => { cursor_disposable = vscode.window.onDidChangeTextEditorSelection(async (event: vscode.TextEditorSelectionChangeEvent) => {
if (event.kind == vscode.TextEditorSelectionChangeKind.Command) return; // TODO commands might move cursor too if (event.kind == vscode.TextEditorSelectionChangeKind.Command) return; // TODO commands might move cursor too
if (!movedByFollow) setFollow(null); if (!workspaceState.justJumped) workspaceState.follow = null;
else movedByFollow = false; workspaceState.justJumped = false;
let buf = event.textEditor.document.uri; let buf = event.textEditor.document.uri;
let selection: vscode.Selection = event.selections[0]; let selection: vscode.Selection = event.selections[0];
let buffer = mapping.bufferMapper.by_editor(buf); let buffer = mapping.bufferMapper.by_editor(buf);
@ -128,8 +123,8 @@ export async function join(selected: vscode.TreeItem | undefined) {
let event_handler = async () => { let event_handler = async () => {
try { try {
while (true) { while (true) {
if (workspace === null) break; if (workspaceState.workspace === null) break;
let event = await workspace.event(); let event = await workspaceState.workspace.event();
if (event.type == "leave") { if (event.type == "leave") {
mapping.colors_cache.get(event.value)?.clear() mapping.colors_cache.get(event.value)?.clear()
mapping.colors_cache.delete(event.value); mapping.colors_cache.delete(event.value);
@ -145,7 +140,7 @@ export async function join(selected: vscode.TreeItem | undefined) {
}; };
event_handler(); event_handler();
for (let user of workspace.user_list()) { for (let user of workspaceState.workspace.user_list()) {
mapping.colors_cache.set(user, new mapping.UserDecoration(user)); mapping.colors_cache.set(user, new mapping.UserDecoration(user));
} }
@ -183,12 +178,12 @@ export async function inviteToWorkspace() {
export async function leave() { export async function leave() {
if (!client) throw "can't leave while disconnected"; if (!client) throw "can't leave while disconnected";
if (!workspace) throw "can't leave while not in a workspace"; if (!workspaceState.workspace) throw "can't leave while not in a workspace";
workspace.cursor().clear_callback() workspaceState.workspace.cursor().clear_callback()
client.leave_workspace(workspace.id()); client.leave_workspace(workspaceState.workspace.id());
if (cursor_disposable !== null) cursor_disposable.dispose(); if (cursor_disposable !== null) cursor_disposable.dispose();
let workspace_id = workspace.id(); let workspace_id = workspaceState.workspace.id();
setWorkspace(null); workspaceState.workspace = null;
provider.refresh(); provider.refresh();
vscode.window.showInformationMessage("Left workspace " + workspace_id); vscode.window.showInformationMessage("Left workspace " + workspace_id);
} }

View file

@ -5,17 +5,15 @@ import { client } from "./client"
import { LOGGER, provider } from '../extension'; import { LOGGER, provider } from '../extension';
export let workspace: codemp.Workspace | null = null; export let workspaceState: {
export let follow: string | null = null; workspace: codemp.Workspace | null,
follow: string | null,
justJumped: boolean,
export function setWorkspace(ws: codemp.Workspace | null) { } = {
workspace = ws; workspace: null,
} follow: null,
justJumped: false,
export function setFollow(doFollow: string | null) { };
follow = doFollow;
}
export async function jump(selected: vscode.TreeItem | undefined) { export async function jump(selected: vscode.TreeItem | undefined) {
@ -30,7 +28,7 @@ export async function jump(selected: vscode.TreeItem | undefined) {
} }
if (!user) user = await vscode.window.showInputBox({ prompt: "username" }); if (!user) user = await vscode.window.showInputBox({ prompt: "username" });
if (!user) return; // user cancelled with ESC if (!user) return; // user cancelled with ESC
setFollow(user); workspaceState.follow=user;
executeJump(user); executeJump(user);
} }
@ -41,35 +39,36 @@ export async function executeJump(user: string) {
if (uri === undefined) { if (uri === undefined) {
return vscode.window.showWarningMessage("user is on an untracked buffer: " + user_hl.buffer); return vscode.window.showWarningMessage("user is on an untracked buffer: " + user_hl.buffer);
} }
let editor = await vscode.window.showTextDocument(uri, { preserveFocus: false }); let editor = vscode.window.activeTextEditor;
if (editor === undefined || editor.document.uri != uri) {
workspaceState.justJumped = true;
editor = await vscode.window.showTextDocument(uri, { preserveFocus: false });
}
let range_start: vscode.Position = new vscode.Position(user_hl.startRow, user_hl.startCol); let range_start: vscode.Position = new vscode.Position(user_hl.startRow, user_hl.startCol);
let range_end: vscode.Position = new vscode.Position(user_hl.endRow, user_hl.endCol); let range_end: vscode.Position = new vscode.Position(user_hl.endRow, user_hl.endCol);
let cursor_range = new vscode.Range(range_start, range_end); let cursor_range = new vscode.Range(range_start, range_end);
editor.revealRange(cursor_range, vscode.TextEditorRevealType.InCenter); editor.revealRange(cursor_range, vscode.TextEditorRevealType.InCenter);
} }
export async function createBuffer() { export async function createBuffer() {
let bufferName: any = (await vscode.window.showInputBox({ prompt: "path of the buffer to create" })); let bufferName: any = (await vscode.window.showInputBox({ prompt: "path of the buffer to create" }));
if (workspace === null) return vscode.window.showWarningMessage("Join a workspace first"); if (workspaceState.workspace === null) return vscode.window.showWarningMessage("Join a workspace first");
await workspace.create(bufferName); await workspaceState.workspace.create(bufferName);
vscode.window.showInformationMessage(`new buffer created :${bufferName}`); vscode.window.showInformationMessage(`new buffer created :${bufferName}`);
listBuffers(); provider.refresh();
//provider.refresh();
} }
export async function listBuffers() { export async function listBuffers() {
if (workspace === null) return vscode.window.showWarningMessage("Join a workspace first"); if (workspaceState.workspace === null) return vscode.window.showWarningMessage("Join a workspace first");
let buffers = workspace.filetree(undefined, false); let buffers = workspaceState.workspace.filetree(undefined, false);
vscode.window.showInformationMessage(buffers.join("\n")); vscode.window.showInformationMessage(buffers.join("\n"));
provider.refresh(); provider.refresh();
} }
export async function deleteBuffer() { export async function deleteBuffer() {
let bufferName: any = (await vscode.window.showInputBox({ prompt: "path of the buffer to delete" })); let bufferName: any = (await vscode.window.showInputBox({ prompt: "path of the buffer to delete" }));
if (workspace === null) return vscode.window.showWarningMessage("Join a workspace first"); if (workspaceState.workspace === null) return vscode.window.showWarningMessage("Join a workspace first");
await workspace.delete(bufferName); await workspaceState.workspace.delete(bufferName);
vscode.window.showInformationMessage(`Deleted buffer :${bufferName}`); vscode.window.showInformationMessage(`Deleted buffer :${bufferName}`);
listBuffers(); provider.refresh();
} }

View file

@ -3,7 +3,7 @@ import * as codemp from 'codemp';
import { client, connect, join, refresh, createWorkspace, inviteToWorkspace, listWorkspaces, leave } from './commands/client'; import { client, connect, join, refresh, createWorkspace, inviteToWorkspace, listWorkspaces, leave } from './commands/client';
import { CodempTreeProvider } from './tree'; import { CodempTreeProvider } from './tree';
import * as mapping from './mapping'; import * as mapping from './mapping';
import { workspace, jump, listBuffers, createBuffer, deleteBuffer } from './commands/workspaces' import { workspaceState, jump, listBuffers, createBuffer, deleteBuffer } from './commands/workspaces'
import { attach, share, sync, apply_changes_to_buffer, detach } from './commands/buffers' import { attach, share, sync, apply_changes_to_buffer, detach } from './commands/buffers'
export let provider = new CodempTreeProvider(); export let provider = new CodempTreeProvider();
@ -19,11 +19,11 @@ export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(sub); context.subscriptions.push(sub);
vscode.window.onDidChangeVisibleTextEditors(async (editors: readonly vscode.TextEditor[]) => { vscode.window.onDidChangeVisibleTextEditors(async (editors: readonly vscode.TextEditor[]) => {
if (workspace === null) return; if (workspaceState.workspace === null) return;
for (let editor of editors) { for (let editor of editors) {
let path = mapping.bufferMapper.by_editor(editor.document.uri); let path = mapping.bufferMapper.by_editor(editor.document.uri);
if (!path) continue; if (!path) continue;
let controller = workspace.buffer_by_name(path); let controller = workspaceState.workspace.buffer_by_name(path);
if (!controller) continue; if (!controller) continue;
await apply_changes_to_buffer(path, controller, true); await apply_changes_to_buffer(path, controller, true);
} }
@ -52,8 +52,8 @@ export function activate(context: vscode.ExtensionContext) {
} }
export async function deactivate() { export async function deactivate() {
if (client && workspace) { if (client && workspaceState.workspace) {
await client.leave_workspace(workspace.id()); await client.leave_workspace(workspaceState.workspace.id());
} }
} }

View file

@ -1,6 +1,6 @@
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import { client, workspace_list } from './commands/client'; import { client, workspace_list } from './commands/client';
import { workspace } from './commands/workspaces'; import { workspaceState } from './commands/workspaces';
import { bufferMapper, colors_cache } from './mapping'; import { bufferMapper, colors_cache } from './mapping';
export class CodempTreeProvider implements vscode.TreeDataProvider<CodempTreeItem> { export class CodempTreeProvider implements vscode.TreeDataProvider<CodempTreeItem> {
@ -22,9 +22,9 @@ export class CodempTreeProvider implements vscode.TreeDataProvider<CodempTreeIte
if (element) { if (element) {
switch (element.type) { switch (element.type) {
case Type.Workspace: case Type.Workspace:
if (workspace === null) return []; if (workspaceState.workspace === null) return [];
else if (element.label == workspace.id()) { else if (element.label == workspaceState.workspace.id()) {
return workspace.filetree(undefined, false).map((x) => return workspaceState.workspace.filetree(undefined, false).map((x) =>
new CodempTreeItem(x, Type.Buffer, { active: bufferMapper.bufferToEditorMapping.has(x) }) new CodempTreeItem(x, Type.Buffer, { active: bufferMapper.bufferToEditorMapping.has(x) })
); );
} else return []; } else return [];
@ -48,9 +48,9 @@ export class CodempTreeProvider implements vscode.TreeDataProvider<CodempTreeIte
return []; // empty screen with [connect] button return []; // empty screen with [connect] button
} }
let items = workspace_list.map((x) => let items = workspace_list.map((x) =>
new CodempTreeItem(x, Type.Workspace, { expandable: true, active: workspace === null }) new CodempTreeItem(x, Type.Workspace, { expandable: true, active: workspaceState.workspace === null })
); );
if (workspace !== null) { if (workspaceState.workspace !== null) {
items.push(new CodempTreeItem("", Type.Placeholder, {})); items.push(new CodempTreeItem("", Type.Placeholder, {}));
items.push(new CodempTreeItem("Users", Type.UserList, { expandable: true })); items.push(new CodempTreeItem("Users", Type.UserList, { expandable: true }));
} }