mirror of
https://github.com/hexedtech/codemp-intellij.git
synced 2024-12-03 19:44:51 +01:00
fix: cursor and buffer not syncing when overloaded with cursor movements
This commit is contained in:
parent
70bd32a686
commit
7ae82c83c0
5 changed files with 63 additions and 23 deletions
|
@ -15,8 +15,7 @@ public class BufferAttachAction extends AnAction {
|
|||
public static void attach(AnActionEvent e, String buffer, boolean silent) {
|
||||
BufferHandler bufferHandler = CodeMPHandler.attach(buffer);
|
||||
if(!silent) ActionUtil.notify(e, "Success",
|
||||
String.format("Successfully attached to buffer to buffer to %s!", buffer)
|
||||
);
|
||||
String.format("Successfully attached to buffer to buffer to %s!", buffer));
|
||||
CodeMP.LOGGER.debug("Attached to buffer to {}!", buffer);
|
||||
|
||||
//TODO "get" the Editor corresponding to buffer, for now use the current one
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.codemp.intellij.exceptions.lib.ChannelException;
|
|||
import com.codemp.intellij.exceptions.lib.DeadlockedException;
|
||||
import com.codemp.intellij.jni.BufferHandler;
|
||||
import com.codemp.intellij.jni.CodeMPHandler;
|
||||
import com.codemp.intellij.jni.StringVec;
|
||||
import com.codemp.intellij.jni.TextChangeWrapper;
|
||||
import com.codemp.intellij.listeners.BufferEventListener;
|
||||
import com.intellij.openapi.Disposable;
|
||||
|
@ -22,6 +23,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
|
||||
public class BufferEventAwaiterTask extends Task.Backgroundable implements Disposable {
|
||||
private final Map<String, Disposable> bufferListeners = new ConcurrentHashMap<>();
|
||||
private final Set<String> initialisedBuffers = Collections.newSetFromMap(new ConcurrentHashMap<>()); //also tonioware
|
||||
|
||||
public BufferEventAwaiterTask(@NotNull Project project) {
|
||||
super(project, "Awaiting CodeMP buffer events", false);
|
||||
|
@ -41,6 +43,8 @@ public class BufferEventAwaiterTask extends Task.Backgroundable implements Dispo
|
|||
}
|
||||
|
||||
public void unregisterListener(String name) {
|
||||
CodeMP.ACTIVE_BUFFERS_REVERSE.remove(CodeMP.ACTIVE_BUFFERS.remove(name));
|
||||
this.initialisedBuffers.remove(name);
|
||||
Disposable listener = this.bufferListeners.remove(name);
|
||||
if(listener != null)
|
||||
listener.dispose();
|
||||
|
@ -50,17 +54,25 @@ public class BufferEventAwaiterTask extends Task.Backgroundable implements Dispo
|
|||
public void dispose() {}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"InfiniteLoopStatement", "UnstableApiUsage"})
|
||||
@SuppressWarnings({"InfiniteLoopStatement", "UnstableApiUsage", "BusyWait"})
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
try {
|
||||
Thread.sleep(100); //tonioware
|
||||
} catch(InterruptedException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
|
||||
try {
|
||||
while(true) {
|
||||
String buffer = CodeMPHandler.selectBuffer();
|
||||
StringVec buffers = new StringVec(); //jni moment
|
||||
CodeMP.ACTIVE_BUFFERS.keySet().forEach(buffers::push);
|
||||
|
||||
Optional<String> bufferOptional = CodeMPHandler.selectBuffer(buffers, 100L);
|
||||
if(bufferOptional.isEmpty())
|
||||
continue;
|
||||
String buffer = bufferOptional.get();
|
||||
|
||||
if(!this.initialisedBuffers.contains(buffer)) { //tonioware
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch(InterruptedException ignored) {}
|
||||
this.initialisedBuffers.add(buffer);
|
||||
}
|
||||
|
||||
BufferHandler handler = CodeMPHandler.getBuffer(buffer);
|
||||
|
||||
List<TextChangeWrapper> changeList = new ArrayList<>();
|
||||
|
@ -81,7 +93,6 @@ public class BufferEventAwaiterTask extends Task.Backgroundable implements Dispo
|
|||
}
|
||||
|
||||
Editor bufferEditor = CodeMP.ACTIVE_BUFFERS.get(buffer);
|
||||
|
||||
ApplicationManager.getApplication().invokeLaterOnWriteThread(() ->
|
||||
ApplicationManager.getApplication().runWriteAction(() ->
|
||||
CommandProcessor.getInstance().executeCommand(
|
||||
|
|
|
@ -69,11 +69,7 @@ public class CursorEventAwaiterTask extends Task.Backgroundable implements Dispo
|
|||
return;
|
||||
}
|
||||
|
||||
RangeHighlighter highlighter = this.highlighterMap.get(event.getUser());
|
||||
if(highlighter != null)
|
||||
highlighter.dispose();
|
||||
|
||||
this.highlighterMap.put(event.getUser(), editor
|
||||
RangeHighlighter previous = this.highlighterMap.put(event.getUser(), editor
|
||||
.getMarkupModel()
|
||||
.addRangeHighlighter(
|
||||
startOffset,
|
||||
|
@ -87,6 +83,9 @@ public class CursorEventAwaiterTask extends Task.Backgroundable implements Dispo
|
|||
Font.PLAIN
|
||||
), HighlighterTargetArea.EXACT_RANGE
|
||||
));
|
||||
|
||||
if(previous != null)
|
||||
previous.dispose();
|
||||
});
|
||||
} catch(IndexOutOfBoundsException ignored) {}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,5 @@ foreign_typemap!( //thanks @tasn on GitHub for the idea
|
|||
}
|
||||
};
|
||||
};
|
||||
($p:f_type, unique_prefix="/*codemp::prelude::CodempResult<swig_subst_type!(T)>*/") => "/*codemp::prelude::CodempResult<swig_subst_type!(T)>*/swig_f_type!(T)"
|
||||
"swig_foreign_from_i_type!(T, $p)";
|
||||
);
|
||||
($p:f_type, unique_prefix="/*err*/") => "/*err*/swig_f_type!(T)" "swig_foreign_from_i_type!(T, $p)";
|
||||
);
|
|
@ -1,5 +1,7 @@
|
|||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use codemp::prelude::*;
|
||||
use codemp::tools;
|
||||
use rifgen::rifgen_attr::{generate_access_methods, generate_interface, generate_interface_doc};
|
||||
|
||||
pub mod glue { //rifgen generated code
|
||||
|
@ -66,8 +68,16 @@ impl CodeMPHandler {
|
|||
}
|
||||
|
||||
#[generate_interface]
|
||||
fn select_buffer() -> CodempResult<String> {
|
||||
CODEMP_INSTANCE.select_buffer()
|
||||
fn select_buffer(mut buffer_ids: StringVec, timeout: i64) -> CodempResult<Option<String>> {
|
||||
let mut buffers = Vec::new();
|
||||
for id in buffer_ids.v.iter_mut() {
|
||||
match CODEMP_INSTANCE.get_buffer(id.as_str()) {
|
||||
Ok(buf) => buffers.push(buf),
|
||||
Err(_) => continue
|
||||
}
|
||||
}
|
||||
CODEMP_INSTANCE.rt().block_on(
|
||||
tools::select_buffer_timeout(&buffers, Duration::from_millis(timeout as u64)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,7 +102,7 @@ struct CursorHandler {
|
|||
impl CursorHandler {
|
||||
#[generate_interface(constructor)]
|
||||
fn new() -> CursorHandler {
|
||||
panic!("Default constructor for CursorHandler should never be called!")
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[generate_interface]
|
||||
|
@ -137,7 +147,7 @@ struct BufferHandler {
|
|||
impl BufferHandler {
|
||||
#[generate_interface(constructor)]
|
||||
fn new() -> BufferHandler {
|
||||
panic!("Default constructor for BufferHandler should never be called!")
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[generate_interface]
|
||||
|
@ -145,6 +155,11 @@ impl BufferHandler {
|
|||
self.buffer.name.clone()
|
||||
}
|
||||
|
||||
#[generate_interface]
|
||||
fn get_content(&self) -> String {
|
||||
self.buffer.content()
|
||||
}
|
||||
|
||||
#[generate_interface]
|
||||
fn try_recv(&self) -> CodempResult<Option<TextChangeWrapper>> {
|
||||
match self.buffer.try_recv() {
|
||||
|
@ -175,3 +190,20 @@ impl BufferHandler {
|
|||
self.buffer.send(CodempTextChange { span: start_offset..end_offset, content })
|
||||
}
|
||||
}
|
||||
|
||||
#[generate_interface_doc]
|
||||
struct StringVec { //jni moment
|
||||
v: Vec<String>
|
||||
}
|
||||
|
||||
impl StringVec {
|
||||
#[generate_interface(constructor)]
|
||||
fn new() -> StringVec {
|
||||
Self { v: Vec::new() }
|
||||
}
|
||||
|
||||
#[generate_interface]
|
||||
fn push(&mut self, s: String) {
|
||||
self.v.push(s);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue