Sublime Forum

RegReplace Plugin

#18

Okay, so I now have scope searching working, but I am not committing it yet; I only have parts of it working.

I have it now where you can greedily find scopes and apply an optional find and replace with regex on those scopes (greedy or non-greedy).

I do not have non-greedy scope search done yet. I do not have literal search and replace on a scope done yet either. But it does work great on greedy scope searches with regex. I have been playing around with, and it just made all of my regex for comments obsolete. :smile: .

The rules for defining a scope find and replace will be different.

"scope_test": { "scope": "comment", "find": "SomeRegex", "replace": "PrependText\\0", "greedy_replace": false, "greedy_scope": true, "literal": false, "case": true }

0 Likes

#19

Should have a new release out tonight hopefully; if not, tomorrow for sure.

I have the “searching by scope and then applying regex to the scope region” feature pretty much done (I am skipping literal find and replace for now). Something to note though, due to the nature of Python’s subn function, you need to be careful with optional captured groups. Normally you will expect something like this to return an empty string for group 1 if this or that is not found.

(this|that)?(SomethingElse)

But subn, which I am using for applying regex to the the scope region, will return “unmatched group error” if you try and access group 1 and group 2 when this or that is not found.

You can still use the “?” in all sorts of other instances, but it might give you issues if you try and use it on a group. There are probably other scenarios you might need to be mindful of.

So to fix this, you would have to provide an empty option. This probably makes the “?” mark unneeded now, but I just want to illustrate what you have to do to fix the error.

(this|that|)?(SomethingElse)

This only applies to regex applied to scope regions. Regex with scope qualifiers goes through ST2’s api which does not suffer from this.
I could use Python’s findall function, but then I have to perform some coding gymnastics which I am not anxious to do right now, maybe down the road; we will see.

I also modified the folding command to not fold the trailing newline at the end of a selection. This makes folding regex much better, especially when targeting scopes like comments.

I also added a “mark” and “unmark” command where you can permanently highlight regions based on regex and also clear them; not sure how much use one might get out of this one, but it was easy to add, so I went ahead. It might come in handy.

0 Likes

#20

Version 0.8

  • New “mark” and “unmark” actions
  • Return error dialog showing regex issue
  • Add support for scope search with regex find and replace in scope region
  • Smarter folding of regex regions for “fold” action
  • Small tweak to non-greedy algorithm
  • Change default of optional replace parameter to “\0”; do not delete by default, leave unchanged by default.
  • Allow spaces in the “Regex Input Sequencer”

One big thing to stress is the change of the default value of replace. If you have definitions that relied on the old default of “”, the new default is “\0”. I decided it was better to not replace anything by default instead of deleting everything by default.

The other thing to note, is now when you create a malformed regex expression, you should get an error dialog giving you the internal error: things like unmatched brackets etc.

So now that scope selection is in, it is super easy to target difficult things like comments in every language. Here is a simple definition to delete all comments.

This is included in the default settings. It simply removes the comments leaving the line in tact

"remove_comments": { "scope": "comment", "find" : "(^\\n\\r]+)", "replace": "", "greedy_replace": true }

Here is the actual command:

{ "caption": "Remove: All Comments", "command": "reg_replace", "args": {"replacements": "remove_comments", "remove_trailing_spaces"], "find_only": true} },

Folding is much better now. Folding now will automatically adjust regions that have trailing newlines so as not to fold lines into each other.


Here are the fold/unfold commands:

// Folding { "caption": "Code Folding: Fold All Comments", "command": "reg_replace", "args": {"replacements": "remove_comments"], "action": "fold"} }, { "caption": "Code Folding: Unfold All Comments", "command": "reg_replace", "args": {"replacements": "remove_comments"], "action": "unfold"} }

The mark and unmark actions are pretty self explanatory. It simply allows you to highlight specific searches by whatever scope you choose. You can have multiple different regex highlights on the screen at the same time as long as you give them unique keys. How to use them is documented in the readme. The highlights will persist until you delete the region, or clear them with the unmark command, etc. I guess it might be good if you have things you are always looking for in certain files. You can make them stand out a lot. It might not be that useful, it is kind of similar to the “find_only” option; the only difference is it doesn’t disappear until you clear it. But it was easy to to add…so there it is.

0 Likes

#21

Hi,

I’m using this entry in the reg_replace.sublime-settings file:

"remove_empty_lines": { "find": "^ \\t]*$\\r?\\n", "replace": "", "scope_filter": "!comment"], "greedy": true, "case": true },

