Sublime Forum

How to get the specific view's on modified event

#1

How can I bind on modified event to a specific view?

On my desperate last attempt what I came up is this:

Basically I want to get the input_view and output_view (output) into a variable and when input_view changes I want to update the output view. However the event listener - or the updates to the output view - should only be active when the plug in is toggled on.

The following code prints “modified” whenever ANY view is modified and not just the one I want… How can I make this work?

I appreciate the help!

class ToggleWatch(TextCommand):
	

	def is_enabled(self):
		return isCoffee(self.view)

	def run(self, edit):
		watch_mode = True
		print "watch_mode " , watch_mode
		Modified.inputview = self.view
		Modified.inputself = self
		Modified.output = self.view.window().new_file()
		output = Modified.output
		output.set_scratch(True)


		output.set_syntax_file('Packages/JavaScript/JavaScript.tmLanguage')
		no_wrapper = settings.get('noWrapper', True)

		args = '-p']
		if no_wrapper:
			args = '-b'] + args

		print "watch_mode yes"
		#while True :
		#	time.sleep(1)
		#	print "refreshed"
		res = brew(args, Text.get(self.view))
		if res"okay"] is True:
			output.insert(edit, 0, res"out"])
		else:
			output.insert(edit, 0, res"err"].split("\n")[0])

class Modified(sublime_plugin.EventListener):
    def __init__(self):
        pass

    def on_modified(inputself, inputview ):
        print "modified"
0 Likes

#2

Hello. Firstly, we cannot pass arguments to on_modified (AFAIK); after all, how would we supply these?
We cannot bind on_modified to a particular view. Instead, we can store details about which particular view is being edited.

In the following code I use the function isView to confirm that the modified event is taking place in a view, rather than some panel.
I use a dictionary (edit_info) in the event listener. When a view is edited for the first time I create a key based on the views’ id. I can then
store whatever information I need (for this particular view) in the dictionary.

You could perhaps store the view-object itself (or regions) in the dictionary, so that you might more easily update the buffer and
activate a particular view. I didn’t need this for the code below and, if I recall correctly, I had some problems with this previously.
Specifically, the view object from a Text or WindowCommand is not the same as that discovered in the event listener - which is why
I chose to use their id.

Be aware, of course, that modifying your output view will (I believe?) trigger another on_modified event: perhaps your use of a scratch
buffer circumvents this? Anyway, I hope that the following code may prove of some use.

[code]def isView(view_id):
# are they modifying a view (rather than a panel, etc.)
if not view_id: return False
window = sublime.active_window()
view = window.active_view() if window != None else None
return (view is not None and view.id() == view_id)

class CaptureEditing(sublime_plugin.EventListener):
edit_info = {}
def on_modified(self, view):
vid = view.id()
if not isView(vid):
# I only want to use views, not
# the input-panel, etc…
return
if not CaptureEditing.edit_info.has_key(vid):
# create a dictionary entry based on the
# current views’ id
CaptureEditing.edit_info[vid] = {}
cview = CaptureEditing.edit_info[vid]
# I can now store details of the current edit
# in the edit_info dictionary, via cview.[/code]

0 Likes

#3

Also AFAIK we cannot turn an event listener on and off. You could use a global boolean which is initially false, and your TextCommand could set this to True. The event listener would immediately return if this value is false.

0 Likes

#4

Thank you for your help, I deeply appreciate it! I will try to implement that on my code… Will post the results :smile:

0 Likes

#5

Not a problem. You might also consider (possibly) on_activated, so that your output-view is only updated when it is needed (perhaps…). Andy.

0 Likes

#6

Thanks to you agibsonsw, the following plugin for CoffeeScript has been patched.

Repo :

https://github.com/aponxi/Better-CoffeeScript-Sublime-Plugin

0 Likes

#7

Apparently, you can turn of specific event listeners but this is really hacky and requires messing with the sublime_plugin module located in the install directory. You would just have to iterate over e.g. all_callbacks'on_modified'], compare its base with your even listener (because it is instanced) and remove it from the list. However, usually you won’t need to do this and it is simpler to just add a condition at the beginning of the event handler method. (And you should only do this if you know what you are doing.)

Just for completion’s sake.

0 Likes

#8

I suppose it is also possible to place the event-listener code in a package and dynamically disable this package - even if the package consisted of a single file. I haven’t tried it though :wink:

0 Likes