Home Download Buy Blog Forum Support

ExpandSelectionToScope

ExpandSelectionToScope

Postby cursors_foiled_again on Wed Jul 20, 2011 3:13 am

Hello All,

I have been working on a command that selects words matching your current selection in the current scope (based on braces). Basically like super+d but grabs everything in scope at once.

Currently,
It selects matches to the nearest pair of braces {}
It includes a for/if/foreach/function/class line preceding the {, since that almost always makes sense.
If all the matches are already selected, it selects to the next containing pair of braces.
It looks for whole words, because in practice for me that has seemed better, but that would probably make a good config option.
Relies on the langage grammer for the file to ignore braces in comments and strings.
It doesn't really understand any language scope rules, just goes off of a generalized c-like assumption about braces.
It doesn't understand scope in braceless languages (python), but does select all matches in the file.

I'm new to python, and to sublime, so I was thinking I would post this here to see if anyone had any suggestions on how to improve the code (specifically on style, but also suggestion for features are welcome). Also, if people think this would be useful to others, I'd be happy to share and to open source it. Where would be the most appropriate place to post this code so others can find it?

Thank you

Code: Select all
import sublime, sublime_plugin
import re

class ExtendSelectionToScopeCommand(sublime_plugin.TextCommand):
   def scopeStart(self, brace_pos):
      return not self.view.substr(brace_pos) == "}"

   def run(self, edit):
      #print "Extend Selection To Scope"
      if self.view.sel()[0].a == self.view.sel()[0].b:
         sel = self.view.sel()
         sel.add(self.view.word(sel[0].a));                   
         return

      pos = self.view.sel()[0].a
      word = self.view.substr(self.view.sel()[0]);
      

      # FIND SCOPE DELIMS
      regex_parts = [];
      regex_parts.append("((class|function)[^\;]*?\{)");
      regex_parts.append("((if|while|foreach)[^\;]*?\{)");
      regex_parts.append("(for.*\)[^\;]*?\{)");
      regex_parts.append("(\{)");
      regex_parts.append("(\})");
      regex = "|".join(regex_parts);
      scope_delims = self.view.find_all(regex)

      clean_scope_delims = []
      for match in scope_delims:
         if (not self.view.match_selector(match.a, "(string|comment)")):
            clean_scope_delims.append(match)
      scope_delims = clean_scope_delims

      

      # FIND SURROUNDING SCOPES
      surrounding_scopes = []
      scope_stack = []
      for scope_delim in scope_delims:
         brace_pos = scope_delim.a   
         if self.scopeStart(brace_pos):
            scope_stack.append(sublime.Region(brace_pos, brace_pos))                     
         elif len(scope_stack) > 0:
            scope_stack[-1] = sublime.Region(scope_stack[-1].a, brace_pos)
            if scope_stack[-1].a < pos and scope_stack[-1].b >= pos:
               surrounding_scopes.append(scope_stack[-1])
            scope_stack.pop()
      
      surrounding_scopes.append((sublime.Region(0, self.view.size())))
      
      

      #FIND MATCHES
      matching_words = self.view.find_all("\W"+re.escape(word)+"\W")
      for index in range(0, len(matching_words)):
         matching_words[index] = sublime.Region(matching_words[index].a+1, matching_words[index].b-1)

      
      
      #SELECT MATCHES
      surrounding_scopes.reverse()
      sel = self.view.sel()
      extended = False
      while extended == False and len(surrounding_scopes) > 0:
         target_scope = surrounding_scopes.pop()
         for matching_word in matching_words:
            if matching_word.a >= target_scope.a and matching_word.b <= target_scope.b:
               if not sel.contains(matching_word):
                  extended = True
               sel.add(matching_word)
cursors_foiled_again
 
Posts: 5
Joined: Thu Jul 14, 2011 9:05 pm

Return to Plugin Development

Who is online

Users browsing this forum: Yahoo [Bot] and 12 guests