But if I execute it via the palette, only empty lines inside comments are deleted. Is the scope filter working correctly or is it a small bug?

I’ve used the v0.7 before I did the update to v0.8 today. Does an update overwrite the reg_replace.sublime-settings file (I’ve had stored
my code there before and I had to add it again after the update)?

Thanks for making this plugin, it’s a pleasure to work with!

Regards,
Highend

0 Likes

#22

I am aware that “!” is traditionally used in a “not” since in programming. In early development I was asking what people preferred, but I never got an answer…the plugin was really too new to have many people actually using it.

What you are using says the entire match must be of a “comment” scope to be a qualifying match. Without the “!”, it would mean if any part of the match was comment, it is a qualifying match. You can see the comments I left in the default settings file.

// scope_filter: an array of scope qualifiers for the match. // - Any instance of scope qualifies match: scope.name // - Entire match of scope qualifies match: !scope.name // - Any instance of scope disqualifies match: -scope.name // - Entire match of scope disqualifies match: -!scope.name

Bascially the notation you are using is incorrect for what you want. If you want to avoid comments you want to use the “-” symbol, which translates if any part of the match is a comment, it is a match to be ignored or disqualified. “-!” means if the entire match is of scope type, then it is disqualified.

You probably want this.

-comment

If there indeed is a bug let me know, and I will promptly fix it.

0 Likes

#23

No, there isn’t. You are absolute right, using -comment works as expected.

Thanks a lot for your help.


Highend

0 Likes

#24

I tried to use RegReplace to create a simple sequence to swap quotes of all double quoted strings, or all single quoted strings. I wanted to ensure it woud work in all languages regardless of whether they used “double quoted” or “single quoted” scope types. It was really hard, so I figured there had to be a better way. This lead me to add a new feature.

Version 0.9

  • Allow multipass on a scope region with regex with new “multi_pass_regex” parameter

This allowed me to use a scope search with regex qualifiers, and identify all string regions. I then used regex to determine if they were single or double quoted and find all internal quotes that needed to be escaped and unescaped within the string.

Regex defines for swapping from double to single quotes

"swap_quotes_to_single": { "scope": "string", "find" : "^\"(.*?)\"$", "replace": "'\\1'", "greedy_replace": false }, "escape_single_quotes": { "scope": "string", "find" : "^(\".*?(?<!\\\\))((?:\\\\]{2})*)'(.*?\")$", "replace": "\\1\\2\\'\\3", "greedy_replace": false, "multi_pass_regex": true }, "unescape_quotes_double": { "scope": "string", "find" : "^('.*?(?<!\\\\))((?:\\\\]{2})*)\\\\\"(.*?')$", "replace": "\\1\\2\"\\3", "greedy_replace": false, "multi_pass_regex": true },

Regex defines for swapping for single to double quotes

"swap_quotes_to_double": { "scope": "string", "find" : "^'(.*?)'$", "replace": "\"\\1\"", "greedy_replace": false }, "escape_double_quotes": { "scope": "string", "find" : "^('.*?(?<!\\\\))((?:\\\\]{2})*)\"(.*?')$", "replace": "\\1\\2\\\"\\3", "greedy_replace": false, "multi_pass_regex": true }, "unescape_single_quotes": { "scope": "string", "find" : "^(\".*?(?<!\\\\))((?:\\\\]{2})*)\\\\'(.*?\")$", "replace": "\\1\\2'\\3", "greedy_replace": false, "multi_pass_regex": true }

The commands

// Swap Quotes { "caption": "Replace: Swap Quotes to Single", "command": "reg_replace", "args": {"replacements": "escape_single_quotes", "swap_quotes_to_single", "unescape_double_quotes"], "find_only": true} }, { "caption": "Replace: Swap Quotes to Double", "command": "reg_replace", "args": {"replacements": "escape_double_quotes", "swap_quotes_to_double", "unescape_single_quotes"], "find_only": true} }

Now it is easy :smile:.

0 Likes

#25

Version 1.0

  • Add “literal” param for scope search defines.
  • Reduce code complexity

That finishes off everything I had planned (now I can stop tinkering with this). Scope searches with literal search qualifiers cannot use “multi_pass_regex” param (it will just be ignored). There is really no need for it since literals have no trouble finding all instances. If in the future people find a scenario where there is useful, I will add it, but until then, I think this plugin is feature complete.

