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): if mode == MODE_VISUAL: # Vim selects the FIRSTCHAR of NEXTWORD when moving backward in VISUAL mode. if not utils.is_region_reversed(self.view, s): return sublime.Region(s.a, s.b + 1) return s
def f(view, s): state = VintageState(view) if state.mode == MODE_NORMAL: if s.b == view.size(): return sublime.Region(view.size() - 1, view.size() - 1) elif view.substr(s.b) == '\n': if not view.line(s.b).empty(): r = sublime.Region(s.b + 1, s.b + 1) pt = utils.next_non_white_space_char(view, r.b, white_space='\t ') return sublime.Region(pt, pt) if state.mode == MODE_VISUAL: if not utils.is_region_reversed(view, s): # FIXME: Moving from EMPTYLINE to NONEMPTYLINE should select FIRSTCHAR on NEXTLINE # only, but it selects a WORD and the FIRSTCHAR of the following WORD too. # When starting from an empty line, select only the FIRSTCHAR of the FIRSTWORD on # NEXTLINE. if view.size() == s.b: return sublime.Region(s.a, s.b) if ViExecutionState.select_word_begin_from_empty_line: ViExecutionState.reset_word_state() return sublime.Region(s.a, view.word(view.line(s.b).a).a + 1) # If after the motion we're on an empty line, stay there. if view.substr(s.b - 1) == '\n' and view.line(s.b - 1).empty(): return s # Always select the FIRSTCHAR of NEXTWORD skipping any WHITESPACE. # XXX: Possible infinite loop at EOF. pt = s.b while True: pt = utils.next_non_white_space_char(view, pt, white_space='\t ') # We're on an EMPTYLINE, so stay here. if view.substr(pt) == '\n' and view.line(pt).empty(): break # NEWLINECHAR after NONEMPTYLINE; keep going. elif view.substr(pt) == '\n': pt += 1 continue # Any NONWHITESPACECHAR; stop here. else: break s = sublime.Region(s.a, pt + 1) # Reversed selections... else: # Skip over NEWLINECHAR at EOL if on NONEMPTYLINE. if view.substr(s.b) == '\n' and not view.line(s.b).empty(): # FIXME: Don't swallow empty lines. pt = utils.next_non_white_space_char(view, s.b, white_space='\t \n') return sublime.Region(s.a, pt) return s
def f(view, s): state = VintageState(view) if state.mode == MODE_VISUAL: if not utils.is_region_reversed(view, s): if view.line(s.b - 1).empty() and view.substr(s.b) not in (" \t") and not view.line(s.b).empty(): # When issuing *w* from an empty line in visual mode, Vim will select the FIRSTCHAR # of the FIRSTWORD on the NEXTLINE. For that to happen, we need to signal here # that were in such a context. ViExecutionState.select_word_begin_from_empty_line = True if view.substr(s.b - 1) != "\n": # Ensures that we don't skip over WORDS of length 1. return sublime.Region(s.a, s.b - 1) else: return sublime.Region(s.a, s.b + 1) return s
def f(view, s): state = VintageState(view) if state.mode == MODE_VISUAL: if not utils.is_region_reversed(view, s): if (view.line(s.b - 1).empty() and view.substr(s.b) not in (' \t') and not view.line(s.b).empty()): # When issuing *w* from an empty line in visual mode, Vim will select the FIRSTCHAR # of the FIRSTWORD on the NEXTLINE. For that to happen, we need to signal here # that were in such a context. ViExecutionState.select_word_begin_from_empty_line = True if view.substr(s.b - 1) != '\n': # Ensures that we don't skip over WORDS of length 1. return sublime.Region(s.a, s.b - 1) else: return sublime.Region(s.a, s.b + 1) return s
def f(view, s): state = VintageState(view) if state.mode == MODE_NORMAL: if s.b == view.size(): return sublime.Region(view.size() - 1, view.size() - 1) elif view.substr(s.b) == '\n': if not view.line(s.b).empty(): r = sublime.Region(s.b + 1, s.b + 1) pt = utils.next_non_white_space_char(view, r.b, white_space='\t ') return sublime.Region(pt, pt) if state.mode == MODE_VISUAL: if not utils.is_region_reversed(view, s): # FIXME: Moving from EMPTYLINE to NONEMPTYLINE should select FIRSTCHAR on NEXTLINE # only, but it selects a WORD and the FIRSTCHAR of the following WORD too. # When starting from an empty line, select only the FIRSTCHAR of the FIRSTWORD on # NEXTLINE. if view.size() == s.b: return sublime.Region(s.a, s.b) if ViExecutionState.select_word_begin_from_empty_line: ViExecutionState.reset_word_state() return sublime.Region( s.a, view.word(view.line(s.b).a).a + 1) # If after the motion we're on an empty line, stay there. if view.substr(s.b - 1) == '\n' and view.line(s.b - 1).empty(): return s # Always select the FIRSTCHAR of NEXTWORD skipping any WHITESPACE. # XXX: Possible infinite loop at EOF. pt = s.b while True: pt = utils.next_non_white_space_char(view, pt, white_space='\t ') # We're on an EMPTYLINE, so stay here. if view.substr(pt) == '\n' and view.line(pt).empty(): break # NEWLINECHAR after NONEMPTYLINE; keep going. elif view.substr(pt) == '\n': pt += 1 continue # Any NONWHITESPACECHAR; stop here. else: break s = sublime.Region(s.a, pt + 1) # Reversed selections... else: # Skip over NEWLINECHAR at EOL if on NONEMPTYLINE. if view.substr(s.b) == '\n' and not view.line(s.b).empty(): # FIXME: Don't swallow empty lines. pt = utils.next_non_white_space_char( view, s.b, white_space='\t \n') return sublime.Region(s.a, pt) if state.mode == _MODE_INTERNAL_NORMAL: if current_iteration == total_iterations: if view.substr(s.b - 1) == '\n' and not view.line(s.b - 1).empty(): return sublime.Region(s.a, s.b - 1) return s