mirror of
https://github.com/hexedtech/codemp-intellij.git
synced 2024-11-24 16:04:48 +01:00
feat: buffer send/recv
This commit is contained in:
parent
1228f786b7
commit
5b7d3c95dd
8 changed files with 278 additions and 92 deletions
|
@ -10,26 +10,30 @@ import org.jetbrains.annotations.NotNull;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class ConnectAction extends AnAction {
|
public class ConnectAction extends AnAction {
|
||||||
static {
|
public ConnectAction() {
|
||||||
|
super();
|
||||||
/*try {
|
/*try {
|
||||||
NativeUtils.loadLibraryFromJar("/resources/libHelloJNI.so");
|
NativeUtils.loadLibraryFromJar("/resources/libHelloJNI.so");
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}*/
|
}*/
|
||||||
System.load("/home/zaaarf/dev/irl/rust/codemp/client/intellij/target/debug/libcodemp_intellij.so");
|
//System.load("/home/zaaarf/dev/irl/rust/codemp/client/intellij/target/debug/libcodemp_intellij.so");
|
||||||
//System.load("O:/dev/IRL/Rust/codemp/client/intellij/target/debug/codemp_intellij.dll");
|
System.load("O:/dev/IRL/Rust/codemp/client/intellij/target/debug/codemp_intellij.dll");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connect(String url) throws Exception {
|
||||||
|
CodeMPHandler.connect(url);
|
||||||
|
//Messages.showInfoMessage(String.format("Connected to %s!", url), "CodeMP");
|
||||||
|
System.out.printf("Connected to %s!\n", url);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||||
String url = Messages.showInputDialog("URL to CodeMP instance:", "CodeMP Connect", Messages.getQuestionIcon());
|
String url = Messages.showInputDialog("URL to CodeMP instance:", "CodeMP Connect",
|
||||||
if(url == null || url.isBlank())
|
Messages.getQuestionIcon());
|
||||||
url = "http://alemi.dev:50051";
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CodeMPHandler.connect(url);
|
this.connect(url);
|
||||||
//Messages.showInfoMessage(String.format("Connected to %s!", url), "CodeMP");
|
|
||||||
System.out.printf("Connected to %s!\n", url);
|
|
||||||
} catch(Exception ex) {
|
} catch(Exception ex) {
|
||||||
Messages.showErrorDialog(String.format("Failed to connect to %s: %s!", url, ex.getMessage()), "CodeMP");
|
Messages.showErrorDialog(String.format("Failed to connect to %s: %s!", url, ex.getMessage()), "CodeMP");
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.codemp.intellij.actions;
|
||||||
|
|
||||||
|
import com.codemp.intellij.actions.buffer.BufferAttachAction;
|
||||||
|
import com.intellij.openapi.actionSystem.AnAction;
|
||||||
|
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class FastForwardAction extends AnAction {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||||
|
ConnectAction connectAction = new ConnectAction();
|
||||||
|
JoinAction joinAction = new JoinAction();
|
||||||
|
BufferAttachAction attachAction = new BufferAttachAction();
|
||||||
|
try {
|
||||||
|
connectAction.connect("http://alemi.dev:50051");
|
||||||
|
joinAction.join(e, "default");
|
||||||
|
attachAction.attach(e, "test");
|
||||||
|
} catch(Exception ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,64 +36,65 @@ public class JoinAction extends AnAction {
|
||||||
null, JBColor.BLUE, null, null, Font.PLAIN
|
null, JBColor.BLUE, null, null, Font.PLAIN
|
||||||
);
|
);
|
||||||
|
|
||||||
|
public void join(AnActionEvent e, String session) throws Exception {
|
||||||
|
CursorHandler cursorHandler = CodeMPHandler.join(session);
|
||||||
|
EditorFactory.getInstance()
|
||||||
|
.getEventMulticaster()
|
||||||
|
.addCaretListener(new CursorEventListener());
|
||||||
|
//Messages.showInfoMessage(String.format("Joined %s!", session), "CodeMP");
|
||||||
|
System.out.printf(String.format("Joined %s!\n", session));
|
||||||
|
Editor editor = FileEditorManager.getInstance(Objects.requireNonNull(e.getProject()))
|
||||||
|
.getSelectedTextEditor();
|
||||||
|
assert editor != null;
|
||||||
|
Document document = editor.getDocument();
|
||||||
|
ProgressManager.getInstance().run(new Task.Backgroundable(e.getProject(), "Awaiting CodeMP cursor events") {
|
||||||
|
@Override
|
||||||
|
public void run(@NotNull ProgressIndicator indicator) {
|
||||||
|
while(true) {
|
||||||
|
try {
|
||||||
|
CursorEventWrapper event = cursorHandler.recv();
|
||||||
|
ApplicationManager.getApplication().invokeLater(() -> {
|
||||||
|
try {
|
||||||
|
RangeHighlighter h = highlighterMap.get(event.getUser());
|
||||||
|
if(h != null)
|
||||||
|
h.dispose();
|
||||||
|
|
||||||
|
System.out.printf(
|
||||||
|
"Cursor moved by user %s! Start pos: x%d y%d; end pos: x%d y%d with buffer %s!\n",
|
||||||
|
event.getUser(),
|
||||||
|
event.getStartCol(), event.getStartCol(),
|
||||||
|
event.getEndRow(), event.getEndCol(),
|
||||||
|
event.getBuffer());
|
||||||
|
|
||||||
|
highlighterMap.put(event.getUser(), editor
|
||||||
|
.getMarkupModel()
|
||||||
|
.addRangeHighlighter(TextAttributesKey.createTextAttributesKey("codemp", HIGHLIGHTED),
|
||||||
|
document.getLineStartOffset(event.getStartRow()) + event.getStartCol(),
|
||||||
|
document.getLineStartOffset(event.getEndRow()) + event.getEndCol(),
|
||||||
|
HighlighterLayer.SELECTION,
|
||||||
|
HighlighterTargetArea.EXACT_RANGE
|
||||||
|
));
|
||||||
|
} catch(Exception ex) {
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch(Exception ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||||
String session = Messages.showInputDialog(
|
String session = Messages.showInputDialog(
|
||||||
"Session to connect to:",
|
"Session to connect to:",
|
||||||
"CodeMP Join",
|
"CodeMP Join",
|
||||||
Messages.getQuestionIcon());
|
Messages.getQuestionIcon());
|
||||||
if(session == null || session.isBlank())
|
|
||||||
session = "default";
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CursorHandler cursorHandler = CodeMPHandler.join(session);
|
this.join(e, session);
|
||||||
EditorFactory.getInstance()
|
|
||||||
.getEventMulticaster()
|
|
||||||
.addCaretListener(new CursorEventListener());
|
|
||||||
//Messages.showInfoMessage(String.format("Joined %s!", session), "CodeMP");
|
|
||||||
System.out.printf(String.format("Joined %s!", session));
|
|
||||||
Editor editor = FileEditorManager.getInstance(Objects.requireNonNull(e.getProject()))
|
|
||||||
.getSelectedTextEditor();
|
|
||||||
assert editor != null;
|
|
||||||
Document document = editor.getDocument();
|
|
||||||
ProgressManager.getInstance().run(new Task.Backgroundable(e.getProject(), "Awaiting CodeMP cursor events") {
|
|
||||||
@Override
|
|
||||||
public void run(@NotNull ProgressIndicator indicator) {
|
|
||||||
while(true) {
|
|
||||||
try {
|
|
||||||
CursorEventWrapper event = cursorHandler.recv();
|
|
||||||
ApplicationManager.getApplication().invokeLater(() -> {
|
|
||||||
try {
|
|
||||||
RangeHighlighter h = highlighterMap.get(event.getUser());
|
|
||||||
if(h != null)
|
|
||||||
h.dispose();
|
|
||||||
|
|
||||||
System.out.printf(
|
|
||||||
"Cursor moved by user %s! Start pos: x%d y%d; end pos: x%d y%d with buffer %s!\n",
|
|
||||||
event.getUser(),
|
|
||||||
event.getStartCol(), event.getStartCol(),
|
|
||||||
event.getEndRow(), event.getEndCol(),
|
|
||||||
event.getBuffer());
|
|
||||||
|
|
||||||
highlighterMap.put(event.getUser(), editor
|
|
||||||
.getMarkupModel()
|
|
||||||
.addRangeHighlighter(TextAttributesKey.createTextAttributesKey("codemp", HIGHLIGHTED),
|
|
||||||
document.getLineStartOffset(event.getStartRow()) + event.getStartCol(),
|
|
||||||
document.getLineStartOffset(event.getEndRow()) + event.getEndCol(),
|
|
||||||
HighlighterLayer.SELECTION,
|
|
||||||
HighlighterTargetArea.EXACT_RANGE
|
|
||||||
));
|
|
||||||
} catch(Exception ex) {
|
|
||||||
throw new RuntimeException();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch(Exception ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch(Exception ex) {
|
} catch(Exception ex) {
|
||||||
Messages.showErrorDialog(String.format(
|
Messages.showErrorDialog(String.format(
|
||||||
"Failed to join session %s: %s!",
|
"Failed to join session %s: %s!",
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
package com.codemp.intellij.actions.buffer;
|
||||||
|
|
||||||
|
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.actionSystem.AnAction;
|
||||||
|
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||||
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
|
import com.intellij.openapi.editor.Document;
|
||||||
|
import com.intellij.openapi.editor.Editor;
|
||||||
|
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||||
|
import com.intellij.openapi.progress.ProgressIndicator;
|
||||||
|
import com.intellij.openapi.progress.ProgressManager;
|
||||||
|
import com.intellij.openapi.progress.Task;
|
||||||
|
import com.intellij.openapi.ui.Messages;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import javax.print.Doc;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class BufferAttachAction extends AnAction {
|
||||||
|
|
||||||
|
public void attach(AnActionEvent e, String buffer) throws Exception {
|
||||||
|
BufferHandler bufferHandler = CodeMPHandler.attach(buffer);
|
||||||
|
//Messages.showInfoMessage(String.format("Connected to %s!", url), "CodeMP");
|
||||||
|
|
||||||
|
//register buffer change listener
|
||||||
|
//TODO "get" the Document corresponding to buffer, for now use the current one
|
||||||
|
BufferEventListener listener = new BufferEventListener(buffer);
|
||||||
|
assert e.getProject() != null;
|
||||||
|
Editor editor = FileEditorManager.getInstance(e.getProject()).getSelectedTextEditor();
|
||||||
|
assert editor != null;
|
||||||
|
Document document = editor.getDocument();
|
||||||
|
document.addDocumentListener(listener);
|
||||||
|
|
||||||
|
ProgressManager.getInstance().run(new Task.Backgroundable(e.getProject(), "Awaiting CodeMP buffer events") {
|
||||||
|
@Override
|
||||||
|
public void run(@NotNull ProgressIndicator indicator) {
|
||||||
|
while(true) {
|
||||||
|
try {
|
||||||
|
TextChangeWrapper event = bufferHandler.recv();
|
||||||
|
ApplicationManager.getApplication().invokeLaterOnWriteThread(() ->
|
||||||
|
ApplicationManager.getApplication().runWriteAction(() -> {
|
||||||
|
System.out.printf("Received text change %s from offset %d to %d!\n",
|
||||||
|
event.getContent(), event.getStart(), event.getEnd());
|
||||||
|
document.replaceString( //TODO this doesn't work
|
||||||
|
(int) event.getStart(),
|
||||||
|
(int) event.getEnd(),
|
||||||
|
event.getContent()
|
||||||
|
);
|
||||||
|
}));
|
||||||
|
} catch(Exception ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
System.out.printf("Created buffer %s!\n", buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||||
|
String buffer = Messages.showInputDialog(
|
||||||
|
"Buffer name:",
|
||||||
|
"Attach to CodeMP Buffer",
|
||||||
|
Messages.getQuestionIcon());
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.attach(e, buffer);
|
||||||
|
} catch(Exception ex) {
|
||||||
|
Messages.showErrorDialog(String.format(
|
||||||
|
"Failed to attach to buffer %s: %s!",
|
||||||
|
buffer, ex.getMessage()), "Attach to CodeMP Buffer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package com.codemp.intellij.listeners;
|
||||||
|
|
||||||
|
import com.codemp.intellij.jni.BufferHandler;
|
||||||
|
import com.codemp.intellij.jni.CodeMPHandler;
|
||||||
|
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||||
|
import com.intellij.openapi.editor.event.DocumentListener;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class BufferEventListener implements DocumentListener {
|
||||||
|
|
||||||
|
private final String bufferName;
|
||||||
|
|
||||||
|
public BufferEventListener(String bufferName) {
|
||||||
|
this.bufferName = bufferName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void documentChanged(@NotNull DocumentEvent event) {
|
||||||
|
try {
|
||||||
|
int changeOffset = event.getOffset();
|
||||||
|
CharSequence newFragment = event.getNewFragment();
|
||||||
|
BufferHandler bufferHandler = CodeMPHandler.getBuffer(this.bufferName);
|
||||||
|
bufferHandler.send(changeOffset, changeOffset + event.getOldFragment().length(),
|
||||||
|
newFragment.toString());
|
||||||
|
} catch(Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
ABCD
|
||||||
|
ABAACD
|
||||||
|
|
||||||
|
getOffset() -> B + 1
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
|
@ -2,7 +2,6 @@ package com.codemp.intellij.listeners;
|
||||||
|
|
||||||
import com.codemp.intellij.jni.CodeMPHandler;
|
import com.codemp.intellij.jni.CodeMPHandler;
|
||||||
import com.intellij.openapi.editor.Caret;
|
import com.intellij.openapi.editor.Caret;
|
||||||
import com.intellij.openapi.editor.EditorFactory;
|
|
||||||
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;
|
||||||
|
@ -20,7 +19,8 @@ public class CursorEventListener implements CaretListener {
|
||||||
try {
|
try {
|
||||||
VisualPosition startPos = caret.getSelectionStartPosition();
|
VisualPosition startPos = caret.getSelectionStartPosition();
|
||||||
VisualPosition endPos = caret.getSelectionEndPosition();
|
VisualPosition endPos = caret.getSelectionEndPosition();
|
||||||
System.out.printf("start %dx %dy end %dx %dy", startPos.line, startPos.column, endPos.line, endPos.column);
|
System.out.printf("start %dx %dy end %dx %dy",
|
||||||
|
startPos.line, startPos.column, endPos.line, endPos.column);
|
||||||
CodeMPHandler.getCursor().send(
|
CodeMPHandler.getCursor().send(
|
||||||
"", startPos.line, startPos.column, endPos.line, endPos.column
|
"", startPos.line, startPos.column, endPos.line, endPos.column
|
||||||
);
|
);
|
||||||
|
|
|
@ -25,17 +25,14 @@
|
||||||
<actions>
|
<actions>
|
||||||
<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.connect" class="com.codemp.intellij.actions.ConnectAction" text="Connect...">
|
<action id="codemp.fast-forward" class="com.codemp.intellij.actions.FastForwardAction" text="Pls hurry"/>
|
||||||
<add-to-group group-id="ToolsMenu" anchor="first"/>
|
<action id="codemp.connect" class="com.codemp.intellij.actions.ConnectAction" text="Connect..."/>
|
||||||
</action>
|
<action id="codemp.join" class="com.codemp.intellij.actions.JoinAction" text="Join..."/>
|
||||||
<action id="codemp.join" class="com.codemp.intellij.actions.JoinAction" text="Join...">
|
|
||||||
<add-to-group group-id="ToolsMenu" anchor="first"/>
|
|
||||||
</action>
|
|
||||||
<group id="codemp.buffer" text="Buffer" popup="true">
|
<group id="codemp.buffer" text="Buffer" popup="true">
|
||||||
<action id="codemp.buffer.create" class="com.codemp.intellij.actions.buffer.BufferCreateAction"
|
<action id="codemp.buffer.create" class="com.codemp.intellij.actions.buffer.BufferCreateAction"
|
||||||
text="Create Buffer">
|
text="Create Buffer"/>
|
||||||
<add-to-group group-id="ToolsMenu" anchor="first"/>
|
<action id="codemp.buffer.attach" class="com.codemp.intellij.actions.buffer.BufferAttachAction"
|
||||||
</action>
|
text="Attach to Buffer"/>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
</actions>
|
</actions>
|
||||||
|
|
|
@ -93,33 +93,33 @@ impl CursorEventWrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[generate_interface]
|
#[generate_interface]
|
||||||
fn get_user(&self) -> Result<&str, String> {
|
fn get_user(&self) -> &str {
|
||||||
Ok(&self.user)
|
&self.user
|
||||||
}
|
}
|
||||||
|
|
||||||
#[generate_interface]
|
#[generate_interface]
|
||||||
fn get_buffer(&self) -> Result<&str, String> {
|
fn get_buffer(&self) -> &str {
|
||||||
Ok(&self.buffer)
|
&self.buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
#[generate_interface]
|
#[generate_interface]
|
||||||
fn get_start_row(&self) -> Result<i32, String> {
|
fn get_start_row(&self) -> i32 {
|
||||||
Ok(self.start_row)
|
self.start_row
|
||||||
}
|
}
|
||||||
|
|
||||||
#[generate_interface]
|
#[generate_interface]
|
||||||
fn get_start_col(&self) -> Result<i32, String> {
|
fn get_start_col(&self) -> i32 {
|
||||||
Ok(self.start_col)
|
self.start_col
|
||||||
}
|
}
|
||||||
|
|
||||||
#[generate_interface]
|
#[generate_interface]
|
||||||
fn get_end_row(&self) -> Result<i32, String> {
|
fn get_end_row(&self) -> i32 {
|
||||||
Ok(self.end_row)
|
self.end_row
|
||||||
}
|
}
|
||||||
|
|
||||||
#[generate_interface]
|
#[generate_interface]
|
||||||
fn get_end_col(&self) -> Result<i32, String> {
|
fn get_end_col(&self) -> i32 {
|
||||||
Ok(self.end_col)
|
self.end_col
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,16 +139,14 @@ impl CursorHandler {
|
||||||
fn recv(&self) -> Result<CursorEventWrapper, String> {
|
fn recv(&self) -> Result<CursorEventWrapper, String> {
|
||||||
match self.cursor.blocking_recv(CODEMP_INSTANCE.rt()) {
|
match self.cursor.blocking_recv(CODEMP_INSTANCE.rt()) {
|
||||||
Err(err) => Err(ErrorWrapper::from(err).get_error_message()),
|
Err(err) => Err(ErrorWrapper::from(err).get_error_message()),
|
||||||
Ok(event) => {
|
Ok(event) => Ok(CursorEventWrapper {
|
||||||
Ok(CursorEventWrapper {
|
user: event.user,
|
||||||
user: event.user,
|
buffer: event.position.as_ref().unwrap().buffer.clone(),
|
||||||
buffer: event.position.as_ref().unwrap().buffer.clone(),
|
start_row: event.position.as_ref().unwrap().start().row,
|
||||||
start_row: event.position.as_ref().unwrap().start().row,
|
start_col: event.position.as_ref().unwrap().start().col,
|
||||||
start_col: event.position.as_ref().unwrap().start().col,
|
end_row: event.position.as_ref().unwrap().end().row,
|
||||||
end_row: event.position.as_ref().unwrap().end().row,
|
end_col: event.position.as_ref().unwrap().end().col
|
||||||
end_col: event.position.as_ref().unwrap().end().col
|
})
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,6 +160,35 @@ impl CursorHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[generate_interface_doc]
|
||||||
|
struct TextChangeWrapper {
|
||||||
|
start: usize,
|
||||||
|
end: usize, //not inclusive
|
||||||
|
content: String
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TextChangeWrapper {
|
||||||
|
#[generate_interface(constructor)]
|
||||||
|
fn new() -> TextChangeWrapper {
|
||||||
|
panic!("Default constructor for TextChangeWrapper should never be called!")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[generate_interface]
|
||||||
|
fn get_start(&self) -> usize {
|
||||||
|
self.start
|
||||||
|
}
|
||||||
|
|
||||||
|
#[generate_interface]
|
||||||
|
fn get_end(&self) -> usize {
|
||||||
|
self.end
|
||||||
|
}
|
||||||
|
|
||||||
|
#[generate_interface]
|
||||||
|
fn get_content(&self) -> &str {
|
||||||
|
&self.content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[generate_interface_doc]
|
#[generate_interface_doc]
|
||||||
struct BufferHandler {
|
struct BufferHandler {
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
@ -173,4 +200,25 @@ impl BufferHandler {
|
||||||
fn new() -> BufferHandler {
|
fn new() -> BufferHandler {
|
||||||
panic!("Default constructor for BufferHandler should never be called!")
|
panic!("Default constructor for BufferHandler should never be called!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[generate_interface]
|
||||||
|
fn recv(&self) -> Result<TextChangeWrapper, String> {
|
||||||
|
match self.buffer.blocking_recv(CODEMP_INSTANCE.rt()) {
|
||||||
|
Err(err) => Err(ErrorWrapper::from(err).get_error_message()),
|
||||||
|
Ok(change) => Ok(TextChangeWrapper {
|
||||||
|
start: change.span.start,
|
||||||
|
end: change.span.end,
|
||||||
|
content: change.content.clone()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[generate_interface]
|
||||||
|
fn send(&self, start_offset: usize, end_offset: usize, content: String) -> Result<(), String> {
|
||||||
|
match self.buffer.delta(start_offset, &content, end_offset) {
|
||||||
|
None => Err("Cannot send a no-op".to_string()),
|
||||||
|
Some(op_seq) => self.buffer.send(op_seq)
|
||||||
|
.map_err(|err| ErrorWrapper::from(err).get_error_message())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue