Sublime Forum

[HELP] Make ENTER act differently if output panel is open

#1

I’m trying to create a plugin so when a output panel is open when I press ENTER it closes the output panel, where I am stuck is making ENTER use the default behaviour when the output panel isn’t open.

Here is my code so far

import sublime
import sublime_plugin


class CheckBufferCommand(sublime_plugin.TextCommand):
    def run(self, window):
        view = sublime.active_window().get_output_panel('buffer')
        if view.window():
            self.view.window().destroy_output_panel('buffer')
        else:
            # Stuck here

The key binding I set up

{ "keys": ["enter"], "command": "check_buffer" },

I’ve been stumped for well over an hour.

1 Like

#2

As written above the code that you’ve provided doesn’t seem to track with the description of how you want the plugin to work.

    def get_output_panel(self, name):
        """ deprecated, use create_output_panel """
        return self.create_output_panel(name)

Calling get_output_panel() is thus the same as create_output_panel(), which either returns you the view of the panel that already exists, or creates a new panel first and then returns that. In either case, the result is that the first line of the plugin is ensuring that a panel named ‘buffer’ exists.

The existence of a panel and it’s display on the screen are separate concepts; panels can exist and not be open, in which case they persist their contents and can be re-displayed by way of commands or the panel switcher in the status bar.

It would be my assumption that most panel views have an associated window, in which case if view.window(): is probably always True, which makes the condition always trigger, destroying the output panel that was just created.

As such the code in the else: can’t be reached, but by the same token the command as written would appear to just create a panel and then immediately destroy it again.

There may or may not also be a logical disconnect in that you’re asking Sublime for the panel in the currently active window and then destroying the panel in the window that the check_buffer command is being executed in, which in theory could be different windows depending on how the command is ultimately executed.

Note also that the first parameter to a TextCommand is always a sublime.Edit and not a sublime.Window, so the definition of your run method has a deceptively named argument.

Circling back to your question, the subject of what the Enter key does by default is to some degree open to debate; most of the time it’s going to start a new line in the buffer, but it might also select an item in a panel, confirm the entry of text in an input panel or even do something completely unrelated depending on what key bindings and/or packages the user has.

In a case like that, the best tactic is generally to create your key binding with a context that ensures that it’s only active in the situations where you want it to be active and inactive in the rest of cases. Doing that, you can design your check_buffer command to assume that if it’s being invoked, it can directly do what you want it to do without having to do any checks, and Sublime will take care of what the key should do when it’s not in your particular situation.

All that being said, the hide_panel command will hide the currently visible panel. There is also a default context of panel that takes an operand of a panel name so you can make key bindings that apply only when certain panels are visible.

Taken together, a key binding such as the following will make the Enter key hide the build output if it’s open, but otherwise the key does what it would normally do:

{
    "keys": ["enter"],
    "command": "hide_panel",
    "context": [
        { "key": "panel", "operator": "equal", "operand": "output.exec"}
    ],
},

That sounds more like what you want to do in your case, though you probably need to change the panel name to the one appropriate for what you’re trying to do.

If your intention is to literally destroy a panel as in the code above (i.e. it no longer appears in the panel switcher) your plugin command above just needs to take as a parameter the name of the panel to destroy and use that in the call to destroy_output_panel() without having to do any other checks.

1 Like

#3

Thank you @OdatNurd for such a well detailed explanation.

I would of never thought about just adding another key binding which hides the output panel, but that is exactly what I was looking for, just tested it out and it’s working perfectly.

Thanks again :slight_smile:

1 Like