diff --git a/src/main/java/com/codemp/intellij/CodeMP.java b/src/main/java/com/codemp/intellij/CodeMP.java index 36e9312..6c270d5 100644 --- a/src/main/java/com/codemp/intellij/CodeMP.java +++ b/src/main/java/com/codemp/intellij/CodeMP.java @@ -1,15 +1,21 @@ package com.codemp.intellij; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.util.SystemInfo; import cz.adamh.utils.NativeUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; public class CodeMP { public static Logger LOGGER = LoggerFactory.getLogger(CodeMP.class); + public static Map ACTIVE_BUFFERS = new ConcurrentHashMap<>(); + public static Map ACTIVE_BUFFERS_REVERSE = new ConcurrentHashMap<>(); //TODO jank + private static boolean loadedLibrary = false; public static void loadLibrary() { if(!loadedLibrary) { diff --git a/src/main/java/com/codemp/intellij/actions/buffer/BufferAttachAction.java b/src/main/java/com/codemp/intellij/actions/buffer/BufferAttachAction.java index dea40da..c7a714c 100644 --- a/src/main/java/com/codemp/intellij/actions/buffer/BufferAttachAction.java +++ b/src/main/java/com/codemp/intellij/actions/buffer/BufferAttachAction.java @@ -3,72 +3,27 @@ package com.codemp.intellij.actions.buffer; import com.codemp.intellij.CodeMP; import com.codemp.intellij.jni.BufferHandler; import com.codemp.intellij.jni.CodeMPHandler; -import com.codemp.intellij.jni.TextChangeWrapper; -import com.codemp.intellij.listeners.BufferEventListener; +import com.codemp.intellij.task.TaskManager; import com.codemp.intellij.util.ActionUtil; -import com.codemp.intellij.util.DisposableRegistry; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.command.CommandProcessor; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.progress.Task; -import com.intellij.openapi.project.Project; +import com.intellij.openapi.editor.Editor; import com.intellij.openapi.ui.Messages; import org.jetbrains.annotations.NotNull; public class BufferAttachAction extends AnAction { - public static void attach(AnActionEvent e, String buffer, boolean silent) throws Exception { BufferHandler bufferHandler = CodeMPHandler.attach(buffer); if(!silent) Messages.showInfoMessage(String.format("Attached to buffer to %s!", buffer), "CodeMP Buffer Attach"); CodeMP.LOGGER.debug("Attached to buffer to {}!", buffer); - //register buffer change listener - //TODO "get" the Document corresponding to buffer, for now use the current one - BufferEventListener listener = new BufferEventListener(buffer); + //TODO "get" the Editor corresponding to buffer, for now use the current one + Editor editor = ActionUtil.getCurrentEditor(e); - Project project = ActionUtil.getCurrentProject(e); - Document document = ActionUtil.getCurrentEditor(e).getDocument(); - document.addDocumentListener(listener, DisposableRegistry.getOrCreate(String.format("codemp-buffer-%s", buffer))); - - ProgressManager.getInstance().run(new Task.Backgroundable(e.getProject(), "Awaiting CodeMP buffer events") { - @Override - @SuppressWarnings({"InfiniteLoopStatement", "UnstableApiUsage"}) - public void run(@NotNull ProgressIndicator indicator) { - try { - Thread.sleep(100); //tonioware - } catch(InterruptedException ex) { - throw new RuntimeException(ex); - } - - while(true) { - try { - TextChangeWrapper event = bufferHandler.recv(); - - CodeMP.LOGGER.debug("Received text change {} from offset {} to {}!", - event.getContent(), event.getStart(), event.getEnd()); - - ApplicationManager.getApplication().invokeLaterOnWriteThread(() -> { - ApplicationManager.getApplication().runWriteAction(() -> { - CommandProcessor.getInstance().executeCommand( - project, - () -> document.replaceString( - (int) event.getStart(), (int) event.getEnd(), event.getContent()), - "CodeMPBufferReceive", - "codemp-buffer-receive", //TODO: mark this with the name - document); - }); - }); - } catch(Exception ex) { - throw new RuntimeException(ex); - } - } - } - }); + TaskManager + .getOrCreateBufferTask(ActionUtil.getCurrentProject(e)) + .registerListener(bufferHandler, editor); } @Override diff --git a/src/main/java/com/codemp/intellij/actions/buffer/BufferDetachAction.java b/src/main/java/com/codemp/intellij/actions/buffer/BufferDetachAction.java index b91b308..0933c2a 100644 --- a/src/main/java/com/codemp/intellij/actions/buffer/BufferDetachAction.java +++ b/src/main/java/com/codemp/intellij/actions/buffer/BufferDetachAction.java @@ -3,7 +3,8 @@ package com.codemp.intellij.actions.buffer; import com.codemp.intellij.CodeMP; import com.codemp.intellij.exceptions.ide.BufferDetachException; import com.codemp.intellij.jni.CodeMPHandler; -import com.codemp.intellij.util.DisposableRegistry; +import com.codemp.intellij.task.BufferEventAwaiterTask; +import com.codemp.intellij.task.TaskManager; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.ui.Messages; @@ -14,12 +15,19 @@ public class BufferDetachAction extends AnAction { boolean res = CodeMPHandler.detach(buffer); if(!res) throw new BufferDetachException(buffer); - //dispose of listener's associated disposable - DisposableRegistry.disposeOf(String.format("codemp-buffer-%s", buffer)); - - if(!silent) Messages.showInfoMessage(String.format("Detached from buffer %s!", buffer), - "Detach from CodeMP Buffer" ); - CodeMP.LOGGER.debug("Detached from buffer {}!", buffer); + CodeMP.ACTIVE_BUFFERS.remove(buffer); + BufferEventAwaiterTask task = TaskManager.getBufferTask(); + if(task != null) { + task.unregisterListener(buffer); + if(!silent) Messages.showInfoMessage(String.format("Detached from buffer %s!", buffer), + "Detach from CodeMP Buffer"); + CodeMP.LOGGER.debug("Detached from buffer {}!", buffer); + } else { + if(!silent) Messages.showErrorDialog( + String.format("Failed to detach from %s: buffer event task was dead!", buffer), + "Detach from CodeMP Buffer"); + CodeMP.LOGGER.debug("Failed to detach from {}: buffer event task was dead!", buffer); + } } @Override diff --git a/src/main/java/com/codemp/intellij/actions/workspace/WorkspaceJoinAction.java b/src/main/java/com/codemp/intellij/actions/workspace/WorkspaceJoinAction.java index cfcef52..6066e22 100644 --- a/src/main/java/com/codemp/intellij/actions/workspace/WorkspaceJoinAction.java +++ b/src/main/java/com/codemp/intellij/actions/workspace/WorkspaceJoinAction.java @@ -2,57 +2,32 @@ package com.codemp.intellij.actions.workspace; import com.codemp.intellij.CodeMP; import com.codemp.intellij.jni.CodeMPHandler; -import com.codemp.intellij.jni.CursorEventWrapper; 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.ColorUtil; -import com.codemp.intellij.util.DisposableRegistry; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; -import com.intellij.openapi.editor.markup.HighlighterLayer; -import com.intellij.openapi.editor.markup.HighlighterTargetArea; -import com.intellij.openapi.editor.markup.RangeHighlighter; -import com.intellij.openapi.editor.markup.TextAttributes; -import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import org.jetbrains.annotations.NotNull; -import java.awt.*; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - public class WorkspaceJoinAction extends AnAction { - - private static final Map highlighterMap = new ConcurrentHashMap<>(); - public static void join(AnActionEvent e, String workspace, boolean silent) throws Exception { CursorHandler cursorHandler = CodeMPHandler.join(workspace); if(!silent) Messages.showInfoMessage(String.format("Joined workspace %s!", workspace), "CodeMP"); else CodeMP.LOGGER.debug("Joined workspace {}!", workspace); - Editor editor = ActionUtil.getCurrentEditor(e); - - CursorEventAwaiter task = new CursorEventAwaiter( - e.getProject(), - "Awaiting CodeMP cursor events", - cursorHandler, - editor - ); + CursorEventAwaiterTask task = TaskManager + .getOrCreateCursorTask(ActionUtil.getCurrentProject(e), cursorHandler); EditorFactory.getInstance() .getEventMulticaster() - .addCaretListener(new CursorEventListener(), - DisposableRegistry.getOrCreate(String.format("codemp-cursor-%s", workspace))); - - ProgressManager.getInstance().run(task); + .addCaretListener(new CursorEventListener(cursorHandler), task); } @Override @@ -72,68 +47,4 @@ public class WorkspaceJoinAction extends AnAction { "CodeMP Join"); } } - - //TODO this is janky as it shows a progress bar it doesn't use tbh - //implements disposable so i can use it as lifetime ig - private static class CursorEventAwaiter extends Task.Backgroundable { - - private final CursorHandler handler; - private final Editor editor; - - public CursorEventAwaiter(Project project, String title, CursorHandler handler, Editor editor) { - super(project, title); - this.handler = handler; - this.editor = editor; - } - - @Override - @SuppressWarnings("InfiniteLoopStatement") - public void run(@NotNull ProgressIndicator indicator) { - while(true) { - try { - CursorEventWrapper event = handler.recv(); - int startOffset = this.editor.getDocument().getLineStartOffset(event.getStartRow()) + event.getStartCol(); - int endOffset = this.editor.getDocument().getLineStartOffset(event.getEndRow()) + event.getEndCol(); - - ApplicationManager.getApplication().invokeLater(() -> { - try { - RangeHighlighter highlighter = highlighterMap.get(event.getUser()); - if(highlighter != null) - highlighter.dispose(); - - CodeMP.LOGGER.debug( - "Cursor moved by user {}! Start pos: {}x {}y; end pos: {}x {}y with buffer {}!", - event.getUser(), - event.getStartCol(), event.getStartCol(), - event.getEndRow(), event.getEndCol(), - event.getBuffer()); - - highlighterMap.put(event.getUser(), this.editor - .getMarkupModel() - .addRangeHighlighter( - startOffset, - endOffset, - HighlighterLayer.SELECTION, - new TextAttributes( - null, - ColorUtil.colorFromUsername(event.getUser()), - null, - null, - Font.PLAIN - ), HighlighterTargetArea.EXACT_RANGE - )); - } catch(IllegalArgumentException ex) { - //suppress if the cursor only exceeds length by one, it's probably just him adding something at EOF - if(endOffset - this.editor.getDocument().getTextLength() != 1) - throw ex; - } catch(Exception ex) { - throw new RuntimeException(ex); - } - }); - } catch(Exception ex) { - throw new RuntimeException(ex); - } - } - } - } } diff --git a/src/main/java/com/codemp/intellij/actions/workspace/WorkspaceLeaveAction.java b/src/main/java/com/codemp/intellij/actions/workspace/WorkspaceLeaveAction.java index 9122f4c..43d5d18 100644 --- a/src/main/java/com/codemp/intellij/actions/workspace/WorkspaceLeaveAction.java +++ b/src/main/java/com/codemp/intellij/actions/workspace/WorkspaceLeaveAction.java @@ -2,7 +2,6 @@ package com.codemp.intellij.actions.workspace; import com.codemp.intellij.CodeMP; import com.codemp.intellij.jni.CodeMPHandler; -import com.codemp.intellij.util.DisposableRegistry; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.ui.Messages; @@ -12,9 +11,6 @@ public class WorkspaceLeaveAction extends AnAction { public static void leave(boolean silent) throws Exception { CodeMPHandler.leaveWorkspace(); - //dispose of listener's associated disposable - DisposableRegistry.disposeOf("codemp-cursor"); - if(!silent) Messages.showInfoMessage("Left workspace!", "Detach from CodeMP Buffer" ); CodeMP.LOGGER.debug("Left workspace!"); diff --git a/src/main/java/com/codemp/intellij/listeners/BufferEventListener.java b/src/main/java/com/codemp/intellij/listeners/BufferEventListener.java index 5992dec..02b5515 100644 --- a/src/main/java/com/codemp/intellij/listeners/BufferEventListener.java +++ b/src/main/java/com/codemp/intellij/listeners/BufferEventListener.java @@ -1,5 +1,6 @@ package com.codemp.intellij.listeners; +import com.codemp.intellij.CodeMP; import com.codemp.intellij.jni.BufferHandler; import com.codemp.intellij.jni.CodeMPHandler; import com.intellij.openapi.command.CommandProcessor; @@ -9,14 +10,17 @@ import org.jetbrains.annotations.NotNull; public class BufferEventListener implements DocumentListener { - private final String bufferName; + private final BufferHandler bufferHandler; - public BufferEventListener(String bufferName) { - this.bufferName = bufferName; + public BufferEventListener(BufferHandler bufferHandler) { + this.bufferHandler = bufferHandler; } @Override public void documentChanged(@NotNull DocumentEvent event) { + CodeMP.LOGGER.debug("Changed {} to {} at offset {}", + event.getOldFragment(), event.getNewFragment(), event.getOffset()); + Object group = CommandProcessor.getInstance().getCurrentCommandGroupId(); if(group instanceof String groupString && groupString.startsWith("codemp-buffer-receive")) return; @@ -24,8 +28,7 @@ public class BufferEventListener implements DocumentListener { try { //TODO move actions break int changeOffset = event.getOffset(); CharSequence newFragment = event.getNewFragment(); - BufferHandler bufferHandler = CodeMPHandler.getBuffer(this.bufferName); - bufferHandler.send(changeOffset, + this.bufferHandler.send(changeOffset, changeOffset + event.getOldFragment().length(), newFragment.toString()); } catch(Exception e) { diff --git a/src/main/java/com/codemp/intellij/listeners/CursorEventListener.java b/src/main/java/com/codemp/intellij/listeners/CursorEventListener.java index a4999c8..269e699 100644 --- a/src/main/java/com/codemp/intellij/listeners/CursorEventListener.java +++ b/src/main/java/com/codemp/intellij/listeners/CursorEventListener.java @@ -2,6 +2,7 @@ package com.codemp.intellij.listeners; import com.codemp.intellij.CodeMP; import com.codemp.intellij.jni.CodeMPHandler; +import com.codemp.intellij.jni.CursorHandler; import com.intellij.openapi.editor.Caret; import com.intellij.openapi.editor.VisualPosition; import com.intellij.openapi.editor.event.CaretEvent; @@ -9,6 +10,13 @@ import com.intellij.openapi.editor.event.CaretListener; import org.jetbrains.annotations.NotNull; public class CursorEventListener implements CaretListener { + + private final CursorHandler cursorHandler; + + public CursorEventListener(CursorHandler cursorHandler) { + this.cursorHandler = cursorHandler; + } + @Override public void caretPositionChanged(@NotNull CaretEvent event) { Caret caret = event.getCaret(); @@ -20,8 +28,10 @@ public class CursorEventListener implements CaretListener { VisualPosition endPos = caret.getSelectionEndPosition(); CodeMP.LOGGER.debug("Caret moved from {}x {}y to {}x {}y", startPos.line, startPos.column, endPos.line, endPos.column); - CodeMPHandler.getCursor().send( - "", startPos.line, startPos.column, endPos.line, endPos.column + this.cursorHandler.send( + CodeMP.ACTIVE_BUFFERS_REVERSE.get(event.getEditor()), + startPos.line, startPos.column, + endPos.line, endPos.column ); } catch(Exception ex) { throw new RuntimeException(ex); diff --git a/src/main/java/com/codemp/intellij/task/BufferEventAwaiterTask.java b/src/main/java/com/codemp/intellij/task/BufferEventAwaiterTask.java new file mode 100644 index 0000000..e1f3091 --- /dev/null +++ b/src/main/java/com/codemp/intellij/task/BufferEventAwaiterTask.java @@ -0,0 +1,107 @@ +package com.codemp.intellij.task; + +import com.codemp.intellij.CodeMP; +import com.codemp.intellij.jni.BufferHandler; +import com.codemp.intellij.jni.CodeMPHandler; +import com.codemp.intellij.jni.TextChangeWrapper; +import com.codemp.intellij.listeners.BufferEventListener; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; +import org.jetbrains.annotations.NotNull; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +public class BufferEventAwaiterTask extends Task.Backgroundable implements Disposable { + private final Map bufferListeners = new ConcurrentHashMap<>(); + + public BufferEventAwaiterTask(@NotNull Project project) { + super(project, "Awaiting CodeMP buffer events", false); + } + + 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) { + Disposable listener = this.bufferListeners.remove(name); + if(listener != null) + listener.dispose(); + } + + @Override + public void dispose() {} + + @Override + @SuppressWarnings({"InfiniteLoopStatement", "UnstableApiUsage"}) + public void run(@NotNull ProgressIndicator indicator) { + try { + Thread.sleep(1000); //tonioware + } catch(InterruptedException ex) { + throw new RuntimeException(ex); + } + + try { + while(true) { + try { + String buffer = CodeMPHandler.selectBuffer(); + BufferHandler handler = CodeMPHandler.getBuffer(buffer); + + List changeList = new ArrayList<>(); + while(true) { + Optional changeOptional; + try { + changeOptional = handler.tryRecv(); + } catch(Exception e) { + CodeMP.LOGGER.error(e.getMessage()); + if(e.getMessage().equals("Error: deadlocked! (safe to retry)")) + continue; + else throw e; + } + if(changeOptional.isEmpty()) + break; + TextChangeWrapper change = changeOptional.get(); + CodeMP.LOGGER.debug("Received text change {} from offset {} to {}!", + change.getContent(), change.getStart(), change.getEnd()); + changeList.add(change); + } + + Editor bufferEditor = CodeMP.ACTIVE_BUFFERS.get(buffer); + + ApplicationManager.getApplication().invokeLaterOnWriteThread(() -> + ApplicationManager.getApplication().runWriteAction(() -> + CommandProcessor.getInstance().executeCommand( + this.myProject, + () -> changeList.forEach((change) -> + bufferEditor.getDocument().replaceString( + (int) change.getStart(), (int) change.getEnd(), change.getContent()) + ), + "CodeMPBufferReceive", + "codemp-buffer-receive", //TODO: mark this with the name + bufferEditor.getDocument() + ))); + } catch(Exception ex) { + throw new RuntimeException(ex); + } + } + } catch(Exception ex) { + TaskManager.nullBufferTask(); + Disposer.dispose(this); //stopped + } + } +} diff --git a/src/main/java/com/codemp/intellij/task/CursorEventAwaiterTask.java b/src/main/java/com/codemp/intellij/task/CursorEventAwaiterTask.java new file mode 100644 index 0000000..f3474a5 --- /dev/null +++ b/src/main/java/com/codemp/intellij/task/CursorEventAwaiterTask.java @@ -0,0 +1,100 @@ +package com.codemp.intellij.task; + +import com.codemp.intellij.CodeMP; +import com.codemp.intellij.jni.CursorEventWrapper; +import com.codemp.intellij.jni.CursorHandler; +import com.codemp.intellij.util.ColorUtil; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.markup.HighlighterLayer; +import com.intellij.openapi.editor.markup.HighlighterTargetArea; +import com.intellij.openapi.editor.markup.RangeHighlighter; +import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; +import org.jetbrains.annotations.NotNull; + +import java.awt.*; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +//TODO this is janky as it shows a progress bar it doesn't use tbh +//implements disposable so i can use it as lifetime ig +public class CursorEventAwaiterTask extends Task.Backgroundable implements Disposable { + private final CursorHandler handler; + private final Map highlighterMap = new ConcurrentHashMap<>(); + + public CursorEventAwaiterTask(@NotNull Project project, @NotNull CursorHandler handler) { + super(project, "Awaiting CodeMP cursor events", false); + this.handler = handler; + } + + @Override + public void dispose() {} + + @Override + @SuppressWarnings("InfiniteLoopStatement") + public void run(@NotNull ProgressIndicator indicator) { + assert myProject != null; //will never fail + try { + while(true) { + try { + CursorEventWrapper event = handler.recv(); + + Editor editor = CodeMP.ACTIVE_BUFFERS.get(event.getBuffer()); + if(editor == null) + continue; + + CodeMP.LOGGER.debug( + "Cursor moved by user {}! Start pos: {}x {}y; end pos: {}x {}y in buffer {}!", + event.getUser(), + event.getStartCol(), event.getStartCol(), + event.getEndRow(), event.getEndCol(), + event.getBuffer()); + + int startOffset = editor.getDocument().getLineStartOffset(event.getStartRow()) + event.getStartCol(); + int endOffset = editor.getDocument().getLineStartOffset(event.getEndRow()) + event.getEndCol(); + + ApplicationManager.getApplication().invokeLater(() -> { + try { + RangeHighlighter highlighter = this.highlighterMap.get(event.getUser()); + if(highlighter != null) + highlighter.dispose(); + + this.highlighterMap.put(event.getUser(), editor + .getMarkupModel() + .addRangeHighlighter( + startOffset, + endOffset, + HighlighterLayer.SELECTION, + new TextAttributes( + null, + ColorUtil.colorFromUsername(event.getUser()), + null, + null, + Font.PLAIN + ), HighlighterTargetArea.EXACT_RANGE + )); + } catch(IllegalArgumentException ex) { + //suppress if the cursor only exceeds length by one, it's probably just him adding something at EOF + if(endOffset - editor.getDocument().getTextLength() != 1) + throw ex; + } catch(Exception ex) { + throw new RuntimeException(ex); + } + }); + } catch(Exception ex) { + throw new RuntimeException(ex); + } + } + } catch(Exception ex) { //exited + this.highlighterMap.forEach((s, r) -> r.dispose()); + TaskManager.nullCursorTask(); + Disposer.dispose(this); + } + } +} diff --git a/src/main/java/com/codemp/intellij/task/TaskManager.java b/src/main/java/com/codemp/intellij/task/TaskManager.java new file mode 100644 index 0000000..70b059d --- /dev/null +++ b/src/main/java/com/codemp/intellij/task/TaskManager.java @@ -0,0 +1,40 @@ +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; + } +} diff --git a/src/main/java/com/codemp/intellij/util/DisposableRegistry.java b/src/main/java/com/codemp/intellij/util/DisposableRegistry.java deleted file mode 100644 index 3be0988..0000000 --- a/src/main/java/com/codemp/intellij/util/DisposableRegistry.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.codemp.intellij.util; - -import com.intellij.openapi.Disposable; -import com.intellij.openapi.util.Disposer; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * A registry holding {@link Disposable Disposables} used within the plugin, - * since there's no other way to keep track of them across different sections. - * Only parentless {@link Disposable Disposables} are handled here, since - * those with a parent will be disposed automatically. - */ -public class DisposableRegistry { - private static final Map DISPOSABLE_MAP = new ConcurrentHashMap<>(); - - public static boolean exists(String name) { - return DISPOSABLE_MAP.containsKey(name); - } - - public static Disposable get(String name) { - return DISPOSABLE_MAP.get(name); - } - - public static Disposable create(String name) { - disposeOf(name); //get rid of existing ones, if there is one, to prevent memory leaks - Disposable res = Disposer.newDisposable(name); - DISPOSABLE_MAP.put(name, res); - return res; - } - - public static Disposable getOrCreate(String name) { - Disposable disposable = DISPOSABLE_MAP.get(name); - if(disposable == null) - disposable = create(name); - return disposable; - } - - public static boolean track(String name, Disposable disposable) { - boolean replaced = exists(name); - if(replaced) - disposeOf(name); - DISPOSABLE_MAP.put(name, disposable); - return replaced; - } - - public static boolean disposeOf(String name) { - if(exists(name)) { - Disposable disposable = DISPOSABLE_MAP.remove(name); - Disposer.dispose(disposable); - return true; - } else return false; - } - - public static boolean disposeOf(Disposable disposable) { - if(DISPOSABLE_MAP.containsValue(disposable)) { - return DISPOSABLE_MAP.entrySet().removeIf(entry -> { - if(entry.getValue().equals(disposable)) { - Disposer.dispose(disposable, false); - return true; - } else return false; - }); - } else return false; - } -} diff --git a/src/main/rust/lib.rs b/src/main/rust/lib.rs index 671a310..a85dca8 100644 --- a/src/main/rust/lib.rs +++ b/src/main/rust/lib.rs @@ -67,6 +67,11 @@ impl CodeMPHandler { fn disconnect_buffer(path: String) -> Result { convert(CODEMP_INSTANCE.disconnect_buffer(&path)) } + + #[generate_interface] + fn select_buffer() -> Result { + convert(CODEMP_INSTANCE.select_buffer()) + } } fn convert_buffer(result: Result, CodempError>) -> Result { @@ -206,6 +211,24 @@ impl BufferHandler { panic!("Default constructor for BufferHandler should never be called!") } + #[generate_interface] + fn get_name(&self) -> String { + self.buffer.name.clone() + } + + #[generate_interface] + fn try_recv(&self) -> Result, String> { + match self.buffer.try_recv() { + Err(err) => Err(ErrorWrapper::from(err).get_error_message()), + Ok(None) => Ok(None), + Ok(Some(change)) => Ok(Some(TextChangeWrapper { + start: change.span.start, + end: change.span.end, + content: change.content.clone() + })) + } + } + #[generate_interface] fn recv(&self) -> Result { match self.buffer.blocking_recv(CODEMP_INSTANCE.rt()) {