Sublime Forum

[Solved] Trouble with on_text_command in plugin to extend selection

#1

I have a question about the on_text_command EventListener. I have a plugin that toggles off and on the “extend” attribute of the cursor movement keys. The toggle command is tied to a keybinding. When you toggle extend mode on you expand the area of selected text by using any of the cursor movement keys without the need to hold down the shift key. My plugin uses the on_text_command EventListener to add the {“extend”: True} attribute to the tupple that is passed to the listener from the “move” and “move_to” commands. For example, pressing the right arrow key sends the following to the on_text_command: (“move”, {‘by’: ‘characters’, ‘forward’: true}). My plugin changes this to (“move”, {‘by’: ‘characters’, ‘forward’ : ‘true’, ‘extend’: True}). This works, but I seem to be not understanding something about the proper syntax for setting up the ‘return’ from the on_text_command however. After reading the API I set it up like this:

if command == "move" :       
     return("move", {'forward' : args['forward'], 'by': args['by'], 'extend': True})

That didn’t work, so I’ve settled on using the run_command to execute the move and just returning with noop - like this:

if command == "move" :        #if move command, extend it.
  view.run_command("move", {'forward' : args['forward'], 'by': args['by'], 'extend': True})
  return 'noop'

I’m no python programmer, but that noop doesn’t feel right - even though it works. I’m wondering if someone who is familiar with the on_text_command could let me know if there is some other way to properly set up the return from on_text_command so as to execute the move/move_to command(s) directly from the return, without the need for the preceding run_command. Thanks very much!

1 Like

#2

hmm, I tried the same thing and can see in the console that the command gets rewritten:

class TestEventListener(sublime_plugin.EventListener):
    def on_text_command(self, view, command, args):
        print(command, args)
        if command == "move":
            return("move", {'forward' : args['forward'], 'by': args['by'], 'extend': True})

move {‘forward’: True, ‘by’: ‘characters’}
move {‘extend’: True, ‘forward’: True, ‘by’: ‘characters’}

it seems that the problem is, the on_text_command is called again, and the command is re-written again (to the same thing), so nothing happens - no command is executed. I guess it’s like an infinite loop?

the solution is to check if the args dict already has extend in it, and don’t return anything (/ return None) if it does:

class TestEventListener(sublime_plugin.EventListener):
    def on_text_command(self, view, command, args):
        print(command, args)
        if command == "move" and ('extend' not in args or not args['extend']):
            return("move", {'forward' : args['forward'], 'by': args['by'], 'extend': True})
1 Like

#3

Thanks! That fixed it.

0 Likes