Sublime Forum

API find() method?

#3

Would that function work the same way as if you’d dong a search using ctrl+f? Let me make clearer my end goals:

  • This search: {(?:^{}]+|(?0))} with the Regex and Highlight Matches options will outline all the outermost matched {}'s in my file. I would like to bind that whole operation to a hotkey.
  • This search:^\s*$ with Regex on followed by enter puts my cursor at the next empty line. In this case I don’t want to highlight all the occurrences in the file, I want to move my cursor to the next instance each time. I would like to bind this sequence of actions to a hotkey.

It seems like this should be very simple to accomplish. If somebody could explain to me how to either create a macro that will do this (doesn’t seem possible because macros don’t record searches) or how to write a plugin that would do a search with whatever options turned on I want and allow me to either highlight all the matches or just move to the next one I would be very appreciative.

I’ll try to look through that example you gave me but as you say it seems a little unclear to me.

p.s. If anybody could give me a good explanation (or point me to one) on how Views, RegionSets, Regions, Edits, and Windows … work(?) I would really appreciate it. Like what the difference between a View and a Region are and how RegionSets and Regions are related. I think I have a very rough understanding of it all but If someone wouldn’t mind laying it out a little more clearly for me I would really appreciate it.

As always thank you all for your help!

0 Likes

#4

Yeah, you want to use find.
sublimetext.com/docs/2/api_r … blime.View
find(pattern, fromPosition, )

so in your run function in your plugin, do something like this (not tested):

selection_regionset = view.sel() new_selection_region_list = ] for selection_region in selection_regionset: new_selection_region = view.find(r"^\s*$", selection_region.end()) new_selection_region_list.append(new_selection_region) selection_regionset.clear() #don't modify the regionset in place because it might make the for loop act funny for new_selection_region in new_selection_region_list: selection_regionset.add(new_selection_region)
The trick is that view.sel() returns a reference to a RegionSet, and you modify the view’s selection by modifying that RegionSet.

Really brief rundown:
A window holds multiple views. A view shows the contents of a buffer, and a region specifies a section of the view. An edit refers to a change to a view.

0 Likes

#5

[quote=“adzenith”]Really brief rundown:
A window holds multiple views. A view shows the contents of a buffer, and a region specifies a section of the view. An edit refers to a change to a view.[/quote]

^^^THIS^^^ is super helpful. Thank you. The rest of what you gave me is really helpful too but that piece helps me understand so much else.

follow ups:

  • If you add a region to a regionset does that highlight it automatically as if you’d searched for it? (And if not, how could I make that happen?)
  • What function would I use to advance the cursor? Something like show I’m guessing? But that looks like it just literally scrolls. I want to have the option to scroll to the next region in a set and put the cursor at the start of it.

I think with those answers I should be all set. Thank you so much.

0 Likes

#6

Bump? (Sorry if that’s considered bad forum etiquette here)
I still would like answers to these questions.

Also the code example provided above seems like it mostly works but I still have a couple of questions:

]If I run the saved search twice in a row it keeps the cursor in the same place. How would I get it to look for the next match? I’m guessing something about modifying the fromPosition of the find (selection_region.end() in my/your code) but I’m not exactly sure how to do this./]
]If it makes a match below the screen, it puts the cursor there but it doesn’t scroll to it. How would I make it scroll to it as well? Ideally I’m thinking I’d like to always put scroll so the cursor is in the middle of the screen after a match./]
]Also, how would I make it search in reverse instead of forward?/]

Thanks guys! You’ve all been really really helpful!

0 Likes

#7

Change view.sel() to change the selection.
You can use view.add_regions to highlight stuff.
Check out the API here: sublimetext.com/docs/2/api_reference.html

0 Likes

#8

I have been looking at the api docs but they are a little lacking. Would changing the selection help me do a reverse search, search beyond my current position, or scroll to my match as well as putting the cursor there? If so, how?

0 Likes

#9

Here’s an implementation of reverse search:

github.com/SublimeText/VintageE … ion.py#L67

AFAIK, there’s no built-in way of doing this.

0 Likes

#10

I haven’t looked at your questions in detail, so apologise in advance if the following code fragment is not helpful :smiley:

I use the following to search backward or forward for the search text (or phrase) named ‘to_find’, from the point ‘from_pt’:

if direction == 'down': # find next occurrence new_region = self.view.find(to_find, from_pt + 1, sublime.LITERAL) else: # find previous occurrence new_regions = (r for r in reversed(self.view.find_all(to_find, sublime.LITERAL)) \ if r.begin() < from_pt) try: new_region = new_regions.next() except StopIteration: continue if new_region: sels.add(new_region) self.view.show(new_region) # or self.view.show_at_center(new_region)
For the reverse search it essentially finds all occurrences of the phrase, then selects the first one of these occurrences that occurs before ‘from_pt’.

Delete the argument sublime.LITERAL in order to use your regex for the search. show_at_center (as opposed to ‘show’) will scroll the region to the centre of the view.

Andy.

0 Likes

#11

Hi guys, unfortunately business at work has kept me from working on this little project for a few weeks now. I was diving back into it today trying to remember/relearn all the helpful things you’ve all given me and I came across what seems like a promising alternative solution.

I think what I’m really trying to do is make use of the “find_next” and “find_prev” (and possibly “find_all”) commands that I see in the Default sublime-keymap and other places. I was trying to see how these commands are implemented but I don’t seem to be able to locate a FindNextCommand in any .py file that comes with the application (if I’m missing something obvious here please correct me and I’ll go on to commit sepuku). I’m guessing that this is because not all commands available have definitions that are visible to us. I would just call the commands blindly and trust that they would work but I first need to be able to set whatever the match that’s being made is (in either next, prev, or all).

Is this road a possibility or should I continue trying to duplicate the logic clumsily in my own python? I would much rather call the commands that already exist.

p.s. I’ve noticed sometimes that depending on where the cursor is, doing a straight find (which I guess is a find forward) might not always find what I’m looking for. Is there a way to have find look for the very next match and if it’s not after the cursor wrap around to the top of the document and continue searching? Thanks!

0 Likes

#12

I hate to be rude and “bump” but… anybody?

0 Likes

#13

You can use view.run_command(x) to run most commands you see in the keymap.

0 Likes

#14

Thank you for your reply. Unfortunately, this much I already knew. While I’m perfectly capable of running view.run_command(find_next), the problem remains of how to indicate what should be found next. The documentation says that find_next

but I have no idea how to set the “current search term”. Do you know how I would accomplish that? I’ve been trying to find out through the docs and the python sources available but nothing’s helped yet.

0 Likes

#15

The search term is what’s currently in the search box. I don’t know of any way to set this programmatically other than by calling slurp_find_string.

0 Likes

#16

Does slurp_find_string just grab what’s in the search box? If this is all true, would this be the right place to request a command that can be called to set the search term in other ways?

0 Likes

#17

Anybody? I hate to be a pain but this seems like fairly basic functionality that’s obscured currently, and I would really hate to have to re-invent the wheel (probably much more poorly) just to accomplish this.

0 Likes

#18

If I’m not mistaken the commands listed here are built-in, meaning they are most likely not Python code but C++.

The only possibility to retrieve the term you are searching for would be to hook into the find_next command after it was executed somehow and check for the selection if any. But that is (probably) not what you wanted so I’m afraid you have to write your own logic.

I think there was an option to wrap the search when EOF is reached.

0 Likes

#19

Does anybody know what this might be? Also, can anybody confirm the rest of this? Thanks!

0 Likes

#20

screencast.com/t/ss0lsGROuiWW

0 Likes

#21

[quote=“FichteFoll”]
screencast.com/t/ss0lsGROuiWW[/quote]

Ah yeah, I have that selected. It still doesn’t seem to work sometimes, but I can’t be more specific at the moment unfortunately.

0 Likes

#22

Is there any way I can talk to a developer about this access to the find function and using find_next, find_prev? I appreciate all the help I’ve been given by users but it seems like everybody is more or less guessing (based on plenty of experience but still). It would be great to hear something from the horse’s mouth so to speak. Does anybody know of a Forum user or email address I can direct my questions to? I’ll be sure to bring any information I find (if any) back to the forum here so the community can benefit from this. Thanks!

0 Likes