def _f(view, s): if mode == INTERNAL_NORMAL: old = target new = replacement open_, close_ = _get_punctuation_marks(old) new_open, new_close = _get_punctuation_mark_replacements(new) if open_ == 't': open_, close_ = ('<[^>\\/]+>', '<\\/[^>]+>') next_ = view.find(close_, s.b) if next_: prev_ = reverse_search(view, open_, end=next_.begin(), start=0) else: prev_ = None else: if open_ == close_: line = view.line(s.b) prev_ = None next_ = view.find(close_, s.b, flags=LITERAL) if next_: if next_.a > line.b: next_ = None else: prev_ = reverse_search(view, open_, end=s.b, start=0, flags=LITERAL) if not prev_ or (prev_ and prev_.a < line.a): prev_ = next_ next_ = view.find(close_, s.b + 1, flags=LITERAL) else: next_ = view.find(close_, s.b, flags=LITERAL) if next_: prev_ = reverse_search(view, open_, end=s.b, start=0, flags=LITERAL) else: next_ = None if not (next_ and prev_): return s view.replace(edit, next_, new_close) view.replace(edit, prev_, new_open) return Region(prev_.begin()) return s
def _f(view, s): if mode == INTERNAL_NORMAL: old = target new = replacement open_, close_ = _get_punctuation_marks(old) new_open, new_close = _get_punctuation_mark_replacements(new) # Replacements > 1 are always tags, and the first character could be # "t", which is an alias for "<". if len(replacement) > 1: new_open = '<' + new_open[1:] # Replacements > 1 are always tags, and the first character could be # "t", which is an alias for "<". if len(replacement) > 1: new_close = '</' + new_close[1:] if open_ == 't': open_, close_ = ('<[^>\\/]+>', '<\\/[^>]+>') next_ = view.find(close_, s.b) if next_: prev_ = reverse_search(view, open_, end=next_.begin(), start=0) else: prev_ = None else: next_ = view.find(close_, s.b, flags=LITERAL) if next_: prev_ = reverse_search(view, open_, end=s.b, start=0, flags=LITERAL) else: next_ = None if not (next_ and prev_): return s view.replace(edit, next_, new_close) view.replace(edit, prev_, new_open) return Region(prev_.begin()) return s
def _rfind(view, sub, start, end, flags=0): # TODO Make start and end optional arguments interpreted as in slice notation. # TODO [refactor] into reusable api. res = reverse_search(view, sub, start, end, flags) if res is None: return Region(-1) return res
def _f(view, s): if mode == INTERNAL_NORMAL: if len(target) != 1: return s # The *target* letters w, W, s, and p correspond to a |word|, a # |WORD|, a |sentence|, and a |paragraph| respectively. These are # special in that they have nothing to delete, and used with |ds| they # are a no-op. With |cs|, one could consider them a slight shortcut for # ysi (cswb == ysiwb, more or less). noop = 'wWsp' if target in noop: return s valid_targets = '\'"`b()B{}r[]a<>t.,-_;:@#~*\\/' if target not in valid_targets: return s # All marks, except punctuation marks, are only searched for on the # current line. # If opening punctuation mark is used, contained whitespace is also trimmed. trim_contained_whitespace = True if target in '({[<' else False search_current_line_only = False if target in 'b()B{}r[]a<>' else True # Expand targets into begin and end variables because punctuation marks # and their aliases represent themselves and their counterparts e.g. (), # []. Target is the same for begin and end for all other valid marks # e.g. ', ", `, -, _, etc. t_char_begin, t_char_end = _get_punctuation_marks(target) s_rowcol_begin = view.rowcol(s.begin()) s_rowcol_end = view.rowcol(s.end()) # A t is a pair of HTML or XML tags. if target == 't': # TODO test dst works when cursor position is inside tag begin <a|bc>x</abc> -> dst -> |x # TODO test dst works when cursor position is inside tag end <abc>x</a|bc> -> dst -> |x t_region_end = view.find('<\\/.*?>', s.b) t_region_begin = reverse_search(view, '<.*?>', start=0, end=s.b) else: current = view.substr(s.begin()) # TODO test ds{char} works when cursor position is on target begin |"x" -> ds" -> |x # TODO test ds{char} works when cursor position is on target end "x|" -> ds" -> |x if current == t_char_begin: t_region_begin = Region(s.begin(), s.begin() + 1) else: t_region_begin = _rfind(view, t_char_begin, start=0, end=s.begin(), flags=LITERAL) t_region_begin_rowcol = view.rowcol(t_region_begin.begin()) t_region_end = _find(view, t_char_end, start=t_region_begin.end(), flags=LITERAL) t_region_end_rowcol = view.rowcol(t_region_end.end()) if search_current_line_only: if t_region_begin_rowcol[0] != s_rowcol_begin[0]: return s if t_region_end_rowcol[0] != s_rowcol_end[0]: return s if trim_contained_whitespace: t_region_begin_ws = _find(view, '\\s*.', start=t_region_begin.end()) t_region_end_ws = _rfind(view, '.\\s*', start=t_region_begin.end(), end=t_region_end.begin()) if t_region_begin_ws.size() > 1: t_region_begin = Region(t_region_begin.begin(), t_region_begin_ws.end() - 1) if t_region_end_ws.size() > 1: t_region_end = Region(t_region_end_ws.begin() + 1, t_region_end.end()) # Note: Be careful using boolean evaluation on a Region because an empty # Region evaluates to False. It evaluates to False because Region # invokes `__len__()` which will be zero if the Region is empty e.g. # `Region(3).size()` is `0`, whereas `Region(3, 4).size()` is `1`. # `sublime.View.find(sub)` returns `Region(-1)` if *sub* not found. This # is similar to how the python `str.find(sub)` function works i.e. it # returns `-1` if *sub* not found, because *sub* could be found at # position `0`. To check if a Region was found use `Region(3) >= 0`. To # check if a Region is non empty you can use boolean evaluation i.e. `if # Region(3): ...`. In the following case boolean evaluation is # intentional. if not (t_region_end and t_region_begin): return s # It's important that the end is replaced first. If we replaced the # begin region first then the end replacement would be off-by-one # because the begin is reducing the size of the internal buffer by one # i.e. it's deleting a character. view.replace(edit, t_region_end, '') view.replace(edit, t_region_begin, '') return Region(t_region_begin.begin()) return s
def _rfind(view, sub, start, end, flags=0): res = reverse_search(view, sub, start, end, flags) if res is None: return Region(-1) return res