def select(self, item): """Select action to perform.""" if "action" in item: if item['action'] == "fold": self.folds += item["sequence"] elif item['action'] == "unfold": self.unfolds += item["sequence"] elif item['action'] == "mark": self.highlights += item['sequence'] else: error("action %s is not a valid action" % item["action"]) elif "highlight" in item and bool(item['highlight']): sublime.message_dialog( "RegReplace:\n\"on_save_sequence\" setting option '\"highlight\": true' is deprecated!" "\nPlease use '\"action\": \"mark\"'.") self.highlights += item['sequence'] else: self.replacements.append({ "sequence": item['sequence'], "multi_pass": True if "multi_pass" in item and bool(item['multi_pass']) else False })
def perform_action(self): """Perform action on targed text.""" status = True if self.action == 'fold': # Fold regions self.view.fold(self.ignore_ending_newlines(self.replace_obj.target_regions)) elif self.action == 'unfold': # Unfold regions try: self.view.unfold(self.ignore_ending_newlines(self.replace_obj.target_regions)) except Exception: error("Cannot unfold! Please upgrade to the latest stable beta build to remove this error.") elif self.action == 'mark': # Mark targeted regions if 'key' in self.options: color = self.options['scope'].strip() if 'scope' in self.options else DEFAULT_HIGHLIGHT_COLOR style = self.options['style'].strip() if 'style' in self.options else DEFAULT_HIGHLIGHT_STYLE self.set_highlights(self.options['key'].strip(), style, color) elif self.action == 'unmark': # Unmark targeted regions if 'key' in self.options: self.clear_highlights(self.options['key'].strip()) else: # Not a valid action status = False return status
def select(self, item): """Select action to perform.""" if "action" in item: if item['action'] == "fold": self.folds += item["sequence"] elif item['action'] == "unfold": self.unfolds += item["sequence"] elif item['action'] == "mark": self.highlights += item['sequence'] else: error("action %s is not a valid action" % item["action"]) elif "highlight" in item and bool(item['highlight']): sublime.message_dialog( "RegReplace:\n\"on_save_sequence\" setting option '\"highlight\": true' is deprecated!" "\nPlease use '\"action\": \"mark\"'." ) self.highlights += item['sequence'] else: self.replacements.append( { "sequence": item['sequence'], "multi_pass": True if "multi_pass" in item and bool(item['multi_pass']) else False } )
def greedy_scope_replace(self, regions, re_find, replace, greedy_replace, multi): """ Greedy scope replace """ total_replaced = 0 try: for region in reversed(regions): replaced = 0 string = self.view.substr(region) extraction, replaced = self.apply_scope_regex( string, re_find, replace, greedy_replace, multi) if replaced > 0: total_replaced += 1 if self.find_only or self.action is not None: self.target_regions.append(region) else: self.view.replace(self.edit, region, extraction) except Exception as err: print(str(traceback.format_exc())) error('REGEX ERROR: %s' % str(err)) return total_replaced return total_replaced
def greedy_scope_replace(self, regions, re_find, replace, greedy_replace, multi): """Greedy scope replace.""" total_replaced = 0 tabs_to_spaces = self.view.settings().get('translate_tabs_to_spaces', False) if tabs_to_spaces: self.view.settings().set('translate_tabs_to_spaces', False) try: for region in reversed(regions): sub_regions = deque() replaced = 0 string = self.view.substr(region) extraction, replaced = self.apply_scope_regex( string, re_find, replace, greedy_replace, multi, region.begin(), sub_regions ) if replaced > 0: total_replaced += 1 if self.find_only or self.action is not None: self.target_regions.extend(sub_regions) else: self.view_replace(region, extraction) except Exception as err: print(str(traceback.format_exc())) error('REGEX ERROR: %s' % str(err)) return total_replaced if tabs_to_spaces: self.view.settings().set('translate_tabs_to_spaces', True) return total_replaced
def find_and_replace(self): """ Walk the sequence finding the targeted regions in the text. If allowed, replacements will be done as well. """ if self.use_test_buffer: replace_list = sublime.load_settings( 'reg_replace_test.sublime-settings').get('replacements', {}) else: replace_list = rrsettingsrules.get('replacements', {}) result_template = '%s: %d regions;\n' if self.panel_display else '%s: %d regions; ' results = '' # Walk the sequence # Multi-pass only if requested and will be occurring if self.multi_pass and not self.find_only and self.action is None: # Multi-pass initialization current_replacements = 0 total_replacements = 0 count = 0 # Sweep file until all instances are found # Avoid infinite loop and break out if sweep threshold is met while count < self.max_sweeps: count += 1 current_replacements = 0 for replacement in self.replacements: # Is replacement available in the list? if replacement in replace_list: pattern = replace_list[replacement] current_replacements += self.replace_obj.search( pattern, 'scope' in pattern) total_replacements += current_replacements # No more regions found? if current_replacements == 0: break # Record total regions found results += 'Regions Found: %d regions;' % total_replacements else: not_found = [] for replacement in self.replacements: # Is replacement available in the list? if replacement in replace_list: pattern = replace_list[replacement] results += result_template % ( replacement, self.replace_obj.search(pattern, 'scope' in pattern)) else: not_found.append(replacement) if not_found: error("%d rules not found! See console." % len(not_found)) print('\n'.join( ['RegReplace: "%s" not found!' % r for r in not_found])) return results
def process_test_cmd(self, test): """Process the test command.""" remove = [] okay = True for k, v in test.items(): if k not in self.test_keys: remove.append(k) elif ( k == 'replacements' and not isinstance(v, list) or not all(isinstance(x, str) for x in test['replacements']) ): error('You need to specify valid replacements in your sequence for testing!') okay = False break elif k in self.test_bool_keys: if v is None: remove.append(k) elif not isinstance(v, bool): error('"%s" must be a boolean value!') okay = False break elif k == 'action': if v is None: remove.append(k) elif not isinstance(v, str): error('"action" must be a string!') okay = False break elif k == 'options': if v is None: remove.append(k) elif not isinstance(v, dict): error('"options" must be a dict!') okay = False break else: for k1, v1 in v.items(): if k1 not in self.test_subkeys: remove.append((k, k1)) elif not isinstance(v1, str): error('"%s" must be a string!' % k1) okay = False break if okay: # Remove any items set to None or invalid keys for r in remove: if isinstance(r, tuple): del test[r[0]][r[1]] else: del test[r] return okay
def find_and_replace(self): """ Walk the sequence finding the targeted regions in the text. If allowed, replacements will be done as well. """ if self.use_test_buffer: replace_list = sublime.load_settings('reg_replace_test.sublime-settings').get('replacements', {}) else: replace_list = rrsettingsrules.get('replacements', {}) result_template = '%s: %d regions;\n' if self.panel_display else '%s: %d regions; ' results = '' # Walk the sequence # Multi-pass only if requested and will be occuring if self.multi_pass and not self.find_only and self.action is None: # Multi-pass initialization current_replacements = 0 total_replacements = 0 count = 0 # Sweep file until all instances are found # Avoid infinite loop and break out if sweep threshold is met while count < self.max_sweeps: count += 1 current_replacements = 0 for replacement in self.replacements: # Is replacement available in the list? if replacement in replace_list: pattern = replace_list[replacement] current_replacements += self.replace_obj.search(pattern, 'scope' in pattern) total_replacements += current_replacements # No more regions found? if current_replacements == 0: break # Record total regions found results += 'Regions Found: %d regions;' % total_replacements else: not_found = [] for replacement in self.replacements: # Is replacement available in the list? if replacement in replace_list: pattern = replace_list[replacement] results += result_template % (replacement, self.replace_obj.search(pattern, 'scope' in pattern)) else: not_found.append(replacement) if not_found: error("%d rules not found! See console." % len(not_found)) print('\n'.join(['RegReplace: "%s" not found!' % r for r in not_found])) return results
def convert(self, text): """ Convert the source to an object. Test object will be compiled separately. """ obj = {} test = {} try: # Examine the python code to ensure it it is safe to evaluate. # We will evaluate each statement and see if it is safe. # None and numbers are ignored unless it is in the `arg` dictionary. # All the top level variables are either string, boolean, list of strings, or dictionary. code = ast.parse(text) for snippet in code.body: if ast_class(snippet) == 'Assign' and len( snippet.targets) == 1: target = snippet.targets[0] if ast_class(target) == 'Name': name = target.id class_name = ast_class(snippet.value) if name in self.string_keys and class_name == 'Str': obj[name] = compile_expr(snippet.value) elif name in self.bool_keys and class_name == 'Name' and snippet.value.id in ( 'True', 'False'): obj[name] = compile_expr(snippet.value) elif name == 'scope_filter' and class_name == 'List': if all( ast_class(l) == 'Str' for l in snippet.value.elts): obj[name] = compile_expr(snippet.value) elif name == 'args' and class_name == 'Dict': if self.eval_dict(snippet.value): obj[name] = compile_expr(snippet.value) elif name == 'test' and class_name == 'Dict': if self.eval_dict(snippet.value): test = compile_expr(snippet.value) except Exception as e: error('Could not read rule settings!\n\n%s' % str(e)) return None, None return obj, test
def process_selections(self, orig_find, selection_only, selection_inputs, literal): """Process selections if necessary.""" sel_start = [] sel_size = [] find = orig_find errors = False sels = self.view.sel() if selection_only and selection_inputs: error( "Cannot use 'selection_inputs' with global option 'selection_only'!" ) errors = True elif selection_only: sel_start = [] sel_size = [] for s in sels: sel_start.append(s.begin()) sel_size.append(s.size()) elif selection_inputs: try: sel_inputs = [] count = 0 for s in sels: assert s.size( ) <= self.sel_input_max_size, "Exceeded max selection size" engine = self.normal_module if not literal and self.extend: engine = self.extend_module sel_inputs.append(self.view.substr(s)) count += 1 assert count <= self.sel_input_max_count find = RegexInputFormatter(engine).format(orig_find, *sel_inputs, sel=sel_inputs) except Exception: print(str(traceback.format_exc())) error('Failed to process selection inputs.') errors = True return find, sels, sel_start, sel_size, errors
def greedy_scope_replace(self, regions, re_find, replace, greedy_replace, multi): """Greedy scope replace.""" total_replaced = 0 try: for region in reversed(regions): replaced = 0 string = self.view.substr(region) extraction, replaced = self.apply_scope_regex(string, re_find, replace, greedy_replace, multi) if replaced > 0: total_replaced += 1 if self.find_only or self.action is not None: self.target_regions.append(region) else: self.view_replace(region, extraction) except Exception as err: print(str(traceback.format_exc())) error('REGEX ERROR: %s' % str(err)) return total_replaced return total_replaced
def convert(self, text): """ Convert the source to an object. Test object will be compiled separately. """ obj = {} test = {} try: # Examine the python code to ensure it it is safe to evaluate. # We will evalute each statement and see if it is safe. # None and numbers are ignored unless it is in the arg dictionary. # All the top level variables are either string, bool, list of strings, or dict. code = ast.parse(text) for snippet in code.body: if ast_class(snippet) == 'Assign' and len(snippet.targets) == 1: target = snippet.targets[0] if ast_class(target) == 'Name': name = target.id class_name = ast_class(snippet.value) if name in self.string_keys and class_name == 'Str': obj[name] = compile_expr(snippet.value) elif name in self.bool_keys and class_name == 'Name' and snippet.value.id in ('True', 'False'): obj[name] = compile_expr(snippet.value) elif name == 'scope_filter' and class_name == 'List': if all(ast_class(l) == 'Str' for l in snippet.value.elts): obj[name] = compile_expr(snippet.value) elif name == 'args' and class_name == 'Dict': if self.eval_dict(snippet.value): obj[name] = compile_expr(snippet.value) elif name == 'test' and class_name == 'Dict': if self.eval_dict(snippet.value): test = compile_expr(snippet.value) except Exception as e: error('Could not read rule settings!\n\n%s' % str(e)) return None, None return obj, test
def run(self, edit): """Parse the regex panel, and if okay, run the test entry in the active view.""" obj, test = ConvertPythonSrc2Obj().convert(self.view.substr(sublime.Region(0, self.view.size()))) # Something went wrong. if test is None or obj is None: return # Ensure test command is valid. if not self.process_test_cmd(test): return # Copy all regex rules that are to be included in the test sequence test_rules = {} rules = sublime.load_settings('reg_replace_rules.sublime-settings').get('replacements', {}) for x in test['replacements']: if x in rules: test_rules[x] = rules[x] # Ensure the bare minimum items are in the current test rule # and ensure the regex (if any) compiles. # If all is well, execute the command. if not obj.get('name'): error('A valid name must be provided!') elif obj.get('scope') is None and obj.get('find') is None: error('A valid find pattern or scope must be provided!') else: try: if obj.get('find') is not None: if obj.get('selection_inputs', False): pass elif obj.get('literal', False): flags = 0 pattern = re.escape(obj['find']) if obj.get('literal_ignorecase', False): flags = re.I re.compile(pattern, flags) else: extend = sublime.load_settings( 'reg_replace.sublime-settings' ).get('extended_back_references', False) if extend: bre.compile_search(obj['find']) else: re.compile(obj['find']) test_rules[obj['name']] = obj settings = sublime.load_settings('reg_replace_test.sublime-settings') settings.set('format', '3.2') settings.set('replacements', test_rules) window = sublime.active_window() if window is not None: view = window.active_view() if view is not None: test["use_test_buffer"] = True view.run_command('reg_replace', test) except Exception as e: error('Regex compile failed!\n\n%s' % str(e))
def perform_action(self): """Perform action on targeted text.""" status = True if self.action == 'fold': # Fold regions self.view.fold( self.ignore_ending_newlines(self.replace_obj.target_regions)) elif self.action == 'unfold': # Unfold regions try: self.view.unfold( self.ignore_ending_newlines( self.replace_obj.target_regions)) except Exception: error( "Cannot unfold! Please upgrade to the latest stable beta build to remove this error." ) elif self.action == 'mark': # Mark targeted regions if 'key' in self.options: color = self.options['scope'].strip( ) if 'scope' in self.options else DEFAULT_HIGHLIGHT_COLOR style = self.options['style'].strip( ) if 'style' in self.options else DEFAULT_HIGHLIGHT_STYLE self.set_highlights(self.options['key'].strip(), style, color) elif self.action == 'unmark': # Unmark targeted regions if 'key' in self.options: self.clear_highlights(self.options['key'].strip()) elif self.action == 'select': self.view.sel().clear() self.view.sel().add_all(self.replace_obj.target_regions) else: # Not a valid action status = False return status
def run(self, edit): """Parse the regex panel, and if okay, run the test entry in the active view.""" obj, test = ConvertPythonSrc2Obj().convert(self.view.substr(sublime.Region(0, self.view.size()))) # Something went wrong. if test is None or obj is None: return # Ensure test command is valid. if not self.process_test_cmd(test): return # Copy all regex rules that are to be included in the test sequence test_rules = {} rules = sublime.load_settings('reg_replace_rules.sublime-settings').get('replacements', {}) for x in test['replacements']: if x in rules: test_rules[x] = rules[x] # Ensure the bare minimum items are in the current test rule # and ensure the regex (if any) compiles. # If all is well, execute the command. if not obj.get('name'): error('A valid name must be provided!') elif obj.get('scope') is None and obj.get('find') is None: error('A valid find pattern or scope must be provided!') else: try: if obj.get('find') is not None: if obj.get('literal', False): flags = 0 pattern = re.escape(obj['find']) if obj.get('literal_ignorecase', False): flags = re.I re.compile(pattern, flags) else: extend = sublime.load_settings( 'reg_replace.sublime-settings' ).get('extended_back_references', False) if extend: bre.compile_search(obj['find']) else: re.compile(obj['find']) test_rules[obj['name']] = obj settings = sublime.load_settings('reg_replace_test.sublime-settings') settings.set('format', '3.0') settings.set('replacements', test_rules) window = sublime.active_window() if window is not None: view = window.active_view() if view is not None: test["use_test_buffer"] = True view.run_command('reg_replace', test) except Exception as e: error('Regex compile failed!\n\n%s' % str(e))
def process_selections(self, orig_find, selection_only, selection_inputs, literal): """Process selections if necessary.""" sel_start = [] sel_size = [] find = orig_find errors = False sels = self.view.sel() if selection_only and selection_inputs: error("Cannot use 'selection_inputs' with global option 'selection_only'!") errors = True elif selection_only: sel_start = [] sel_size = [] for s in sels: sel_start.append(s.begin()) sel_size.append(s.size()) elif selection_inputs: try: sel_inputs = [] count = 0 for s in sels: assert s.size() <= self.sel_input_max_size, "Exceeded max selection size" engine = self.normal_module if not literal and self.extend: engine = self.extend_module sel_inputs.append(self.view.substr(s)) count += 1 assert count <= self.sel_input_max_count find = RegexInputFormatter(engine).format(orig_find, *sel_inputs, sel=sel_inputs) except Exception: print(str(traceback.format_exc())) error('Failed to process selection inputs.') errors = True return find, sels, sel_start, sel_size, errors
def run(self, edit): """Parse the regex panel, and if okay, insert/replace entry in settings.""" obj = ConvertPythonSrc2Obj().convert( self.view.substr(sublime.Region(0, self.view.size())))[0] if obj is None: return if not obj.get('name'): error('A valid name must be provided!') elif obj.get('scope') is None and obj.get('find') is None: error('A valid find pattern or scope must be provided!') elif not self.is_existing_name(obj['name']): try: if obj.get('find') is not None: if obj.get('selection_inputs', False): pass elif obj.get('literal', False): flags = 0 pattern = re.escape(obj['find']) if obj.get('literal_ignorecase', False): flags = re.I re.compile(pattern, flags) else: extend = sublime.load_settings( 'reg_replace.sublime-settings').get( 'extended_back_references', False) if extend: bre.compile_search(obj['find']) else: re.compile(obj['find']) settings = sublime.load_settings( 'reg_replace_rules.sublime-settings') rules = settings.get('replacements', {}) rules[obj['name']] = obj settings.set('replacements', rules) sublime.save_settings('reg_replace_rules.sublime-settings') self.view.settings().set('regreplace.name', obj['name']) except Exception as e: error('Regex compile failed!\n\n%s' % str(e))
def run(self, edit): """Parse the regex panel, and if okay, insert/replace entry in settings.""" obj = ConvertPythonSrc2Obj().convert(self.view.substr(sublime.Region(0, self.view.size())))[0] if obj is None: return if not obj.get('name'): error('A valid name must be provided!') elif obj.get('scope') is None and obj.get('find') is None: error('A valid find pattern or scope must be provided!') elif not self.is_existing_name(obj['name']): try: if obj.get('find') is not None: if obj.get('literal', False): flags = 0 pattern = re.escape(obj['find']) if obj.get('literal_ignorecase', False): flags = re.I re.compile(pattern, flags) else: extend = sublime.load_settings( 'reg_replace.sublime-settings' ).get('extended_back_references', False) if extend: bre.compile_search(obj['find']) else: re.compile(obj['find']) settings = sublime.load_settings('reg_replace_rules.sublime-settings') rules = settings.get('replacements', {}) rules[obj['name']] = obj settings.set('replacements', rules) sublime.save_settings('reg_replace_rules.sublime-settings') self.view.settings().set('regreplace.name', obj['name']) except Exception as e: error('Regex compile failed!\n\n%s' % str(e))
def scope_apply(self, pattern): """ Find and replace based on scope """ # Initialize replacement variables replaced = 0 regions = [] # Grab pattern definitions scope = pattern['scope'] find = pattern['find'] if 'find' in pattern else None replace = pattern['replace'] if 'replace' in pattern else '\\0' greedy_scope = bool( pattern['greedy_scope']) if 'greedy_scope' in pattern else True greedy_replace = bool( pattern['greedy_replace']) if 'greedy_replace' in pattern else True case = bool(pattern['case']) if 'case' in pattern else True multi = bool(pattern['multi_pass_regex'] ) if 'multi_pass_regex' in pattern else False literal = bool(pattern['literal']) if 'literal' in pattern else False dotall = bool(pattern['dotall']) if 'dotall' in pattern else False self.plugin = pattern.get("plugin", None) self.plugin_args = pattern.get("args", {}) if scope is None or scope == '': return replace if self.selection_only: sels = self.view.sel() sel_start = [] sel_size = [] for s in sels: sel_start.append(s.begin()) sel_size.append(s.size()) regions = self.view.find_by_selector(scope) if self.selection_only: regions = self.filter_by_selection(regions) # Find supplied? if find is not None: # Compile regex: Ignore case flag? if not literal: try: flags = 0 if not case: flags |= re.IGNORECASE if dotall: flags |= re.DOTALL re_find = re.compile(find, flags) except Exception as err: print(str(traceback.format_exc())) error('REGEX ERROR: %s' % str(err)) return replaced # Greedy Scope? if greedy_scope: replaced = self.greedy_scope_replace( regions, re_find, replace, greedy_replace, multi) else: replaced = self.non_greedy_scope_replace( regions, re_find, replace, greedy_replace, multi) else: if greedy_scope: replaced = self.greedy_scope_literal_replace( regions, find, replace, greedy_replace) else: replaced = self.non_greedy_scope_literal_replace( regions, find, replace, greedy_replace) else: replaced = self.select_scope_regions(regions, greedy_scope) if self.selection_only: new_sels = [] count = 0 offset = 0 for s in sels: r = sublime.Region(sel_start[count] + offset, s.end()) new_sels.append(r) offset += r.size() - sel_size[count] count += 1 sels.clear() sels.add_all(new_sels) return replaced
def scope_apply(self, pattern): """Find and replace based on scope.""" # Initialize replacement variables replaced = 0 regions = [] # Grab pattern definitions scope = pattern['scope'] find = pattern.get('find') replace = pattern.get('replace', r'\g<0>') selection_inputs = pattern.get('selection_inputs', False) greedy_scope = bool(pattern.get('greedy_scope', True)) greedy_replace = bool(pattern.get('greedy', True)) literal = pattern.get('literal', False) literal_ignorecase = literal and bool(pattern.get('literal_ignorecase', False)) multi = bool(pattern.get('multi_pass', False)) self.format = bool(pattern.get('format_replace', False)) and self.use_format self.plugin = pattern.get("plugin", None) self.plugin_args = pattern.get("args", {}) if scope is None or scope == '': return replace find, sels, sel_start, sel_size, errors = self.process_selections( find, self.selection_only, selection_inputs, literal ) if errors: return replace regions = self.view.find_by_selector(scope) if self.selection_only: regions = self.filter_by_selection(regions)[0] # Find supplied? if find is not None: if not literal: try: if self.extend: re_find = self.extend_module.compile_search(find, self.regex_version_flag) else: re_find = self.normal_module.compile(find, self.regex_version_flag) except Exception as err: print(str(traceback.format_exc())) error('REGEX ERROR: %s' % str(err)) return replaced # Greedy Scope? if greedy_scope: replaced = self.greedy_scope_replace(regions, re_find, replace, greedy_replace, multi) else: replaced = self.non_greedy_scope_replace(regions, re_find, replace, greedy_replace, multi) else: try: re_find = self.normal_module.compile( self.normal_module.escape(find), (self.normal_module.I if literal_ignorecase else 0) | self.regex_version_flag ) except Exception as err: print(str(traceback.format_exc())) error('REGEX ERROR: %s' % str(err)) return replaced if greedy_scope: replaced = self.greedy_scope_literal_replace(regions, re_find, replace, greedy_replace) else: replaced = self.non_greedy_scope_literal_replace(regions, re_find, replace, greedy_replace) else: replaced = self.select_scope_regions(regions, greedy_scope) if self.selection_only: new_sels = [] count = 0 offset = 0 for s in sels: r = sublime.Region(sel_start[count] + offset, s.end()) new_sels.append(r) offset += r.size() - sel_size[count] count += 1 sels.clear() sels.add_all(new_sels) return replaced
def non_greedy_scope_replace(self, regions, re_find, replace, greedy_replace, multi): """Non greedy scope replace.""" # Initialize replace total_replaced = 0 replaced = 0 last_region = len(regions) - 1 selected_region = None selected_sub_regions = None selected_extraction = None # See if there is a cursor and get the first selections starting point pt = self.get_sel_point() # Intialize with first qualifying region for wrapping and the case of no cursor in view count = 0 try: for region in regions: sub_regions = deque() string = self.view.substr(region) extraction, replaced = self.apply_scope_regex( string, re_find, replace, greedy_replace, multi, region.begin(), sub_regions ) if replaced > 0: selected_region = region selected_sub_regions = sub_regions selected_extraction = extraction break else: count += 1 except Exception as err: print(str(traceback.format_exc())) error('REGEX ERROR: %s' % str(err)) return total_replaced try: # If regions were already swept till the end, skip calculation relative to cursor if selected_region is not None and count < last_region and pt is not None: # Try and find the first qualifying match contained withing the first selection or after reverse_count = last_region for region in reversed(regions): sub_regions = deque() # Make sure we are not checking previously checked regions # And check if region contained after start of selection? if reverse_count >= count and region.end() - 1 >= pt: string = self.view.substr(region) extraction, replaced = self.apply_scope_regex( string, re_find, replace, greedy_replace, multi, region.begin(), sub_regions ) if replaced > 0: selected_region = region selected_sub_regions = sub_regions selected_extraction = extraction reverse_count -= 1 else: break except Exception as err: print(str(traceback.format_exc())) error('REGEX ERROR: %s' % str(err)) return total_replaced # Did we find a suitable region? if selected_region is not None: # Show Instance total_replaced += 1 self.view.show(selected_region.begin()) if self.find_only or self.action is not None: # If "find only" or replace action is overridden, just track regions self.target_regions.extend(selected_sub_regions) else: # Apply replace tabs_to_spaces = self.view.settings().get('translate_tabs_to_spaces', False) if tabs_to_spaces: self.view.settings().set('translate_tabs_to_spaces', False) self.view_replace(selected_region, selected_extraction) if tabs_to_spaces: self.view.settings().set('translate_tabs_to_spaces', True) return total_replaced
def apply(self, pattern): """Normal find and replace.""" # Initialize replacement variables regions = [] flags = 0 replaced = 0 # Grab pattern definitions find = pattern["find"] replace = pattern.get("replace", "\\0") greedy = bool(pattern.get("greedy", True)) scope_filter = pattern.get("scope_filter", []) self.plugin = pattern.get("plugin", None) self.plugin_args = pattern.get("args", {}) literal = pattern.get("literal", False) literal_ignorecase = literal and bool(pattern.get("literal_ignorecase", False)) # Ignore Case? if literal_ignorecase: if self.extend: flags |= self.extend_module.IGNORECASE else: flags |= self.normal_module.IGNORECASE if self.selection_only: sels = self.view.sel() sel_start = [] sel_size = [] for s in sels: sel_start.append(s.begin()) sel_size.append(s.size()) # Find and format replacements extractions = [] try: # regions = self.view.find_all(find, flags, replace, extractions) if self.selection_only and not self.full_file: for sel in sels: regions += self.regex_findall(find, flags, replace, extractions, literal, sel) else: regions = self.regex_findall(find, flags, replace, extractions, literal) except Exception as err: print(str(traceback.format_exc())) error("REGEX ERROR: %s" % str(err)) return replaced if self.selection_only and self.full_file: regions, extractions = self.filter_by_selection(regions, extractions) # Where there any regions found? if len(regions) > 0: # Greedy or non-greedy search? Get replaced instances. if greedy: replaced = self.greedy_replace(extractions, regions, scope_filter) else: replaced = self.non_greedy_replace(extractions, regions, scope_filter) if self.selection_only: new_sels = [] count = 0 offset = 0 for s in sels: r = sublime.Region(sel_start[count] + offset, s.end()) new_sels.append(r) offset += r.size() - sel_size[count] count += 1 sels.clear() sels.add_all(new_sels) return replaced
def apply(self, pattern): """Normal find and replace.""" # Initialize replacement variables regions = [] flags = 0 replaced = 0 # Grab pattern definitions find = pattern['find'] replace = pattern.get('replace', r'\g<0>') selection_inputs = pattern.get('selection_inputs', False) greedy = bool(pattern.get('greedy', True)) scope_filter = pattern.get('scope_filter', []) self.format = bool(pattern.get('format_replace', False)) and self.use_format self.plugin = pattern.get("plugin", None) self.plugin_args = pattern.get("args", {}) literal = pattern.get('literal', False) literal_ignorecase = literal and bool(pattern.get('literal_ignorecase', False)) # Ignore Case? if literal_ignorecase: if self.extend: flags |= self.extend_module.IGNORECASE else: flags |= self.normal_module.IGNORECASE find, sels, sel_start, sel_size, errors = self.process_selections( find, self.selection_only, selection_inputs, literal ) if errors: return replace # Find and format replacements extractions = deque() try: # regions = self.view.find_all(find, flags, replace, extractions) if self.selection_only and not self.full_file: for sel in sels: regions += self.regex_findall(find, flags, replace, extractions, literal, sel) else: regions = self.regex_findall(find, flags, replace, extractions, literal) except Exception as err: print(str(traceback.format_exc())) error('REGEX ERROR: %s' % str(err)) return replaced if self.selection_only and self.full_file: regions, extractions = self.filter_by_selection(regions, extractions) # Where there any regions found? if len(regions) > 0: # Greedy or non-greedy search? Get replaced instances. if greedy: replaced = self.greedy_replace(extractions, regions, scope_filter) else: replaced = self.non_greedy_replace(extractions, regions, scope_filter) if self.selection_only: new_sels = [] count = 0 offset = 0 for s in sels: r = sublime.Region(sel_start[count] + offset, s.end()) new_sels.append(r) offset += r.size() - sel_size[count] count += 1 sels.clear() sels.add_all(new_sels) return replaced
def scope_apply(self, pattern): """Find and replace based on scope.""" # Initialize replacement variables replaced = 0 regions = [] # Grab pattern definitions scope = pattern["scope"] find = pattern.get("find") replace = pattern.get("replace", "\\0") greedy_scope = bool(pattern.get("greedy_scope", True)) greedy_replace = bool(pattern.get("greedy", True)) literal = pattern.get("literal", False) literal_ignorecase = literal and bool(pattern.get("literal_ignorecase", False)) multi = bool(pattern.get("multi_pass", False)) self.plugin = pattern.get("plugin", None) self.plugin_args = pattern.get("args", {}) if scope is None or scope == "": return replace if self.selection_only: sels = self.view.sel() sel_start = [] sel_size = [] for s in sels: sel_start.append(s.begin()) sel_size.append(s.size()) regions = self.view.find_by_selector(scope) if self.selection_only: regions = self.filter_by_selection(regions)[0] # Find supplied? if find is not None: if not literal: try: if self.extend: re_find = self.extend_module.compile_search(find, self.regex_version_flag) else: re_find = self.normal_module.compile(find, self.regex_version_flag) except Exception as err: print(str(traceback.format_exc())) error("REGEX ERROR: %s" % str(err)) return replaced # Greedy Scope? if greedy_scope: replaced = self.greedy_scope_replace(regions, re_find, replace, greedy_replace, multi) else: replaced = self.non_greedy_scope_replace(regions, re_find, replace, greedy_replace, multi) else: try: re_find = self.normal_module.compile( self.normal_module.escape(find), (self.normal_module.I if literal_ignorecase else 0) | self.regex_version_flag, ) except Exception as err: print(str(traceback.format_exc())) error("REGEX ERROR: %s" % str(err)) return replaced if greedy_scope: replaced = self.greedy_scope_literal_replace(regions, re_find, replace, greedy_replace) else: replaced = self.non_greedy_scope_literal_replace(regions, re_find, replace, greedy_replace) else: replaced = self.select_scope_regions(regions, greedy_scope) if self.selection_only: new_sels = [] count = 0 offset = 0 for s in sels: r = sublime.Region(sel_start[count] + offset, s.end()) new_sels.append(r) offset += r.size() - sel_size[count] count += 1 sels.clear() sels.add_all(new_sels) return replaced
def scope_apply(self, pattern): """Find and replace based on scope.""" # Initialize replacement variables replaced = 0 regions = [] # Grab pattern definitions scope = pattern['scope'] find = pattern['find'] if 'find' in pattern else None replace = pattern['replace'] if 'replace' in pattern else '\\0' greedy_scope = bool(pattern['greedy_scope']) if 'greedy_scope' in pattern else True greedy_replace = bool(pattern['greedy_replace']) if 'greedy_replace' in pattern else True case = bool(pattern['case']) if 'case' in pattern else True multi = bool(pattern['multi_pass_regex']) if 'multi_pass_regex' in pattern else False literal = bool(pattern['literal']) if 'literal' in pattern else False dotall = bool(pattern['dotall']) if 'dotall' in pattern else False self.plugin = pattern.get("plugin", None) self.plugin_args = pattern.get("args", {}) if scope is None or scope == '': return replace if self.selection_only: sels = self.view.sel() sel_start = [] sel_size = [] for s in sels: sel_start.append(s.begin()) sel_size.append(s.size()) regions = self.view.find_by_selector(scope) if self.selection_only: regions = self.filter_by_selection(regions)[0] # Find supplied? if find is not None: # Compile regex: Ignore case flag? if not literal: try: flags = 0 if not case: flags |= re.IGNORECASE if dotall: flags |= re.DOTALL if self.extend: re_find = bre.compile_search(find, flags) else: re_find = re.compile(find, flags) except Exception as err: print(str(traceback.format_exc())) error('REGEX ERROR: %s' % str(err)) return replaced # Greedy Scope? if greedy_scope: replaced = self.greedy_scope_replace(regions, re_find, replace, greedy_replace, multi) else: replaced = self.non_greedy_scope_replace(regions, re_find, replace, greedy_replace, multi) else: if greedy_scope: replaced = self.greedy_scope_literal_replace(regions, find, replace, greedy_replace) else: replaced = self.non_greedy_scope_literal_replace(regions, find, replace, greedy_replace) else: replaced = self.select_scope_regions(regions, greedy_scope) if self.selection_only: new_sels = [] count = 0 offset = 0 for s in sels: r = sublime.Region(sel_start[count] + offset, s.end()) new_sels.append(r) offset += r.size() - sel_size[count] count += 1 sels.clear() sels.add_all(new_sels) return replaced
def apply(self, pattern): """Normal find and replace.""" # Initialize replacement variables regions = [] flags = 0 replaced = 0 # Grab pattern definitions find = pattern['find'] replace = pattern['replace'] if 'replace' in pattern else '\\0' literal = bool(pattern['literal']) if 'literal' in pattern else False dotall = bool(pattern['dotall']) if 'dotall' in pattern else False greedy = bool(pattern['greedy']) if 'greedy' in pattern else True case = bool(pattern['case']) if 'case' in pattern else True scope_filter = pattern['scope_filter'] if 'scope_filter' in pattern else [] self.plugin = pattern.get("plugin", None) self.plugin_args = pattern.get("args", {}) # Ignore Case? if not case: flags |= re.IGNORECASE if dotall: flags |= re.DOTALL if self.selection_only: sels = self.view.sel() sel_start = [] sel_size = [] for s in sels: sel_start.append(s.begin()) sel_size.append(s.size()) # Find and format replacements extractions = [] try: # regions = self.view.find_all(find, flags, replace, extractions) if self.selection_only and not self.full_file: for sel in sels: regions += self.regex_findall(find, flags, replace, extractions, literal, sel) else: regions = self.regex_findall(find, flags, replace, extractions, literal) except Exception as err: print(str(traceback.format_exc())) error('REGEX ERROR: %s' % str(err)) return replaced if self.selection_only and self.full_file: regions, extractions = self.filter_by_selection(regions, extractions) # Where there any regions found? if len(regions) > 0: # Greedy or non-greedy search? Get replaced instances. if greedy: replaced = self.greedy_replace(extractions, regions, scope_filter) else: replaced = self.non_greedy_replace(extractions, regions, scope_filter) if self.selection_only: new_sels = [] count = 0 offset = 0 for s in sels: r = sublime.Region(sel_start[count] + offset, s.end()) new_sels.append(r) offset += r.size() - sel_size[count] count += 1 sels.clear() sels.add_all(new_sels) return replaced
def apply(self, pattern): """ Normal find and replace """ # Initialize replacement variables regions = [] flags = 0 replaced = 0 # Grab pattern definitions find = pattern['find'] replace = pattern['replace'] if 'replace' in pattern else '\\0' literal = bool(pattern['literal']) if 'literal' in pattern else False dotall = bool(pattern['dotall']) if 'dotall' in pattern else False greedy = bool(pattern['greedy']) if 'greedy' in pattern else True case = bool(pattern['case']) if 'case' in pattern else True scope_filter = pattern[ 'scope_filter'] if 'scope_filter' in pattern else [] self.plugin = pattern.get("plugin", None) self.plugin_args = pattern.get("args", {}) # Ignore Case? if not case: flags |= re.IGNORECASE if dotall: flags |= re.DOTALL if self.selection_only: sels = self.view.sel() sel_start = [] sel_size = [] for s in sels: sel_start.append(s.begin()) sel_size.append(s.size()) # Find and format replacements extractions = [] try: # regions = self.view.find_all(find, flags, replace, extractions) if self.selection_only and not self.full_file: for sel in sels: regions += self.regex_findall(find, flags, replace, extractions, literal, sel) else: regions = self.regex_findall(find, flags, replace, extractions, literal) except Exception as err: print(str(traceback.format_exc())) error('REGEX ERROR: %s' % str(err)) return replaced if self.selection_only and self.full_file: regions, extractions = self.filter_by_selection( regions, extractions) # Where there any regions found? if len(regions) > 0: # Greedy or non-greedy search? Get replaced instances. if greedy: replaced = self.greedy_replace(find, extractions, regions, scope_filter) else: replaced = self.non_greedy_replace(find, extractions, regions, scope_filter) if self.selection_only: new_sels = [] count = 0 offset = 0 for s in sels: r = sublime.Region(sel_start[count] + offset, s.end()) new_sels.append(r) offset += r.size() - sel_size[count] count += 1 sels.clear() sels.add_all(new_sels) return replaced