I am open to improvements or new feature ideas; just drop a post here explaining what it is you want, and I will evaluate the request and decide.

If you find any bugs, let me know.

0 Likes

#26

Small fix:

Version 1.1

  • Faster unfold when many regions to unfold
0 Likes

#27

Didn’t realize that view.folded_regions() was not included in the latest official beta (not dev builds). So I added the old unfold method again with a threshold for those who are still using the latest official beta. A message will pop up when the threshold is reached alerting the user of what has happened and will explain that upgrading to the latest beta build will fix this. So now this will work on anybodies install as long as they are not grossly outdated.

Old methods of unfold will be deprecated on the next official beta.

Version 1.2.1

  • Account for people still on the last offical beta since view.folded_regions() is not included in that release. This method of unfold will be deprecated on new ST2 offical beta release.
0 Likes

#28

Version 1.3

  • Add the ability to apply regex sequences right before a file save event. Files are targeted with user defined file patterns.

Just add the on save sequences to reg_replace.sublime-settings
You can create as many on save sequences as you want, and they can all target different files. If a file matches multiple sequences, then the sequences will be strung together as one sequence.

Included example. **on_save ** is turned off by default.

// If on_save is true, RegReplace will search through the file patterns listed below right before a file is saved, // if the file name matches a file pattern, the sequence will be applied before the file is saved. // RegReplace will apply all sequences that apply to a given file in the order they appear below. "on_save": true, "on_save_sequences": // An example on_save_sequence that targets all files and trims trailing spaces // - file_pattern: an array of file patterns that must match for the sequence to be applied // - sequence: an array of replacement definitions to be applied on saving the file {"file_pattern": "*"], "sequence": "remove_trailing_spaces"]} ],

0 Likes

Whitespace handlers could play better together
#29

One more small update

Version 1.4

  • Allow on save regex sequences to define target files with regex as well as unix file name pattern matching
  • Add example “remove_dangling_commas” replacement definition
  • Add example on_save sequence using file regex pattern to remove dangling commas from sublime json files

Decided to allow “on_save_sequences” to use unix file name pattern matching and/or regex (you can use either or both).

Example:

"on_save_sequences": // An example on_save event that removes dangling commas from json files // - file_regex: an array of regex strings that must match the file for the sequence to be applied // - case: regex case sensitivity (true|false) false is default (this setting is optional) // - file_pattern: an array of file patterns that must match for the sequence to be applied // - sequence: an array of replacement definitions to be applied on saving the file { "file_regex": ".*\\.sublime-(settings|commands|menu|keymap|mousemap|theme|build|project|completions|commands)"], "file_pattern": "*.json"], "sequence": "remove_json_dangling_commas"] },

0 Likes

#30

Version 1.5.1

Now allows you to specify sequences to that only highlight instead of replace on save. Also added the ability to have the on save replacement sequences use multipass if desired. Highlight on save sequences and replace on save sequences can coexist; replacements are run first, and then highlights are performed. The read me gives more details.

0 Likes

#31

id like to excuse myself for not reading the instructions word by word and ask if there is an option to apply RegReplace commands to selection(s).

0 Likes

#32

Not yet…but there can be. I will have to look into.

0 Likes

#33

Should have regex under selection out fairly soon day or so. The code is pretty much done (it was pretty simple). I think I will just have a setting that you can enable, and then after that, if you a something selected, it will default to search selection only. If you have no selections (cursors are fine), then it will search the whole document.

It is pretty straight forward. If you are doing the special replacements that first target a scope and then apply the regex to that scope, you will have to ensure the entire scope is under the selection (I might change this in the future).

I might have it out by tomorrow if I am not feeling too lazy.

0 Likes

#34

thanks. :smile:
i was thinking exactly the same about the apllication.

0 Likes

#35

Finally finished this.

Version 1.6

  • Save under selection added (limits searches to selections if and only if selection exists)
  • Cleanup “highlight on save regions” when performing other regex searches

Replace Only Under Selection(s)
Sometimes you only want to search under selections. This can be done by enabling the selection_only setting in the settings file. By enabling this setting, regex targets will be limited to the current selection if and only if a selection exists. Auto replace/highlight on save events ignore this setting. If you have a command that you wish to ignore this setting, just set the no_selection argument to true. Highlight style will be forced to underline under selections if find_only is set to ensure they will show up.

0 Likes

#36

Is it possible to fold (rather than replace) on_save?

0 Likes

#37

check the first post for details.

0 Likes