Sublime Forum

on_modified: what changed?

#1

Is there a way to find out what the modification was in an on_modified or on_selection_modified callback?

0 Likes

#2

Unfortunately not - this is something I’m planning to implement in version 3 (!)

0 Likes

#3

Oh no… that’s so long from now…
Any tips for a workaround? I don’t really want to diff the whole file each modification… :stuck_out_tongue:

0 Likes

#4

Depends on what you’re trying to accomplish… you may want to consider looking near the selection for modified areas, or making use of the regions API, which would let you monitor, for example, if text has been inserted or deleted within a certain range.

0 Likes

#5

Oh, interesting… because marked regions automatically move with the text—they’re locked to the actual buffer position rather than the textpoint.
Could the function names be changed to something like mark_regions, erase_marked_regions, and get_marked_regions? I only ask because when you mentioned the region API I originally thought you were talking about sublime.Region’s methods, rather than sublime.View’s methods for marking (or whatever it’s called) regions. Also, is there a way to skip drawing non-empty regions? I could just make multiple empty regions but that’s a bit more complicated.
Hopefully this will work.

Next question: When I modify the buffer in my on_modified callback, I get called back again! Is there any way to avoid or detect this behaviour?
Thanks!

0 Likes

#6

If you pass an empty string for the scope parameter, the regions won’t be drawn.

May I ask why you’re modifying the buffer in the on_modified callback? With the current behavior, this will cause a new undo group to be created, which is likely not ideal. As for not getting a callback, your best bet is something like:

def on_modified(self, view):
    if self.ignore:
        return

    edit = view.begin_edit()
    try:
        ...
    finally:
        self.ignore = True
        view.end_edit()
        self.ignore = False
0 Likes

#7

Oh, sweet, I didn’t think to try passing an empty string there.

I’m working on an elastic tabstops plugin, because I thought it’d be fun and pretty cool.
So I’m waiting for the buffer to be modified, and then I’m inserting spaces in preceding and following lines in order to fix the alignment. Ideally these insertions would be part of the same edit as the edit that caused the on_modified callback, but I didn’t think it was possible to get a reference to the previous edit and add to it. I’ve been thinking of doing something like figuring out what was added to the buffer, calling view.run_command(“undo”), and then starting an edit and adding the text back as well as the aligning spaces.
I sort of stopped working on it because I couldn’t figure out how to not get called back, but I’ll try the code you suggested and let you know how it goes. I tried using a flag before and I had trouble because it seemed like on_modified wouldn’t get called again until it had returned, i.e. until it had already set the flag back to false.

0 Likes

Plugin Api: on_modified should receive diffs
#8

If you turn the flag into a counter (increment before calling end_edit, decrement after, and check it equals 0 before proceeding), then you should be fine.

0 Likes

#9

The code you posted worked great. I had been clearing the flag on the line before the call to end_edit, instead of on the line after, which is why it wasn’t working.
Thanks!

0 Likes