mirror of
https://github.com/hexedtech/codemp-intellij.git
synced 2024-11-24 16:04:48 +01:00
feat: workspace support, initial impl
This commit is contained in:
parent
085488ba36
commit
7c5c851f6f
24 changed files with 324 additions and 146 deletions
|
@ -4,7 +4,8 @@ version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
codemp = { git = "ssh://git@github.com/codewithotherpeopleandchangenamelater/codemp.git", branch = "workspace", features = ["global", "sync"] }
|
codemp = { path = "../../lib", features = ["global", "sync", "transport"] }
|
||||||
|
#codemp = { git = "ssh://git@github.com/codewithotherpeopleandchangenamelater/codemp.git", branch = "workspace", features = ["global", "sync"] }
|
||||||
jni = { version = "0.21.1", features = ["invocation"] }
|
jni = { version = "0.21.1", features = ["invocation"] }
|
||||||
jni-sys = "0.3.0"
|
jni-sys = "0.3.0"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
|
|
|
@ -19,11 +19,11 @@ repositories {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.github.adamheinrich:native-utils:master-SNAPSHOT'
|
implementation 'com.github.adamheinrich:native-utils:master-SNAPSHOT'
|
||||||
implementation 'org.slf4j:slf4j-api:2.0.9'
|
implementation 'org.slf4j:slf4j-api:2.0.9'
|
||||||
implementation 'ch.qos.logback:logback-classic:1.4.6'
|
implementation 'ch.qos.logback:logback-classic:1.4.12'
|
||||||
}
|
}
|
||||||
|
|
||||||
intellij {
|
intellij {
|
||||||
version.set('2022.2.5')
|
version.set('2023.3')
|
||||||
type.set('IC')
|
type.set('IC')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package com.codemp.intellij;
|
package com.codemp.intellij;
|
||||||
|
|
||||||
import com.intellij.openapi.editor.Editor;
|
import com.codemp.intellij.exceptions.ide.NotConnectedException;
|
||||||
|
import com.codemp.intellij.jni.ClientHandler;
|
||||||
|
import com.codemp.intellij.workspace.Workspace;
|
||||||
import com.intellij.openapi.util.SystemInfo;
|
import com.intellij.openapi.util.SystemInfo;
|
||||||
import cz.adamh.utils.NativeUtils;
|
import cz.adamh.utils.NativeUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -12,11 +14,25 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
public class CodeMP {
|
public class CodeMP {
|
||||||
public static Logger LOGGER = LoggerFactory.getLogger(CodeMP.class);
|
public static Logger LOGGER = LoggerFactory.getLogger(CodeMP.class);
|
||||||
|
public static final Map<String, Workspace> ACTIVE_WORKSPACES = new ConcurrentHashMap<>();
|
||||||
|
private static ClientHandler CLIENT = null;
|
||||||
|
|
||||||
public static final Map<String, Editor> ACTIVE_BUFFERS = new ConcurrentHashMap<>();
|
public static void connect(String url) {
|
||||||
public static final Map<Editor, String> ACTIVE_BUFFERS_REVERSE = new ConcurrentHashMap<>();
|
CodeMP.loadLibrary(); //will only load it the first time
|
||||||
|
CLIENT = new ClientHandler(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void disconnect() {
|
||||||
|
CLIENT = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ClientHandler getClient(String reason) throws NotConnectedException {
|
||||||
|
if(CLIENT == null) throw new NotConnectedException(reason);
|
||||||
|
return CLIENT;
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean loadedLibrary = false;
|
private static boolean loadedLibrary = false;
|
||||||
|
|
||||||
public static void loadLibrary() {
|
public static void loadLibrary() {
|
||||||
if(!loadedLibrary) {
|
if(!loadedLibrary) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package com.codemp.intellij.actions;
|
package com.codemp.intellij.actions;
|
||||||
|
|
||||||
import com.codemp.intellij.CodeMP;
|
import com.codemp.intellij.CodeMP;
|
||||||
import com.codemp.intellij.jni.CodeMPHandler;
|
|
||||||
import com.codemp.intellij.util.ActionUtil;
|
import com.codemp.intellij.util.ActionUtil;
|
||||||
import com.intellij.openapi.actionSystem.AnAction;
|
import com.intellij.openapi.actionSystem.AnAction;
|
||||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||||
|
@ -10,8 +9,7 @@ import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class ConnectAction extends AnAction {
|
public class ConnectAction extends AnAction {
|
||||||
public static void connect(AnActionEvent e, String url, boolean silent) {
|
public static void connect(AnActionEvent e, String url, boolean silent) {
|
||||||
CodeMP.loadLibrary(); //will only load it the first time
|
CodeMP.connect(url);
|
||||||
CodeMPHandler.connect(url);
|
|
||||||
|
|
||||||
if(!silent) ActionUtil.notify(e,
|
if(!silent) ActionUtil.notify(e,
|
||||||
"Success", String.format("Connected to %s!", url));
|
"Success", String.format("Connected to %s!", url));
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.codemp.intellij.actions;
|
||||||
|
|
||||||
|
import com.codemp.intellij.CodeMP;
|
||||||
|
import com.codemp.intellij.util.ActionUtil;
|
||||||
|
import com.intellij.openapi.actionSystem.AnAction;
|
||||||
|
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class DisconnectAction extends AnAction {
|
||||||
|
public static void disconnect(AnActionEvent e, boolean silent) {
|
||||||
|
String url = CodeMP.getClient("disconnect").getUrl();
|
||||||
|
|
||||||
|
CodeMP.disconnect();
|
||||||
|
|
||||||
|
if(!silent) ActionUtil.notify(e,
|
||||||
|
"Success", String.format("Disconnected from %s!", url));
|
||||||
|
CodeMP.LOGGER.debug("Connected to {}!", url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||||
|
try {
|
||||||
|
disconnect(e, false);
|
||||||
|
} catch(Exception ex) {
|
||||||
|
ActionUtil.notifyError(e, "Failed to disconnect!", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,8 +2,6 @@ package com.codemp.intellij.actions.buffer;
|
||||||
|
|
||||||
import com.codemp.intellij.CodeMP;
|
import com.codemp.intellij.CodeMP;
|
||||||
import com.codemp.intellij.jni.BufferHandler;
|
import com.codemp.intellij.jni.BufferHandler;
|
||||||
import com.codemp.intellij.jni.CodeMPHandler;
|
|
||||||
import com.codemp.intellij.task.TaskManager;
|
|
||||||
import com.codemp.intellij.util.ActionUtil;
|
import com.codemp.intellij.util.ActionUtil;
|
||||||
import com.intellij.openapi.actionSystem.AnAction;
|
import com.intellij.openapi.actionSystem.AnAction;
|
||||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||||
|
@ -21,7 +19,7 @@ public class BufferAttachAction extends AnAction {
|
||||||
//TODO "get" the Editor corresponding to buffer, for now use the current one
|
//TODO "get" the Editor corresponding to buffer, for now use the current one
|
||||||
Editor editor = ActionUtil.getCurrentEditor(e);
|
Editor editor = ActionUtil.getCurrentEditor(e);
|
||||||
|
|
||||||
TaskManager
|
WorkspaceManager
|
||||||
.getOrCreateBufferTask(ActionUtil.getCurrentProject(e))
|
.getOrCreateBufferTask(ActionUtil.getCurrentProject(e))
|
||||||
.registerListener(bufferHandler, editor);
|
.registerListener(bufferHandler, editor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package com.codemp.intellij.actions.buffer;
|
package com.codemp.intellij.actions.buffer;
|
||||||
|
|
||||||
import com.codemp.intellij.CodeMP;
|
import com.codemp.intellij.CodeMP;
|
||||||
import com.codemp.intellij.jni.CodeMPHandler;
|
|
||||||
import com.codemp.intellij.util.ActionUtil;
|
import com.codemp.intellij.util.ActionUtil;
|
||||||
import com.intellij.openapi.actionSystem.AnAction;
|
import com.intellij.openapi.actionSystem.AnAction;
|
||||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package com.codemp.intellij.actions.buffer;
|
package com.codemp.intellij.actions.buffer;
|
||||||
|
|
||||||
import com.codemp.intellij.CodeMP;
|
import com.codemp.intellij.CodeMP;
|
||||||
import com.codemp.intellij.jni.CodeMPHandler;
|
|
||||||
import com.codemp.intellij.util.ActionUtil;
|
import com.codemp.intellij.util.ActionUtil;
|
||||||
import com.intellij.openapi.actionSystem.AnAction;
|
import com.intellij.openapi.actionSystem.AnAction;
|
||||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||||
|
|
|
@ -2,9 +2,7 @@ package com.codemp.intellij.actions.buffer;
|
||||||
|
|
||||||
import com.codemp.intellij.CodeMP;
|
import com.codemp.intellij.CodeMP;
|
||||||
import com.codemp.intellij.exceptions.ide.BufferDetachException;
|
import com.codemp.intellij.exceptions.ide.BufferDetachException;
|
||||||
import com.codemp.intellij.jni.CodeMPHandler;
|
|
||||||
import com.codemp.intellij.task.BufferEventAwaiterTask;
|
import com.codemp.intellij.task.BufferEventAwaiterTask;
|
||||||
import com.codemp.intellij.task.TaskManager;
|
|
||||||
import com.codemp.intellij.util.ActionUtil;
|
import com.codemp.intellij.util.ActionUtil;
|
||||||
import com.intellij.openapi.actionSystem.AnAction;
|
import com.intellij.openapi.actionSystem.AnAction;
|
||||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||||
|
@ -17,7 +15,6 @@ public class BufferDetachAction extends AnAction {
|
||||||
if(!res) throw new BufferDetachException(buffer);
|
if(!res) throw new BufferDetachException(buffer);
|
||||||
|
|
||||||
CodeMP.ACTIVE_BUFFERS.remove(buffer);
|
CodeMP.ACTIVE_BUFFERS.remove(buffer);
|
||||||
BufferEventAwaiterTask task = TaskManager.getBufferTask();
|
|
||||||
if(task != null) {
|
if(task != null) {
|
||||||
task.unregisterListener(buffer);
|
task.unregisterListener(buffer);
|
||||||
if(!silent) ActionUtil.notify(e, "Success",
|
if(!silent) ActionUtil.notify(e, "Success",
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
package com.codemp.intellij.actions.buffer;
|
package com.codemp.intellij.actions.buffer;
|
||||||
|
|
||||||
import com.codemp.intellij.CodeMP;
|
import com.codemp.intellij.CodeMP;
|
||||||
import com.codemp.intellij.jni.CodeMPHandler;
|
|
||||||
import com.codemp.intellij.task.TaskManager;
|
|
||||||
import com.codemp.intellij.util.ActionUtil;
|
import com.codemp.intellij.util.ActionUtil;
|
||||||
import com.intellij.openapi.actionSystem.AnAction;
|
import com.intellij.openapi.actionSystem.AnAction;
|
||||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||||
import com.intellij.openapi.application.ApplicationManager;
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
import com.intellij.openapi.command.CommandProcessor;
|
import com.intellij.openapi.command.CommandProcessor;
|
||||||
import com.intellij.openapi.editor.Editor;
|
import com.intellij.openapi.editor.Editor;
|
||||||
import com.intellij.openapi.ui.Messages;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class BufferSyncAction extends AnAction {
|
public class BufferSyncAction extends AnAction {
|
||||||
|
|
|
@ -1,47 +1,39 @@
|
||||||
package com.codemp.intellij.actions.workspace;
|
package com.codemp.intellij.actions.workspace;
|
||||||
|
|
||||||
import com.codemp.intellij.CodeMP;
|
import com.codemp.intellij.CodeMP;
|
||||||
import com.codemp.intellij.jni.CodeMPHandler;
|
|
||||||
import com.codemp.intellij.jni.CursorHandler;
|
|
||||||
import com.codemp.intellij.listeners.CursorEventListener;
|
|
||||||
import com.codemp.intellij.task.CursorEventAwaiterTask;
|
|
||||||
import com.codemp.intellij.task.TaskManager;
|
|
||||||
import com.codemp.intellij.util.ActionUtil;
|
import com.codemp.intellij.util.ActionUtil;
|
||||||
|
import com.codemp.intellij.workspace.Workspace;
|
||||||
import com.intellij.openapi.actionSystem.AnAction;
|
import com.intellij.openapi.actionSystem.AnAction;
|
||||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||||
import com.intellij.openapi.editor.EditorFactory;
|
|
||||||
import com.intellij.openapi.ui.Messages;
|
import com.intellij.openapi.ui.Messages;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class WorkspaceJoinAction extends AnAction {
|
public class WorkspaceJoinAction extends AnAction {
|
||||||
public static void join(AnActionEvent e, String workspace, boolean silent) {
|
public static void join(AnActionEvent e, String workspaceId, boolean silent) {
|
||||||
CursorHandler cursorHandler = CodeMPHandler.join(workspace);
|
CodeMP.ACTIVE_WORKSPACES.put(workspaceId, new Workspace(
|
||||||
|
workspaceId, CodeMP.getClient("join workspace"),
|
||||||
|
false, e.getProject() //TODO: implement remote projects
|
||||||
|
));
|
||||||
|
|
||||||
if(!silent) ActionUtil.notify(e,
|
if(!silent) ActionUtil.notify(e,
|
||||||
"Success", String.format("Joined workspace %s!", workspace));
|
"Success", String.format("Joined workspace %s!", workspaceId));
|
||||||
CodeMP.LOGGER.debug("Joined workspace {}!", workspace);
|
CodeMP.LOGGER.debug("Joined workspace {}!", workspaceId);
|
||||||
|
|
||||||
CursorEventAwaiterTask task = TaskManager
|
|
||||||
.getOrCreateCursorTask(ActionUtil.getCurrentProject(e), cursorHandler);
|
|
||||||
|
|
||||||
EditorFactory.getInstance()
|
|
||||||
.getEventMulticaster()
|
|
||||||
.addCaretListener(new CursorEventListener(cursorHandler), task);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||||
String session = Messages.showInputDialog(
|
String workspaceId = Messages.showInputDialog(
|
||||||
"Session to connect to:",
|
"Workspace to connect to:",
|
||||||
"CodeMP Join",
|
"CodeMP Join",
|
||||||
Messages.getQuestionIcon());
|
Messages.getQuestionIcon());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
join(e, session, false);
|
join(e, workspaceId, false);
|
||||||
} catch(Exception ex) {
|
} catch(Exception ex) {
|
||||||
ActionUtil.notifyError(e, String.format(
|
ActionUtil.notifyError(e, String.format(
|
||||||
"Failed to join session %s!",
|
"Failed to join workspace %s!",
|
||||||
session), ex);
|
workspaceId), ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,33 @@
|
||||||
package com.codemp.intellij.actions.workspace;
|
package com.codemp.intellij.actions.workspace;
|
||||||
|
|
||||||
import com.codemp.intellij.CodeMP;
|
import com.codemp.intellij.CodeMP;
|
||||||
import com.codemp.intellij.jni.CodeMPHandler;
|
|
||||||
import com.codemp.intellij.util.ActionUtil;
|
import com.codemp.intellij.util.ActionUtil;
|
||||||
|
import com.codemp.intellij.workspace.Workspace;
|
||||||
import com.intellij.openapi.actionSystem.AnAction;
|
import com.intellij.openapi.actionSystem.AnAction;
|
||||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||||
import com.intellij.openapi.ui.Messages;
|
import com.intellij.openapi.ui.Messages;
|
||||||
|
import com.intellij.openapi.util.Disposer;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class WorkspaceLeaveAction extends AnAction {
|
public class WorkspaceLeaveAction extends AnAction {
|
||||||
public static void leave(AnActionEvent e, boolean silent) {
|
public static void leave(AnActionEvent e, String workspaceId, boolean silent) {
|
||||||
CodeMPHandler.leaveWorkspace();
|
CodeMP.getClient("leave workspace")
|
||||||
|
.leaveWorkspace(workspaceId);
|
||||||
|
Disposer.dispose(CodeMP.ACTIVE_WORKSPACES.remove(workspaceId));
|
||||||
|
|
||||||
if(!silent) ActionUtil.notify(e, "Success", "Left workspace");
|
if(!silent) ActionUtil.notify(e, "Success", String.format("Left workspace %s!", workspaceId));
|
||||||
CodeMP.LOGGER.debug("Left workspace!");
|
CodeMP.LOGGER.debug("Left workspace!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||||
|
String workspaceId = Messages.showInputDialog(
|
||||||
|
"Workspace to leave:",
|
||||||
|
"CodeMP Workspace Leave",
|
||||||
|
Messages.getQuestionIcon());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
leave(e, false);
|
leave(e, workspaceId, false);
|
||||||
} catch(Exception ex) {
|
} catch(Exception ex) {
|
||||||
ActionUtil.notifyError(e, "Failed to leave workspace!", ex);
|
ActionUtil.notifyError(e, "Failed to leave workspace!", ex);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.codemp.intellij.exceptions.ide;
|
||||||
|
|
||||||
|
import com.codemp.intellij.exceptions.CodeMPException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fired when trying to access the CodeMP client without first connecting
|
||||||
|
* to a server.
|
||||||
|
*/
|
||||||
|
public class NotConnectedException extends CodeMPException {
|
||||||
|
|
||||||
|
public NotConnectedException(String service) {
|
||||||
|
super(String.format("Failed to %s, you are not connected to a server!", service));
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,18 +2,23 @@ package com.codemp.intellij.listeners;
|
||||||
|
|
||||||
import com.codemp.intellij.CodeMP;
|
import com.codemp.intellij.CodeMP;
|
||||||
import com.codemp.intellij.jni.CursorHandler;
|
import com.codemp.intellij.jni.CursorHandler;
|
||||||
|
import com.codemp.intellij.task.CursorEventAwaiterTask;
|
||||||
|
import com.codemp.intellij.util.FileUtil;
|
||||||
|
import com.codemp.intellij.workspace.Workspace;
|
||||||
import com.intellij.openapi.editor.Caret;
|
import com.intellij.openapi.editor.Caret;
|
||||||
|
import com.intellij.openapi.editor.Editor;
|
||||||
import com.intellij.openapi.editor.VisualPosition;
|
import com.intellij.openapi.editor.VisualPosition;
|
||||||
import com.intellij.openapi.editor.event.CaretEvent;
|
import com.intellij.openapi.editor.event.CaretEvent;
|
||||||
import com.intellij.openapi.editor.event.CaretListener;
|
import com.intellij.openapi.editor.event.CaretListener;
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class CursorEventListener implements CaretListener {
|
public class CursorEventListener implements CaretListener {
|
||||||
|
|
||||||
private final CursorHandler cursorHandler;
|
private final CursorHandler handler;
|
||||||
|
|
||||||
public CursorEventListener(CursorHandler cursorHandler) {
|
public CursorEventListener(CursorHandler handler) {
|
||||||
this.cursorHandler = cursorHandler;
|
this.handler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -26,8 +31,10 @@ public class CursorEventListener implements CaretListener {
|
||||||
VisualPosition endPos = caret.getSelectionEndPosition();
|
VisualPosition endPos = caret.getSelectionEndPosition();
|
||||||
CodeMP.LOGGER.debug("Caret moved from {}x {}y to {}x {}y",
|
CodeMP.LOGGER.debug("Caret moved from {}x {}y to {}x {}y",
|
||||||
startPos.line, startPos.column, endPos.line, endPos.column);
|
startPos.line, startPos.column, endPos.line, endPos.column);
|
||||||
this.cursorHandler.send(
|
|
||||||
CodeMP.ACTIVE_BUFFERS_REVERSE.get(event.getEditor()),
|
Editor editor = event.getEditor();
|
||||||
|
this.handler.send(
|
||||||
|
FileUtil.getRelativePath(editor.getProject(), editor.getVirtualFile()),
|
||||||
startPos.line, startPos.column,
|
startPos.line, startPos.column,
|
||||||
endPos.line, endPos.column
|
endPos.line, endPos.column
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package com.codemp.intellij.listeners;
|
||||||
|
|
||||||
|
import com.codemp.intellij.jni.WorkspaceHandler;
|
||||||
|
import com.codemp.intellij.task.BufferEventAwaiterTask;
|
||||||
|
import com.codemp.intellij.util.FileUtil;
|
||||||
|
import com.codemp.intellij.workspace.Workspace;
|
||||||
|
import com.intellij.openapi.Disposable;
|
||||||
|
import com.intellij.openapi.editor.Document;
|
||||||
|
import com.intellij.openapi.editor.Editor;
|
||||||
|
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||||
|
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
|
||||||
|
import com.intellij.openapi.fileEditor.TextEditor;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.openapi.util.Disposer;
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class WorkspaceFileClosedListener implements FileEditorManagerListener.Before {
|
||||||
|
private final WorkspaceHandler handler;
|
||||||
|
private final BufferEventAwaiterTask task;
|
||||||
|
|
||||||
|
public WorkspaceFileClosedListener(WorkspaceHandler handler, BufferEventAwaiterTask task) {
|
||||||
|
this.handler = handler;
|
||||||
|
this.task = task;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeFileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
|
||||||
|
String path = FileUtil.getRelativePath(source.getProject(), file);
|
||||||
|
if(path == null) return;
|
||||||
|
|
||||||
|
Disposable disp = this.task.activeBuffers.remove(path);
|
||||||
|
if(disp == null) return;
|
||||||
|
|
||||||
|
this.handler.detachFromBuffer(path);
|
||||||
|
Disposer.dispose(disp);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package com.codemp.intellij.listeners;
|
||||||
|
|
||||||
|
import com.codemp.intellij.jni.BufferHandler;
|
||||||
|
import com.codemp.intellij.jni.WorkspaceHandler;
|
||||||
|
import com.codemp.intellij.task.BufferEventAwaiterTask;
|
||||||
|
import com.codemp.intellij.util.FileUtil;
|
||||||
|
import com.intellij.openapi.Disposable;
|
||||||
|
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||||
|
import com.intellij.openapi.fileEditor.FileOpenedSyncListener;
|
||||||
|
import com.intellij.openapi.fileEditor.TextEditor;
|
||||||
|
import com.intellij.openapi.fileEditor.ex.FileEditorWithProvider;
|
||||||
|
import com.intellij.openapi.util.Disposer;
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class WorkspaceFileOpenedListener implements FileOpenedSyncListener {
|
||||||
|
|
||||||
|
private final WorkspaceHandler handler;
|
||||||
|
private final BufferEventAwaiterTask task;
|
||||||
|
|
||||||
|
public WorkspaceFileOpenedListener(WorkspaceHandler handler, BufferEventAwaiterTask task) {
|
||||||
|
this.handler = handler;
|
||||||
|
this.task = task;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fileOpenedSync(@NotNull FileEditorManager source,
|
||||||
|
@NotNull VirtualFile file,
|
||||||
|
@NotNull List<FileEditorWithProvider> editorsWithProviders) {
|
||||||
|
editorsWithProviders
|
||||||
|
.stream()
|
||||||
|
.map(FileEditorWithProvider::component1)
|
||||||
|
.filter(fe -> fe instanceof TextEditor)
|
||||||
|
.map(fe -> (TextEditor) fe)
|
||||||
|
.map(TextEditor::getEditor)
|
||||||
|
.forEach(editor -> {
|
||||||
|
String path = FileUtil.getRelativePath(editor.getProject(), file);
|
||||||
|
if(path == null) return;
|
||||||
|
|
||||||
|
BufferHandler bufferHandler = this.handler.attachToBuffer(path);
|
||||||
|
Disposable disp = Disposer.newDisposable(String.format("codemp-buffer-%s", path));
|
||||||
|
editor.getDocument().addDocumentListener(new BufferEventListener(bufferHandler), disp);
|
||||||
|
|
||||||
|
editor.getDocument().setText(""); //empty it so we can start receiving
|
||||||
|
this.task.activeBuffers.put(path, disp);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,10 +4,10 @@ import com.codemp.intellij.CodeMP;
|
||||||
import com.codemp.intellij.exceptions.lib.ChannelException;
|
import com.codemp.intellij.exceptions.lib.ChannelException;
|
||||||
import com.codemp.intellij.exceptions.lib.DeadlockedException;
|
import com.codemp.intellij.exceptions.lib.DeadlockedException;
|
||||||
import com.codemp.intellij.jni.BufferHandler;
|
import com.codemp.intellij.jni.BufferHandler;
|
||||||
import com.codemp.intellij.jni.CodeMPHandler;
|
|
||||||
import com.codemp.intellij.jni.StringVec;
|
import com.codemp.intellij.jni.StringVec;
|
||||||
import com.codemp.intellij.jni.TextChangeWrapper;
|
import com.codemp.intellij.jni.TextChangeWrapper;
|
||||||
import com.codemp.intellij.listeners.BufferEventListener;
|
import com.codemp.intellij.jni.WorkspaceHandler;
|
||||||
|
import com.codemp.intellij.util.FileUtil;
|
||||||
import com.intellij.openapi.Disposable;
|
import com.intellij.openapi.Disposable;
|
||||||
import com.intellij.openapi.application.ApplicationManager;
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
import com.intellij.openapi.command.CommandProcessor;
|
import com.intellij.openapi.command.CommandProcessor;
|
||||||
|
@ -22,44 +22,23 @@ import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
public class BufferEventAwaiterTask extends Task.Backgroundable implements Disposable {
|
public class BufferEventAwaiterTask extends Task.Backgroundable implements Disposable {
|
||||||
private final Map<String, Disposable> bufferListeners = new ConcurrentHashMap<>();
|
public final Map<String, Disposable> activeBuffers;
|
||||||
|
private final WorkspaceHandler handler;
|
||||||
public BufferEventAwaiterTask(@NotNull Project project) {
|
public BufferEventAwaiterTask(@NotNull Project project, @NotNull WorkspaceHandler handler) {
|
||||||
super(project, "Awaiting CodeMP buffer events", false);
|
super(project, "Awaiting CodeMP buffer events", false);
|
||||||
}
|
this.activeBuffers = new ConcurrentHashMap<>();
|
||||||
|
this.handler = handler;
|
||||||
public void registerListener(BufferHandler handler, Editor editor) {
|
|
||||||
CodeMP.ACTIVE_BUFFERS.put(handler.getName(), editor); //mark as active
|
|
||||||
CodeMP.ACTIVE_BUFFERS_REVERSE.put(editor, handler.getName());
|
|
||||||
|
|
||||||
Disposable disposable = Disposer
|
|
||||||
.newDisposable(this, String.format("codemp-buffer-%s", handler.getName()));
|
|
||||||
|
|
||||||
editor.getDocument()
|
|
||||||
.addDocumentListener(new BufferEventListener(handler), disposable);
|
|
||||||
|
|
||||||
bufferListeners.put(handler.getName(), disposable);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unregisterListener(String name) {
|
|
||||||
CodeMP.ACTIVE_BUFFERS_REVERSE.remove(CodeMP.ACTIVE_BUFFERS.remove(name));
|
|
||||||
Disposable listener = this.bufferListeners.remove(name);
|
|
||||||
if(listener != null)
|
|
||||||
listener.dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {}
|
@SuppressWarnings("InfiniteLoopStatement")
|
||||||
|
|
||||||
@Override
|
|
||||||
@SuppressWarnings({"InfiniteLoopStatement", "UnstableApiUsage"})
|
|
||||||
public void run(@NotNull ProgressIndicator indicator) {
|
public void run(@NotNull ProgressIndicator indicator) {
|
||||||
try {
|
try {
|
||||||
while(true) {
|
while(true) {
|
||||||
StringVec buffers = new StringVec(); //jni moment
|
StringVec buffers = new StringVec(); //jni moment
|
||||||
CodeMP.ACTIVE_BUFFERS.keySet().forEach(buffers::push);
|
this.activeBuffers.keySet().forEach(buffers::push);
|
||||||
|
|
||||||
Optional<BufferHandler> bufferOptional = CodeMPHandler.selectBuffer(buffers, 100L);
|
Optional<BufferHandler> bufferOptional = this.handler.selectBuffer(buffers, 100L);
|
||||||
if(bufferOptional.isEmpty())
|
if(bufferOptional.isEmpty())
|
||||||
continue;
|
continue;
|
||||||
BufferHandler buffer = bufferOptional.get();
|
BufferHandler buffer = bufferOptional.get();
|
||||||
|
@ -81,7 +60,7 @@ public class BufferEventAwaiterTask extends Task.Backgroundable implements Dispo
|
||||||
changeList.add(change);
|
changeList.add(change);
|
||||||
}
|
}
|
||||||
|
|
||||||
Editor bufferEditor = CodeMP.ACTIVE_BUFFERS.get(buffer.getName());
|
Editor bufferEditor = FileUtil.getActiveEditorByPath(this.myProject, buffer.getName());
|
||||||
ApplicationManager.getApplication().invokeLaterOnWriteThread(() ->
|
ApplicationManager.getApplication().invokeLaterOnWriteThread(() ->
|
||||||
ApplicationManager.getApplication().runWriteAction(() ->
|
ApplicationManager.getApplication().runWriteAction(() ->
|
||||||
CommandProcessor.getInstance().executeCommand(
|
CommandProcessor.getInstance().executeCommand(
|
||||||
|
@ -96,8 +75,14 @@ public class BufferEventAwaiterTask extends Task.Backgroundable implements Dispo
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
} catch(ChannelException ex) { //exited
|
} catch(ChannelException ex) { //exited
|
||||||
TaskManager.nullBufferTask();
|
//TODO handle stop
|
||||||
Disposer.dispose(this); //stopped
|
Disposer.dispose(this); //stopped
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
this.activeBuffers.values().forEach(Disposable::dispose);
|
||||||
|
this.activeBuffers.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import com.codemp.intellij.exceptions.lib.ChannelException;
|
||||||
import com.codemp.intellij.jni.CursorEventWrapper;
|
import com.codemp.intellij.jni.CursorEventWrapper;
|
||||||
import com.codemp.intellij.jni.CursorHandler;
|
import com.codemp.intellij.jni.CursorHandler;
|
||||||
import com.codemp.intellij.util.ColorUtil;
|
import com.codemp.intellij.util.ColorUtil;
|
||||||
|
import com.codemp.intellij.util.FileUtil;
|
||||||
import com.intellij.openapi.Disposable;
|
import com.intellij.openapi.Disposable;
|
||||||
import com.intellij.openapi.application.ApplicationManager;
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
import com.intellij.openapi.editor.Editor;
|
import com.intellij.openapi.editor.Editor;
|
||||||
|
@ -15,7 +16,6 @@ import com.intellij.openapi.editor.markup.TextAttributes;
|
||||||
import com.intellij.openapi.progress.ProgressIndicator;
|
import com.intellij.openapi.progress.ProgressIndicator;
|
||||||
import com.intellij.openapi.progress.Task;
|
import com.intellij.openapi.progress.Task;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.openapi.util.Disposer;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
@ -33,17 +33,13 @@ public class CursorEventAwaiterTask extends Task.Backgroundable implements Dispo
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void dispose() {}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("InfiniteLoopStatement")
|
@SuppressWarnings("InfiniteLoopStatement")
|
||||||
public void run(@NotNull ProgressIndicator indicator) {
|
public void run(@NotNull ProgressIndicator indicator) {
|
||||||
assert myProject != null; //will never fail
|
|
||||||
try {
|
try {
|
||||||
while(true) {
|
while(true) {
|
||||||
CursorEventWrapper event = handler.recv();
|
CursorEventWrapper event = this.handler.recv();
|
||||||
Editor editor = CodeMP.ACTIVE_BUFFERS.get(event.getBuffer());
|
Editor editor = FileUtil.getActiveEditorByPath(this.myProject, event.getBuffer());
|
||||||
if(editor == null)
|
if(editor == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -77,7 +73,7 @@ public class CursorEventAwaiterTask extends Task.Backgroundable implements Dispo
|
||||||
HighlighterLayer.SELECTION,
|
HighlighterLayer.SELECTION,
|
||||||
new TextAttributes(
|
new TextAttributes(
|
||||||
null,
|
null,
|
||||||
ColorUtil.colorFromUsername(event.getUser()),
|
ColorUtil.hashColor(event.getUser()),
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
Font.PLAIN
|
Font.PLAIN
|
||||||
|
@ -90,9 +86,12 @@ public class CursorEventAwaiterTask extends Task.Backgroundable implements Dispo
|
||||||
} catch(IndexOutOfBoundsException ignored) {}
|
} catch(IndexOutOfBoundsException ignored) {}
|
||||||
}
|
}
|
||||||
} catch(ChannelException ex) { //exited
|
} catch(ChannelException ex) { //exited
|
||||||
this.highlighterMap.forEach((s, r) -> r.dispose());
|
this.run(indicator);
|
||||||
TaskManager.nullCursorTask();
|
|
||||||
Disposer.dispose(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
this.highlighterMap.forEach((s, r) -> r.dispose());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
package com.codemp.intellij.task;
|
|
||||||
|
|
||||||
import com.codemp.intellij.jni.CursorHandler;
|
|
||||||
import com.intellij.openapi.progress.ProgressManager;
|
|
||||||
import com.intellij.openapi.project.Project;
|
|
||||||
|
|
||||||
public class TaskManager {
|
|
||||||
private static CursorEventAwaiterTask cursorTask = null;
|
|
||||||
|
|
||||||
//TODO in the future joining a workspace will give you a project matching remote
|
|
||||||
public static CursorEventAwaiterTask getOrCreateCursorTask(Project project, CursorHandler handler) {
|
|
||||||
if(cursorTask != null)
|
|
||||||
return cursorTask;
|
|
||||||
cursorTask = new CursorEventAwaiterTask(project, handler);
|
|
||||||
ProgressManager.getInstance().run(cursorTask);
|
|
||||||
return cursorTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void nullCursorTask() {
|
|
||||||
cursorTask = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static BufferEventAwaiterTask bufferTask = null;
|
|
||||||
|
|
||||||
public static BufferEventAwaiterTask getBufferTask() {
|
|
||||||
return bufferTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BufferEventAwaiterTask getOrCreateBufferTask(Project project) {
|
|
||||||
if(bufferTask != null)
|
|
||||||
return bufferTask;
|
|
||||||
bufferTask = new BufferEventAwaiterTask(project);
|
|
||||||
ProgressManager.getInstance().run(bufferTask);
|
|
||||||
return bufferTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void nullBufferTask() {
|
|
||||||
bufferTask = null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,12 +5,9 @@ import com.intellij.ui.JBColor;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
|
||||||
public class ColorUtil {
|
public class ColorUtil {
|
||||||
public static JBColor colorFromUsername(String username) {
|
public static JBColor hashColor(String username) {
|
||||||
int hash = username.hashCode();
|
int hash = username.hashCode();
|
||||||
|
|
||||||
@SuppressWarnings("all")
|
|
||||||
Color hashColor = new Color(hash | (0xFF << 24));
|
Color hashColor = new Color(hash | (0xFF << 24));
|
||||||
|
|
||||||
return new JBColor(hashColor, hashColor.darker());
|
return new JBColor(hashColor, hashColor.darker());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
34
src/main/java/com/codemp/intellij/util/FileUtil.java
Normal file
34
src/main/java/com/codemp/intellij/util/FileUtil.java
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
package com.codemp.intellij.util;
|
||||||
|
|
||||||
|
import com.intellij.openapi.editor.Editor;
|
||||||
|
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||||
|
import com.intellij.openapi.fileEditor.TextEditor;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.openapi.roots.ProjectRootManager;
|
||||||
|
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class FileUtil {
|
||||||
|
public static String getRelativePath(Project project, VirtualFile vf) {
|
||||||
|
if(ProjectRootManager.getInstance(project).getFileIndex().isInContent(vf))
|
||||||
|
return Arrays.stream(ProjectRootManager.getInstance(project).getContentRoots())
|
||||||
|
.filter(r -> VfsUtilCore.isAncestor(r, vf, false))
|
||||||
|
.findAny()
|
||||||
|
.map(root -> VfsUtilCore.getRelativePath(vf, root))
|
||||||
|
.orElse(null);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Editor getActiveEditorByPath(Project project, String path) {
|
||||||
|
return Arrays.stream(FileEditorManager.getInstance(project).getAllEditors())
|
||||||
|
.filter(fe -> fe instanceof TextEditor)
|
||||||
|
.map(fe -> {
|
||||||
|
TextEditor te = (TextEditor) fe;
|
||||||
|
return te.getEditor();
|
||||||
|
}).filter(editor -> path.equals(FileUtil.getRelativePath(editor.getProject(), editor.getVirtualFile())))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
}
|
60
src/main/java/com/codemp/intellij/workspace/Workspace.java
Normal file
60
src/main/java/com/codemp/intellij/workspace/Workspace.java
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
package com.codemp.intellij.workspace;
|
||||||
|
|
||||||
|
import com.codemp.intellij.jni.ClientHandler;
|
||||||
|
import com.codemp.intellij.jni.WorkspaceHandler;
|
||||||
|
import com.codemp.intellij.listeners.*;
|
||||||
|
import com.codemp.intellij.task.BufferEventAwaiterTask;
|
||||||
|
import com.codemp.intellij.task.CursorEventAwaiterTask;
|
||||||
|
import com.intellij.openapi.Disposable;
|
||||||
|
import com.intellij.openapi.editor.EditorFactory;
|
||||||
|
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
|
||||||
|
import com.intellij.openapi.fileEditor.FileOpenedSyncListener;
|
||||||
|
import com.intellij.openapi.progress.ProgressManager;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.util.messages.MessageBusConnection;
|
||||||
|
|
||||||
|
public class Workspace implements Disposable {
|
||||||
|
public final String id;
|
||||||
|
public final String url;
|
||||||
|
public final boolean isRemote;
|
||||||
|
public final WorkspaceHandler handler;
|
||||||
|
public final Project project;
|
||||||
|
public final BufferEventAwaiterTask bufferTask;
|
||||||
|
public final CursorEventAwaiterTask cursorTask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The constructor, that will also take care of creating the tasks and listeners associated with it.
|
||||||
|
* @param id unique id of the workspace on the server
|
||||||
|
* @param client the {@link ClientHandler} to use
|
||||||
|
* @param isRemote whether the project is remote
|
||||||
|
* @param project the {@link Project} to use
|
||||||
|
*/
|
||||||
|
public Workspace(String id, ClientHandler client, boolean isRemote, Project project) {
|
||||||
|
this.id = id;
|
||||||
|
this.url = client.getUrl();
|
||||||
|
this.isRemote = isRemote;
|
||||||
|
this.handler = client.joinWorkspace(id);
|
||||||
|
this.project = project;
|
||||||
|
|
||||||
|
this.cursorTask = new CursorEventAwaiterTask(project, this.handler.getCursor());
|
||||||
|
ProgressManager.getInstance().run(this.cursorTask);
|
||||||
|
|
||||||
|
this.bufferTask = new BufferEventAwaiterTask(project, this.handler);
|
||||||
|
ProgressManager.getInstance().run(this.bufferTask);
|
||||||
|
|
||||||
|
// buffer listening
|
||||||
|
MessageBusConnection conn = this.project.getMessageBus().connect(this);
|
||||||
|
conn.subscribe(FileOpenedSyncListener.TOPIC,
|
||||||
|
new WorkspaceFileOpenedListener(this.handler, this.bufferTask));
|
||||||
|
conn.subscribe(FileEditorManagerListener.Before.FILE_EDITOR_MANAGER,
|
||||||
|
new WorkspaceFileClosedListener(this.handler, this.bufferTask));
|
||||||
|
|
||||||
|
// cursor listening
|
||||||
|
EditorFactory.getInstance()
|
||||||
|
.getEventMulticaster()
|
||||||
|
.addCaretListener(new CursorEventListener(this.handler.getCursor()), this.cursorTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {}
|
||||||
|
}
|
|
@ -11,7 +11,8 @@
|
||||||
<group id="codemp" text="CodeMP" popup="true">
|
<group id="codemp" text="CodeMP" popup="true">
|
||||||
<add-to-group group-id="ToolsMenu" anchor="first"/>
|
<add-to-group group-id="ToolsMenu" anchor="first"/>
|
||||||
<action id="codemp.fast-forward" class="com.codemp.intellij.actions.FastForwardAction" text="Just Hurry"/>
|
<action id="codemp.fast-forward" class="com.codemp.intellij.actions.FastForwardAction" text="Just Hurry"/>
|
||||||
<action id="codemp.connect" class="com.codemp.intellij.actions.ConnectAction" text="Connect..."/>
|
<action id="codemp.connect" class="com.codemp.intellij.actions.ConnectAction" text="Connect..."/>
|
||||||
|
<action id="codemp.connect" class="com.codemp.intellij.actions.DisconnectAction" text="Disconnect"/>
|
||||||
|
|
||||||
<group id="codemp.workspace" text="Workspace" popup="true">
|
<group id="codemp.workspace" text="Workspace" popup="true">
|
||||||
<action id="codemp.workspace.join" class="com.codemp.intellij.actions.workspace.WorkspaceJoinAction"
|
<action id="codemp.workspace.join" class="com.codemp.intellij.actions.workspace.WorkspaceJoinAction"
|
||||||
|
|
|
@ -19,16 +19,16 @@ lazy_static! {
|
||||||
|
|
||||||
#[generate_interface_doc]
|
#[generate_interface_doc]
|
||||||
/// the handler class that represent an instance of a CodeMP client
|
/// the handler class that represent an instance of a CodeMP client
|
||||||
struct CodeMPHandler {
|
struct ClientHandler {
|
||||||
client: CodempClient,
|
client: CodempClient,
|
||||||
url: String
|
url: String
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CodeMPHandler {
|
impl ClientHandler {
|
||||||
#[generate_interface(constructor)]
|
#[generate_interface(constructor)]
|
||||||
/// constructor required by flapigen, DO NOT CALL THIS
|
/// constructor required by flapigen, DO NOT CALL THIS
|
||||||
fn new(address: &str) -> CodeMPHandler {
|
fn new(address: &str) -> ClientHandler {
|
||||||
CodeMPHandler {
|
ClientHandler {
|
||||||
client: RT.block_on(CodempClient::new(address)).unwrap(),
|
client: RT.block_on(CodempClient::new(address)).unwrap(),
|
||||||
url: address.to_string()
|
url: address.to_string()
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ impl WorkspaceHandler {
|
||||||
|
|
||||||
#[generate_interface]
|
#[generate_interface]
|
||||||
/// attach to a buffer and get a [crate::BufferHandler] for it
|
/// attach to a buffer and get a [crate::BufferHandler] for it
|
||||||
fn attach_buffer(&mut self, path: &str) -> CodempResult<BufferHandler> {
|
fn attach_to_buffer(&mut self, path: &str) -> CodempResult<BufferHandler> {
|
||||||
RT.block_on(RT.block_on(self.workspace.write()).attach(path))
|
RT.block_on(RT.block_on(self.workspace.write()).attach(path))
|
||||||
.map(|buffer| BufferHandler { buffer })
|
.map(|buffer| BufferHandler { buffer })
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ impl WorkspaceHandler {
|
||||||
|
|
||||||
#[generate_interface]
|
#[generate_interface]
|
||||||
/// detach from a buffer
|
/// detach from a buffer
|
||||||
fn detach_buffer(&mut self, path: &str) -> bool {
|
fn detach_from_buffer(&mut self, path: &str) -> bool {
|
||||||
RT.block_on(self.workspace.write()).detach(path)
|
RT.block_on(self.workspace.write()).detach(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue