Sublime Forum

Sublime Text 3 Cursor Bug with Plugin Launch Keybinding

#1

One of the users of my plugin (Glue) found this bug in the Windows version of Sublime Text 3 and based upon my testing it occurs in the Linux and Mac OSX versions as well. The plugin opens the input panel for user text entry on launch. The problem is that when the user has an editor view open (view 1) and you launch the Glue terminal window (view 2) with the keybinding (currently set as ctrl-alt-g but I have confirmed that it occurs with other keybindings as well), the cursor in view 1 no longer changes position in the editor view. You can use the up and down arrow keys and text entry without issues but the cursor remains stuck at the position where it was located when the plugin was launched. If view 1 is closed and reopened it works without issues. Closing view 2 does not appear to resolve the problem.

This appears to be an issue in Sublime Text 3 only. I am not able to reproduce it in the Linux, Mac, or Windows versions of Sublime Text 2.

Thoughts?

Thanks much,
Chris

GitHub issue report thread

0 Likes

#2

I have exactly the same problem, is there a way to reset the cursor function after using Glue?

0 Likes

#3

This is still an issue, unrelated to Glue. Running the following basic plugin via the console will still reproduce the issue (Mac/build 3176):

import sublime
import sublime_plugin

class ExampleCommand(sublime_plugin.TextCommand):
  def run(self, edit):

    window = sublime.active_window()
    self.view = window.new_file()
    
    self.view.insert(edit, 0, "Hello, World!")

Unless I’m missing something, how can I open a new file without destroying the text cursor in the previous active view?

0 Likes

#4

The weirdness that you’re seeing here is most likely caused by you assigning a new view to self.view inside the run method, which is not something that you should be doing. Altering the plugin above to the following fixes the problem:

import sublime
import sublime_plugin

class ExampleCommand(sublime_plugin.TextCommand):
  def run(self, edit):

    window = sublime.active_window()
    view = window.new_file()

    view.insert(edit, 0, "Hello, World!")

Generally speaking, in Sublime everything that displays text and allows you to edit it (open files, the input areas in the command palette and console, etc) are all views. When you define a TextCommand class, Sublime creates one instance of it for every view, and in that instance self.view represents the view that the command was created for, which allows the run method to know what view it’s running inside of.

(Similarly there is one instance of every WindowCommand per window, and self.window represents that window).

The edit object that you get as a parameter to the run method is your gateway to making modifications to views. It wraps all of the changes made by that command and to what view. Sublime creates it with code like this (in build 3176, this is at line 1064 in sublime_plugin.py, which you can find in the installation folder of Sublime):

edit = self.view.begin_edit(edit_token, self.name(), args)
try:
    return self.run(edit, **args)
finally:
    self.view.end_edit(edit)

What you’re seeing here in your problem is that when begin_edit() is called, it’s called for the view that you originally invoked the command in. Then when end_edit() gets called, because you assigned a new view to self.view, the view that ends the edit is not the same as the one that started it and hilarity ensues, where hilarity is defined as “any one of a number of weird unintended artifacts that the core was not expecting to deal with”.

I looked at the issue the OP referenced above, and it looks like this was a problem that was only affecting Sublime Text 3 and not Sublime Text 2. Un-coincidentally, in version 2 you could call begin_edit() and end_edit() yourself in order to get an edit object, but in version 3 that API is hidden and used by Sublime behind the scenes.

I didn’t look at the code of the package in question, but I would guess that it was doing something in version 2 that was either technically incorrect but the core reacted better to it, or it was not properly ported to Sublime Text 3 at the time.

1 Like

#5

Wow! Thanks for the detailed response. Lessons learnt.

0 Likes