Add support to DocumentEdits to 'freeze' cursor
This commit is contained in:
@@ -21,8 +21,7 @@ import reactor.ipc.netty.channel.AbortedException;
|
||||
|
||||
/**
|
||||
* This is a stateful callable context that is "aware" of CF errors, and is not
|
||||
* suitable for reuse as it may cache errors
|
||||
*
|
||||
* suitable for reuse as it may cache errors.
|
||||
*/
|
||||
public class CFCallableContext {
|
||||
|
||||
|
||||
@@ -135,14 +135,15 @@ public class DocumentEdits implements ProposalApplier {
|
||||
private int offset;
|
||||
private String text;
|
||||
|
||||
public Insertion(int offset, String insert) {
|
||||
public Insertion(boolean grabCursor, int offset, String insert) {
|
||||
super(grabCursor);
|
||||
this.offset = offset;
|
||||
this.text = insert;
|
||||
}
|
||||
|
||||
@Override
|
||||
void apply(DocumentState doc) throws BadLocationException {
|
||||
doc.insert(offset, text);
|
||||
doc.insert(grabCursor, offset, text);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -162,6 +163,10 @@ public class DocumentEdits implements ProposalApplier {
|
||||
}
|
||||
|
||||
private abstract class Edit {
|
||||
protected boolean grabCursor;
|
||||
protected Edit(boolean grabCursor) {
|
||||
this.grabCursor = grabCursor;
|
||||
}
|
||||
public abstract int getStart();
|
||||
public abstract int getEnd();
|
||||
abstract void apply(DocumentState doc) throws BadLocationException;
|
||||
@@ -174,14 +179,15 @@ public class DocumentEdits implements ProposalApplier {
|
||||
private int start;
|
||||
private int end;
|
||||
|
||||
public Deletion(int start, int end) {
|
||||
public Deletion(boolean grabCursor, int start, int end) {
|
||||
super(grabCursor);
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
@Override
|
||||
void apply(DocumentState doc) throws BadLocationException {
|
||||
doc.delete(start, end);
|
||||
doc.delete(grabCursor, start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -227,7 +233,7 @@ public class DocumentEdits implements ProposalApplier {
|
||||
this.doc = doc;
|
||||
}
|
||||
|
||||
public void insert(int start, final String text) throws BadLocationException {
|
||||
public void insert(boolean grabCursor, int start, final String text) throws BadLocationException {
|
||||
final int tStart = org2new.transform(start, Direction.AFTER);
|
||||
if (!text.isEmpty()) {
|
||||
if (doc!=null) {
|
||||
@@ -252,10 +258,14 @@ public class DocumentEdits implements ProposalApplier {
|
||||
}
|
||||
};
|
||||
}
|
||||
selection = tStart+text.length();
|
||||
if (grabCursor) {
|
||||
selection = tStart+text.length();
|
||||
} else if (selection > tStart) {
|
||||
selection += text.length();
|
||||
}
|
||||
}
|
||||
|
||||
public void delete(final int start, final int end) throws BadLocationException {
|
||||
public void delete(boolean grabCursor, final int start, final int end) throws BadLocationException {
|
||||
final int tStart = org2new.transform(start, Direction.AFTER);
|
||||
if (end>start) { // skip work for 'delete nothing' op
|
||||
final int tEnd = org2new.transform(end, Direction.AFTER);
|
||||
@@ -280,7 +290,14 @@ public class DocumentEdits implements ProposalApplier {
|
||||
};
|
||||
}
|
||||
}
|
||||
selection = tStart;
|
||||
if (grabCursor) {
|
||||
selection = tStart;
|
||||
} else if (selection>tStart) {
|
||||
int len = end - start;
|
||||
if (len > 0) {
|
||||
selection = Math.max(tStart, selection-len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -299,13 +316,22 @@ public class DocumentEdits implements ProposalApplier {
|
||||
private List<Edit> edits = new ArrayList<Edit>();
|
||||
private IDocument doc;
|
||||
|
||||
/**
|
||||
* When this is true, the cursor is moved after each edit, to be positioned right after the
|
||||
* edit.
|
||||
* <p>
|
||||
* When it is false, the cursor only moves to remain in place relative to the surrounding text.
|
||||
* (I.e. if text is inserted/deleted before the cursor its shifted by the length of the inserted/deleted text).
|
||||
*/
|
||||
private boolean grabCursor = true;
|
||||
|
||||
public DocumentEdits(IDocument doc) {
|
||||
this.doc = doc;
|
||||
}
|
||||
|
||||
public void delete(int start, int end) {
|
||||
Assert.isLegal(start<=end);
|
||||
edits.add(new Deletion(start, end));
|
||||
edits.add(new Deletion(grabCursor, start, end));
|
||||
}
|
||||
|
||||
public void delete(int offset, String text) {
|
||||
@@ -313,7 +339,7 @@ public class DocumentEdits implements ProposalApplier {
|
||||
}
|
||||
|
||||
public void insert(int offset, String insert) {
|
||||
edits.add(new Insertion(offset, insert));
|
||||
edits.add(new Insertion(grabCursor, offset, insert));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -417,7 +443,7 @@ public class DocumentEdits implements ProposalApplier {
|
||||
if (edits.size()>0) {
|
||||
Edit firstEdit = edits.get(0);
|
||||
int offset = firstEdit.getStart();
|
||||
edits.add(0, new Insertion(offset, indentString));
|
||||
edits.add(0, new Insertion(grabCursor, offset, indentString));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,4 +471,12 @@ public class DocumentEdits implements ProposalApplier {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop moving the cursor to the end of edits for successive edits. The cursor will still be
|
||||
* update to remain 'in place' relative to the surrounding text.
|
||||
*/
|
||||
public void freezeCursor() {
|
||||
this.grabCursor = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -96,6 +96,10 @@ public class DocumentEditsTest {
|
||||
edits.deleteLineBackward(0);
|
||||
}
|
||||
|
||||
public void freezeCursor() {
|
||||
edits.freezeCursor();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test public void testDeletes() throws Exception {
|
||||
@@ -194,4 +198,40 @@ public class DocumentEditsTest {
|
||||
|
||||
}
|
||||
|
||||
@Test public void testCursorFreeze() throws Exception {
|
||||
TestSubject it = new TestSubject(
|
||||
"something:\n" +
|
||||
"#end"
|
||||
);
|
||||
// it.insBefore("\n#end", "\n foo: ");
|
||||
// it.insBefore("\n#end", "\n zoro: ");
|
||||
// it.insBefore("\n#end", "\n banana: ");
|
||||
//
|
||||
// it.expect(
|
||||
// "something:\n" +
|
||||
// " foo: \n" +
|
||||
// " zoro: \n" +
|
||||
// " banana: <*>\n" +
|
||||
// "#end"
|
||||
// );
|
||||
//
|
||||
// it.reset();
|
||||
|
||||
it.insBefore("\n#end", "\n foo: ");
|
||||
it.freezeCursor();
|
||||
it.insBefore("\n#end", "\n zoro: ");
|
||||
it.insBefore("\n#end", "\n banana: ");
|
||||
it.del("#end");
|
||||
it.insBefore("something", "replc");
|
||||
it.del("something");
|
||||
|
||||
it.expect(
|
||||
"replc:\n" +
|
||||
" foo: <*>\n" +
|
||||
" zoro: \n" +
|
||||
" banana: \n"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user