Search code examples
pythonsublimetext2sublimetext3sublimetextsublime-text-plugin

Sublime Text plugin - how to find all regions in selection


How to find all regions in selection (regeon type too)? If we calling this method:

def chk_links(self,vspace):
    url_regions = vspace.find_all("https?://[^\"'\s]+")

    i=0
    for region in url_regions:
        cl = vspace.substr(region)
        code = self.get_response(cl)
        vspace.add_regions('url'+str(i), [region], "mark", "Packages/User/icons/"+str(code)+".png")
        i = i+1
    return i

in view context, e.g.:

chk_links(self.view)

all works fine, but in this way:

chk_links(self.view.sel()[0])

I get error: AttributeError: 'Region' object has no attribute 'find_all'

Full code of plugin you can find here

Sublime "View" method documentation


Solution

  • The Selection class (returned by View.sel()) is essentially just a list of Region objects that represent the current selection. A Region can be empty, so the list always contains a least one region with a length of 0.

    The only methods available on the Selection class are to modify and query it's extents. Similar methods are available on the Region class.

    What you can do is instead find all of the interesting regions as your code is currently doing, and then as you're iterating them to perform your check, see if they are contained in the selection or not.

    Here's a stripped down version of your example above to illustrate this (some of your logic has been removed for clarity). First the entire list of URL's is collected, and then as the list is iterated each region is only considered if there is NO selection or if THERE IS a selection AND the URL region is contained in the selection bounds.

    import sublime, sublime_plugin
    
    class ExampleCommand(sublime_plugin.TextCommand):
        # Check all links in view
        def check_links(self, view):
            # The view selection list always has at least one item; if its length is
            # 0, then there is no selection; otherwise one or more regions are
            # selected.
            has_selection = len(view.sel()[0]) > 0
    
            # Find all URL's in the view
            url_regions = view.find_all ("https?://[^\"'\s]+")
    
            i = 0
            for region in url_regions:
                # Skip any URL regions that aren't contained in the selection.
                if has_selection and not view.sel ().contains (region):
                    continue
    
                # Region is either in the selection or there is no selection; process
                # Check and
                view.add_regions ('url'+str(i), [region], "mark", "Packages/Default/Icon.png")
                i = i + 1
    
        def run(self, edit):
            if self.view.is_read_only() or self.view.size () == 0:
                return
            self.check_links (self.view)