Sublime Forum

Understanding the .window() method

#1

In some of the code repositories i have seen on Github, I have noticed the use of self.view.window().show_quick_panel(...) where the class inherits from the base sublime_plugin.TextCommand but in some cases, I have seen people use self.window.show_quick_panel(...) where the class inherits from the base sublime_plugin.WindowCommand. So how does .window work in ST3 API ?

0 Likes

#2

Are you sure you didn’t mean self.window in the second case? A text command exposes the view in an instance variable, while a window command exposes the window.

0 Likes

#3

Basically I’m trying to understand the difference between the following 2 commands:
This is an example code snippet where the 2 commands does the same thing but in different manners.

    import sublime
    import sublime_plugin

    class Example1Command(sublime_plugin.TextCommand):

	choices = ['Foo', 'Bar', 'Foo Bar']

	def run(self, edit):
		self.view.window().show_quick_panel(self.choices, self.on_done)

	def on_done(self, id):
		choice = self.choices[id]
		sublime.message_dialog("You have selected {}".format(choice))

class Example2Command(sublime_plugin.WindowCommand):

	choices = ['Foo', 'Bar', 'Foo Bar']

	def run(self):
		self.window.show_quick_panel(self.choices, self.on_done)

	def on_done(self, id):
		choice = self.choices[id]
		sublime.message_dialog("You have selected {}".format(choice))
1 Like

#4

functionally your examples are identical, but one uses a TextCommand when one wants to manipulate the view/buffer and a WindowCommand when the buffer/view is irrelevant, so in your two examples, the WindowCommand is more correct as you are just showing a quick panel and a dialog

0 Likes

#5

Is there a way to actually show a quick panel to the user, get their choice and insert it into the view ?

0 Likes

#6

In place of using sublime.message_dialog() you can use the run_command() method to run the insert command and give it the characters to insert. In that case your second example might look like this:

import sublime
import sublime_plugin


class Example2Command(sublime_plugin.WindowCommand):
    choices = ['Foo', 'Bar', 'Foo Bar']

    def run(self):
        self.window.show_quick_panel(self.choices, self.on_done)

    def on_done(self, id):
        if id >= 0:
            choice = self.choices[id]
            self.window.run_command("insert", {"characters": choice})

This also points out that the on_done method is given an index of -1 when the user closes the quick panel by pressing escape. In your original version that would show you a message dialog with the last item. If you want the user to be able to cancel without doing anything, you need to detect that.

If you’re using the TextCommand version, then you would use self.view.run_command() instead to do the same thing. Using run_command() to run insert on a view inserts it into that view directly; if you use run_command() on a window, it selects the view that’s currently focused automatically.

1 Like

#7

Thanks a lot @OdatNurd for the answer :+1:

0 Likes

#8

Yes. My bad. Edited it.

0 Likes

#9

FYI, sublime_lib offers a show_selection_panel function to make this common case a bit more convenient:

import sublime_plugin
from sublime_lib import show_selection_panel

class Example2Command(sublime_plugin.WindowCommand):
    choices = ['Foo', 'Bar', 'Foo Bar']

    def run(self):
        show_selection_panel(self.window, self.choices, on_select=self.on_select)

    def on_select(self, choice):
        self.window.run_command("insert", {"characters": choice})

on_select will only be called if a choice is made, and it will be passed the chosen value, not the index.

1 Like