Sublime Forum

Bounded Quick Add Next

#1

This is a quick little plugin you can drop in your user package and use in addition to ⌘D and ⌘K⌘D (where skip_last is true in the command arguments). Basically, it searches for the current word, albeit bounded by \b in the regex (that is, word boundaries - so it won’t work for everything [for example, searching for #/ using this plugin will not work since # and / are both word boundaries themselves, so consider using a different key instead of replacing ⌘D and such]).

It’s handy if you’re a terrible human being and use single-letter variable names other than (because there’s really no better way to refer to texture coordinates and vector components than with UVW and XYZ), which ⌘D will punish you for doing by finding every instance of that character. So, your best bet is to just not be an absolutely loathsome person who uses single letter variables (like all you horrible web developers do), but if you happen to be someone the entire world should despise because you absolutely cannot resist the allure of single letter variables like the absolutely awful depth-spawn that you might be, then this plugin is probably for you.

It’s also handy if you have variable names that share words, like event and event_name and event_id, in which case ⌘D will unintentionally hate you and you’re not an awful person, just unlucky. In those cases, it’s probably fairly useful, though chances are you could ⌘K⌘D around the false positives without a lot of problems.

This came up on IRC (as usual) and it’s something I’d experienced before, so I figured I might as well write a plugin for it. Did a cursory search and found nobody else had done it either, but I got lazy, so it wasn’t thorough. Probably been solved before.

So, drop this in your user package if you think you might need it for something:

[code]# bounded_grab_next.py
import sublime, sublime_plugin, re

class BoundedGrabNextCommand(sublime_plugin.TextCommand):
def init(self, p):
super(BoundedGrabNextCommand, self).init§
self._last_word = None
self._last_regex = None
#/init

def run(self, edit, skip_last = False):
last_selection = None
view = self.view

selections = view.sel()
last_selection = selections-1]

# If the last selection is empty, expand to the current word. In other
# words, just do the usual Cmd+D operation.
if last_selection.a == last_selection.b:
  view.window().run_command('find_under_expand')
  return
#/if

regex = None
word = view.substr(last_selection)
if self._last_word == word:
  regex = self._last_regex
else:
  regex = "\\b{0}\\b".format(re.escape(word))
#/if

if skip_last:
  selections.subtract(last_selection)
#/if

last_point = max(last_selection.a, last_selection.b)
next_find = view.find(regex, last_point)
if next_find is None:
  next_find = view.find(regex, 0)

  while next_find and selections.contains(next_find):
    next_find = view.find(regex, next_find.b)
  #/while
#/if

if next_find:
  selections.add(next_find)
#/if

self._last_word = word
self._last_regex = regex

#/run
#/BoundedGrabNextCommand[/code]

The command takes a single argument, skip_last, which behaves mostly the same as ⌘K⌘D. I rarely find this useful, and in this case the chance of a false positive is a bit lower than normal, so you may not need it.

You’ll want to set up a keybinding for it as well. Here’s an example that replaces the “Use Selection for Find” and “Use Selection for Replace” bindings because I never use those. Adjust as necessary, obviously.

{ "command": "bounded_grab_next", "args": {"skip_last": false}, "keys": "super+e"]}, { "command": "bounded_grab_next", "args": {"skip_last": true}, "keys": "super+shift+e"]} ]

So, have fun.

0 Likes

#2

I tried it with ST 3 (Build 3007) and used ctrl+e and ctrl+shift+e as the shortcuts (Windows system).

I get this in the console when I use ctrl+e:

Traceback (most recent call last): File "D:\Users\Highend\Downloads\Sublime Text 3\sublime_plugin.py", line 376, in run_ return self.run(edit, **args) File "D:\Users\Highend\Downloads\Sublime Text 3\Data\Packages\User\BoundedQuickAddNext.py", line 16, in run last_selection = selections-1] File "D:\Users\Highend\Downloads\Sublime Text 3\sublime.py", line 392, in __getitem__ raise IndexError() IndexError

Should it work with ST 3 or ST 2 only atm?

0 Likes

#3

It’s for Sublime Text 2. I don’t plan to do anything for Sublime Text 3 until there’s an official API reference.

0 Likes

#4

I added a small detail to the last part of the script:

if next_find: selections.add(next_find) view.show(next_find) #/if

This will scroll to the added selection when it’s not visible.

0 Likes

#5

That’s a good idea.

0 Likes

#6

Note that if you start with an empty selection, then cmd+d (find_under_expand) will search by whole words automatically. If you start with a non-empty selection, then it will search for any instance of the text.

0 Likes