Sublime Forum

on_modified replacement loop

#1

Im coding a plugin where I need to dynamically replace some placeholders after inserting a snippet.
Im using on_modified eventlistener for this.
So in the on_modified listener Im replacing the placeholder with a UUID.

The problem is that if I undo after the snippet insertion, Im not undoing the snippet insertion but the UUID replacement done by the on_modified handler. So that triggers another on_modified event that replace the placeholder with a new UUID.

In summary, after inserting a snippet, a new UUID is generated, which is fine.
If I press control-z instead of undoing the snippet inertion, Im replacing the UUID with a new UUID.

Is there any way to solve this?
Can I disable “undo” for the on_modified handler?

Thanks

0 Likes

#2

Not sure what you are doing exactly. It’s not possible to use the api to insert the snippet with uuid already? How is the snippet inserted? You can use view.command_history possibly to detect ‘undo’ within on_modified

0 Likes

#3

As far as I know, you cannot insert dynamic content via snippets (like a uuid), so what Im doing is inserting a placeholder %UUID% and then replace it in the on_modified handler. If there is any way to call a python method from the snippet, please let me know.
I will try to use the history to prevent sublime to go into this loop when undoing the snippet insertion.

Thanks!

0 Likes

#4

If you are modifying the snippet to include %UUID% anyway then can you not just embed the snippet’s *result *in your plug-in?

sublime.run_command("insert_snippet", { "contents": "My snippet %s" % UUID }) # haven't checked if this is the correct syntax

Or, if appropriate, just modify the view to achieve the same result as the snippet. But it’s difficult to tell without seeing some code.

You could even collect the snippets you need to use at the top of your plug-in (.py) as HEREDOC strings:

[code]HEADER =
“”"

%(fname)s """

sublime.run_command(“insert_snippet”, { “contents”: HEADER % { “fname”: UUID } } ) [/code]
You should, I believe, be able to embed ${1:something} in the HEREDOC so that it still behaves as a snippet, because the HEREDOC and snippet syntax for parameters differs.

Added: Believe I may have just created a dynamic snippet - Santa should be pleased with me :smile:

0 Likes

#5

Yes, a dynamic snippet:

[code]import sublime, sublime_plugin

MYSNIPPET =
“”"
Do this %(name)s and
then ${1:this}.
“”"
class DynamicSnip(sublime_plugin.TextCommand):
def run(self, edit):
someName = ‘Bob’
self.view.run_command(“insert_snippet”, { “contents” : (MYSNIPPET % { “name”: someName }) })[/code]

0 Likes

#6

That was my initial approach (but using a external file instead of a variable). The problem is that I want the users to be able to use sublime snippets capabilities: definitiaion syntax and search capabilities, so it was not an option for me.
I ended up using on_modified event to replace the placeholder by the dynamic generated UUID and then using command history to avoid the undo loop

0 Likes

#7

I know this is no longer relevant for the OP but it may be useful to others. It is possible to insert variables into (this version of a…) snippet and have them occupy the snippet’s field positions:

[code]import sublime, sublime_plugin

MYSNIPPET =
“”"
Do this ${1:%(name1)s} and %(name2)s.$0
“”"
class DynamicSnip(sublime_plugin.TextCommand):
def run(self, edit):
someName = ‘Bob’
otherName = ‘Ted’
self.view.run_command(“insert_snippet”, { “contents” : (MYSNIPPET %
{ “name1”: someName, “name2”: otherName }) })[/code]

0 Likes