Find in Region by selectors
One thing I would really like to see would be the ability to do a view.find_in_region_by_selectors(region, [selector1, selector2])
, which would essentially be an upgrade to the existing view.find_by_selector
method, to include:
a. a region within which to restrict the results
b. an array of selectors
The result would of course be sorted by position, and could include the entire scope of the region, or just the selector that matched, like this:
[(region, scope/selector), (region, scope/selector)...]
Why?
Firstly, I know that having an array for multiple selectors may seem pointless, because a selector can include a comma to perform an “or”. i.e. string, comment
.
But the problem with this, is that, if the text matching the selectors are adjacent, the region returned will include all of them, and most of the time, it is much more useful to have them separate.
Example:
take a python file containing:
"hello world"#comment
"foobar" # another comment
using the following code:
[view.substr(region) for region in view.find_by_selector('string, comment')]
will return the following:
[’“hello world”#comment\n"foobar"’, ‘# another comment’]
Now, imagine that one wants to know the location of all the comments in the file and all the strings in the file, while preserving the order. With the current API, the “most efficient” workaround is to do this (view.substr
is just for demonstration of what gets returned):
[view.substr(region) for region in sorted(view.find_by_selector('string') + view.find_by_selector('comment'))]
[’“hello world”’, ‘#comment\n’, ‘“foobar”’, ‘# another comment’]
which involves sorting a potentially incredibly massive list.
Now this is where the proposed region restriction comes in handy. Most of the time when I am developing plugins, I am only interested in a small subset of the file/view at a time, and I feel that being able to get results only for a particular region will make the plugin code easier to read/understand and write, while at the same time being more efficient. (Even if the same process would have to happen in the C code, it would be a lot quicker than processing it in Python I think.)
Importance: Minor
One possibility would be to alter the find_by_selector
method, to include the new functionality, in such a way as not to affect existing plugins that rely on the current behavior:
- make the
region
parameter optional (and come after the selector
), and default to the entire view if None
- if the
selector
parameter is a string, use the current functionality and return type (list of regions)
- if the
selector
parameter is an array, return the list of tuples, where each tuple would contain the region and the scope of that region or the selector that matched.
I guess if multiple selectors matched, and the API would return the matching selector(s) as opposed to the scope at the region, then the return value of the matched selectors could be a list, to avoid repeating the region in the return value. i.e.:
[(region1, [selector1, selector2]), (region2, [selector1])...]
instead of:
[(region1, selector1), (region1, selector2), (region2, selector1)...]