Sublime Forum

View.replace() regex

#1

Is there a way to get view.replace() to use regex as it’s replace? I have a plugin which will take multiple find and replace strings from a file and carry them out, view.find() will parse a regex string but view.replace() will just replace it literally, not taking into account things like “\1”. I guess it doesn’t work because the way it works is I’m selecting all the matches of the pattern and then replacing them with the replacement afterwards, even if it did parse regex it wouldn’t know what “\1” referred to.

0 Likes

#2

Don’t do this kind of text operation with sublime API, just get the text, modify it and then replace the old text. Basically, what you want is viewtopic.php?f=6&t=10610#p42057 and doing stuff to the text with re module inbetween.

0 Likes

#3

Don’t see why regex replace shouldn’t be supported by the API.

0 Likes

#4

view.replace() is not a “Find and replace” function, it just a replace a given subset of the view by a given string.
IMHO, what we need is a way to call the replace Command with our arguments.

I think you can do what you want with:

View.find_all(pattern, <flags>, <format>, <extractions>) [Region] Returns all (non-overlapping) regions matching the regex pattern. The optional flags parameter may be sublime.LITERAL, sublime.IGNORECASE, or the two ORed together. If a format string is given, then all matches will be formatted with the formatted string and placed into the extractions list.

This method returns the position of your regexp (as View.find), but in addition you can give it a format and an empty list in the extractions argument.
After that you only have to loop through the lists and do the job (not tested):

lstpos = view.find_all(pattern, <flags>, <format>, lstrepl) for pos, repl in zip(lstpos, lstrepl): view.replace(edit, pos, repl)

0 Likes

#5

Remember, if you have a static list of regions, you should make modifications from the end of the buffer to the beginning, else you smash your offsets

0 Likes

#6

Oups, forget about this.

So something like:

lstpos = view.find_all(pattern, <flags>, <format>, lstrepl) for pos, repl in reversed(zip(lstpos, lstrepl)): view.replace(edit, pos, repl)

0 Likes

#7

The find_all API (in ST3) is not finding the results for me that the regex find from the UI pane does.

The goal is to replace a file with many UNCs into local paths. So:
\computer7\C$\testdir\test.bat
should get replaced into:
C:\testdir\test.bat

If I manually do a find-replace with regex in Sublime, it works:
Find: \\\S*\([A-Z])$
Replace With: \1:

However, if I try to find the regex string via the API, I get no results:

[code]import sublime, sublime_plugin
class PathUncToLocalCommand(sublime_plugin.TextCommand):
def run(self, edit):
RegionsResult = self.view.find_all("\\\S*\([A-Z])$", sublime.IGNORECASE)
print(RegionsResult)

This is the string to find via regex

\computer7\C$\testdir\test.bat[/code]

RegionsResult is an empty list and does not contain any results when trying to do the regex search via the API. However a match is found when doing the regex search manually from the find pane.

0 Likes

#8

Your code raise an exception in my ST2, not on your side ?

You must use a raw string (r"") for your regexp, or transform it in a correct Python string (double every ):

RegionsResult = self.view.find_all(r"\\\\\S*\\([A-Z])\$", sublime.IGNORECASE)
0 Likes

#9

I do this kind of stuff in my RegReplace plugin. I don’t want to go into all the specifics right now, but you can check out the source if you want. You can create reg replace sequence commands with the RegReplace plugin, or you can dig around and see what I did.

ST2: github.com/facelessuser/RegReplace
ST3: github.com/facelessuser/RegReplace/tree/ST3

Anyways, maybe this will solve your issue, or help you solve your issue.

0 Likes

#10

Thanks bizoo… adding the r"" to indicate raw string did the trick.

It is in fact possible to do regex-replace via sublime API with the “format string” and “extractions list”. The following code works as an example of how to do a regex-replace from Sublime API.

[code]import sublime, sublime_plugin

class PathUncToLocalRegexReplaceExampleCommand(sublime_plugin.TextCommand):
def run(self, edit):
ListReplacements = ]
RegionsResult = self.view.find_all(r"\\(\S)\([A-Z])$", sublime.IGNORECASE, “\2:”, ListReplacements)
for i, thisregion in reversed(list(enumerate(RegionsResult))):
self.view.replace(edit, thisregion, ListReplacements
)[/code]

Above example successfully replaced:
\computer7\C$\testdir\test.bat
into:
C:\testdir\test.bat*

0 Likes

#11

[quote=“robertcollier4”]Thanks bizoo… adding the r"" to indicate raw string did the trick.

It is in fact possible to do regex-replace via sublime API with the “format string” and “extractions list”. The following code works as an example of how to do a regex-replace from Sublime API.

[code]import sublime, sublime_plugin

class PathUncToLocalRegexReplaceExampleCommand(sublime_plugin.TextCommand):
def run(self, edit):
ListReplacements = ]
RegionsResult = self.view.find_all(r"\\(\S)\([A-Z])$", sublime.IGNORECASE, “\2:”, ListReplacements)
for i, thisregion in reversed(list(enumerate(RegionsResult))):
self.view.replace(edit, thisregion, ListReplacements
)[/code]

Above example successfully replaced:
\computer7\C$\testdir\test.bat
into:
C:\testdir\test.bat*

I used to use the API to do regex replaces, but the regex engine is different from the Python one, and I found it wasn’t as flexible as the Python one, but yes you can use extractions in the API which is what I used to do up until recently. I found using Python’s re module and reading the view buffer to be easier when doing complex stuff.[/quote]

0 Likes

#12

It’s not all that bad. You can embed flags in the sublime style regex:

(?s)ones.*Priorities

so .* will match new lines

Pretty sure it uses the the perl variant of the boost regex lib

0 Likes