Caret "beyond end of line"

I'm working on a plugins that add carets. However, during that process, the primary caret gets changed (I'm not a 100% sure why, though while digging in the code, it seems the last caret added is the primary one).

Anyway, as a work around, I save the position of the caret, then after adding other carets, I "restore" the position, so it's put last. Works fine.

Issue is, if you don't "allow cursor beyond end of line", when you're on column 10, and scroll down to an empty line, you go to column 0. Fine. And when you scroll again to a longer line, let's say 20 chars, you're back at column 10. But when I set manually the primary caret, this information is lost, so scrolling down again brings you to column 0. Any way to solve this?

12 comments

>I'm working on a plugins that add carets. However, during that process, the primary caret gets changed (I'm not a 100% sure why, though while digging in the code, it seems the last caret added is the primary one).

That's true, a caret that is added becomes the primary one.

> Issue is, if you don't "allow cursor beyond end of line", when you're on column 10, and scroll down to an empty line, you go to column 0. Fine. And when you scroll again to a longer line, let's say 20 chars, you're back at column 10. But when I set manually the primary caret, this information is lost, so scrolling down again brings you to column 0. Any way to solve this?

I don't see a way how to achieve this using current API. Could you please give more details about your use case? What logic your plugin is going to implement?

0

I'm trying to quickly put together a Delphi-like sync edit functionality, as none of the existing plugins are suiting my needs.

And to make the sync editing, what's better than adding carets everywhere edition should be done? :)

 

I've dug into Caret, found what I needed (the desired X position), however it seems to be already reset when I get notified of caret change. So I guess what I'd need would be a way to add a caret as a secondary caret, or maybe a way to add directory an existing caret (ie, not by position, just the Caret object, but that seems tough).

0

We can extend API, allowing to add caret, while not making it a primary one, as you say.

But the description of Sync Edit Mode I've found (http://docwiki.embarcadero.com/RADStudio/XE7/en/Sync_Edit_Mode_%28Delphi,_C%2B%2B%29) looks very similar to in-place renaming functionality in IDEA (https://www.jetbrains.com/help/idea/2016.1/rename-refactorings.html). Why do you think is it worth to implement a separate mechanism? (Currently in-place renaming doesn't work via multiple carets, but it might be some day).

0

As a reference, my feature request:

https://youtrack.jetbrains.com/issue/WI-4811#u=1401303719515

However, it probably doesn't highlight the full interest of the thing. It lies in being able to do partial edits, confined to a specific zone.

Imagine I have this code:

something.x = something.z + something.t * (something.u * something.u);

Now I want to turn it into:

somethingElse.x = somethingElse.z + somethingElse.t * (somethingElse.v * somethingElse.v);

I'll just duplicate the line, select it, enable SyncEdit, edit something into somethingElse, and change u into v.

Same with :

something.x = getX();

something.y = getY();

If I want to apply the same to somethingElse, I'll duplicate and change something into somethingElse.

This behaviour has to not involve any refactoring (unlike rename in place, which I love using).

And I know it can all be achieved with things like find/replace, of course, it's just a matter of speed, and well, the reason I use your tools is speed ;)

Extending the API could be very nice, would make my job easier!

Thanks for your answers, and as usual, I just love your products.

0

I've implemented corresponding change, you'll be able to test it when 2016.2 EAP program will start.

You'll probably also need to add your own Escape editor action handler, as the default one's logic is tied to the default behaviour for newly added carets.

0

Wahoo, thanks!

I already have a Escape handler, as I want to quit sync edit when hitting escape.

0

Hey,

Sorry to bother you again. I've tried the new API, and it works fine, unless I set 2 or carets on the same line, and this line has the primary caret.

Here's my test case:

String hello1 = "aazertT1234562222eTes" + 122209999;

hello1 = hello1 + hello1 + "aazertT1234562222eTes" + 122209999 ;

// Put cursor on hello (on the h) below and press up key... will loop
int l = hello1.length() + hello1.length();

if (hello1.length() > 122209999)
{

}

 

When I put the caret on any "hello1" of the line that has 3, or the one that has 2, my plugins put carets on all hello1. Then, when I hit the down key, it moves the carets down, but as the primary caret had been on the very first hello1.

Moving the caret up, left or right doesn't seem to cause any issue. I've added debug notifications after adding caret (including one in an invokeLater) and they all show the primary caret is the correct one, it's just for some reason, when I hit the bottom key, then it scrolls down from the first caret, and not the primary.

for (Integer caretOffset : caretOffsets)
{
Caret caret = editor.getCaretModel().addCaret(editor.offsetToVisualPosition(caretOffset), false);
}

If I comment the line in that for, then there's no more issue. But of course then my plugins doesn't let user do multiple edits in one go.

Thanks for your help!

 

0

Sorry, I couldn't understand what your problem is.

If it's with 'down' action implementation, please show the initial positions of all carets, and their positions after the action.

If it's with something you try to achieve in your code, please give the piece of code, what it does, and what you suppose it to do.

 

 

0

Sorry, I expected it to be unclear.

My code, roughly, adds lots of secondary carets.

And if I add one secondary caret on a line above the current caret, and another secondary caret on the same line as the current caret, then when pressing the down (arrow) key, instead of moving from the primary caret, it moves from the first (top most) caret.

Line1 |Word

Line2 |Word |*Word

Line3

( | mean caret, |* means primary caret)

In this configuration, pressing the down key will give me a caret on line 2, instead of one line 3.

0

OK, I think I understand what you mean now. When primary caret gets merged with another one, it seems it can loose its 'primary' status now. I'll check whether it can be changed.

0

Totally make sense to me too now. I don't have this issue if I enable "allow caret after end of line", which points indeed toward issue upon caret merge. Thank you so much!

0

I've pushed the change which should make caret model work as expected.

0

Please sign in to leave a comment.