def f(view, s): delta = 1 if mode == MODE_VISUAL: delta = 1 if utils.is_region_reversed(view, s) else 2 text_before_caret = view.substr(sublime.Region(view.line(s.b).a, s.b - delta)) first_char_is_space = view.substr(s.b - delta).isspace() if (view.line(s.b).a == s.b - delta) else False if mode == MODE_NORMAL: if text_before_caret.isspace() or first_char_is_space: pt = utils.previous_non_white_space_char(self.view, s.b - 1, white_space='\t ') if view.line(pt).empty(): return sublime.Region(s.a , pt + 1) elif view.word(pt).size() == 1: return sublime.Region(pt + 1, pt + 1) return sublime.Region(pt, pt) # At BOL. # XXX: Use a general function instead of spelling out the computation. elif view.line(s.b).a == s.b and not view.line(s.b - 1).empty(): return sublime.Region(s.b - 1, s.b - 1) elif mode == MODE_VISUAL: if utils.is_region_reversed(view, s): if text_before_caret.isspace() or first_char_is_space: pt = utils.previous_non_white_space_char(self.view, s.b - delta, white_space='\t ') # PREVIOUSLINE empty; don't go past it. if view.line(pt).empty(): return sublime.Region(s.a , pt + 1) return sublime.Region(s.a, pt) elif utils.is_at_bol(view, s) and not view.line(s.b - 1).empty(): # Single-character words are a special case; we don't want to skip over # them. if view.word(s.b - 1).size() > 1: return sublime.Region(s.a, s.b - 1) else: # Non-reversed region. Note that .b here is at NEXTCHAR, not CURRENTCHAR. if text_before_caret.isspace() or first_char_is_space: pt = utils.previous_non_white_space_char(self.view, s.b - delta, white_space='\t ') if view.line(pt).empty(): return sublime.Region(s.a , pt + 1) # XXX: I don't think this branch is necessary. # On new WORD; make sure motion doesn't skip it. elif view.substr(pt) not in ('\t \n'): return sublime.Region(s.a, pt + 1) return sublime.Region(s.a, pt) # At WORDBEGIN or at any non-ALPHANUMERICCHAR. elif (view.word(s.b - 1).a == s.b - 1) or not view.substr(s.b - 1).isalnum(): return sublime.Region(s.a, s.b - 1) return s
def f(view, s): # TODO: must skip empty paragraphs. start = utils.previous_non_white_space_char(view, s.b - 1, white_space="\n \t") par_as_region = view.expand_by_class(start, sublime.CLASS_EMPTY_LINE) if mode == MODE_NORMAL: return sublime.Region(par_as_region.a, par_as_region.a) elif mode == MODE_VISUAL: # FIXME: Improve motion when .b end crosses over .a end: must extend .a end # by one. if s.a == par_as_region.a: return sublime.Region(s.a, s.a + 1) return sublime.Region(s.a, par_as_region.a) elif mode == _MODE_INTERNAL_NORMAL: return sublime.Region(s.a, par_as_region.a) elif mode == MODE_VISUAL_LINE: if s.a <= s.b: if par_as_region.a < s.a: return sublime.Region(view.full_line(s.a).b, par_as_region.a) return sublime.Region(s.a, par_as_region.a + 1) else: return sublime.Region(s.a, par_as_region.a) return s
def f(view, s): # TODO: must skip empty paragraphs. start = utils.previous_non_white_space_char(view, s.b - 1, white_space='\n \t') par_as_region = view.expand_by_class(start, sublime.CLASS_EMPTY_LINE) if mode == MODE_NORMAL: return sublime.Region(par_as_region.a, par_as_region.a) elif mode == MODE_VISUAL: # FIXME: Improve motion when .b end crosses over .a end: must extend .a end # by one. if s.a == par_as_region.a: return sublime.Region(s.a, s.a + 1) return sublime.Region(s.a, par_as_region.a) elif mode == _MODE_INTERNAL_NORMAL: return sublime.Region(s.a, par_as_region.a) elif mode == MODE_VISUAL_LINE: if s.a <= s.b: if par_as_region.a < s.a: return sublime.Region( view.full_line(s.a).b, par_as_region.a) return sublime.Region(s.a, par_as_region.a + 1) else: return sublime.Region(s.a, par_as_region.a) return s
def find_previous_sentence_end(self, r): sen = r pt = utils.previous_non_white_space_char(self.view, sen.a, white_space='\n \t') sen = sublime.Region(pt, pt) while True: sen = self.view.expand_by_class(sen, sublime.CLASS_LINE_END | sublime.CLASS_PUNCTUATION_END) if sen.a <= 0 or self.view.substr(sen.begin() - 1) in ('.', '\n'): if self.view.substr(sen.begin() - 1) == '.' and not self.view.substr(sen.begin()) == ' ': continue return sen
def find_previous_sentence_end(self, r): sen = r pt = utils.previous_non_white_space_char(self.view, sen.a, white_space='\n \t') sen = sublime.Region(pt, pt) while True: sen = self.view.expand_by_class( sen, sublime.CLASS_LINE_END | sublime.CLASS_PUNCTUATION_END) if sen.a <= 0 or self.view.substr(sen.begin() - 1) in ('.', '\n'): if self.view.substr(sen.begin() - 1) == '.' and not self.view.substr( sen.begin()) == ' ': continue return sen
def f(view, s): # TODO: must skip empty paragraphs. start = utils.previous_non_white_space_char(view, s.b - 1, white_space='\n \t') par_as_region = view.expand_by_class(start, sublime.CLASS_EMPTY_LINE) if mode == MODE_NORMAL: return sublime.Region(par_as_region.a, par_as_region.a) elif mode == MODE_VISUAL: return sublime.Region(s.a + 1, par_as_region.a) elif mode == _MODE_INTERNAL_NORMAL: return sublime.Region(s.a, par_as_region.a) elif mode == MODE_VISUAL_LINE: if s.a <= s.b: if par_as_region.a < s.a: return sublime.Region(view.full_line(s.a).b, par_as_region.a) return sublime.Region(s.a, par_as_region.a + 1) else: return sublime.Region(s.a, par_as_region.a) return s
def a_word(view, pt, inclusive=True, count=1): assert count > 0 start = current_word_start(view, pt) end = pt if inclusive: end = units.word_starts(view, start, count=count, internal=True) # If there is no space at the end of our word text object, include any # preceding spaces. (Follows Vim behavior.) if (not view.substr(end - 1).isspace() and view.substr(start - 1).isspace()): start = utils.previous_non_white_space_char( view, start - 1, white_space=' \t') + 1 # Vim does some inconsistent stuff here... if count > 1 and view.substr(end) == '\n': end += 1 return sublime.Region(start, end) for x in range(count): end = current_word_end(view, end) return sublime.Region(start, end)