def next_paragraph_start(view, pt, count=1, skip_empty=True): if utils.row_at(view, pt) == utils.last_row(view): if not view.line(view.size()).empty(): return view.size() - 1 return view.size() # skip empty rows before moving for the first time current_row = utils.row_at(view, pt) if (view.line(view.text_point(current_row + 1, 0)).empty() and view.line(pt).empty()): pt, _ = _next_non_empty_row(view, pt) for i in range(count): pt, eof = _next_empty_row(view, pt) if eof: if view.line(pt).empty(): return pt return pt - 1 if skip_empty and (i != (count - 1)): pt, eof = _next_non_empty_row(view, pt) if eof: if not view.line(pt).empty(): return pt - 1 return pt return pt
def resolve_mark(self, view, token): if token.content == '<': sel = list(view.sel())[0] view.sel().clear() view.sel().add(sel) if sel.a < sel.b: return row_at(view, sel.a) else: return row_at(view, sel.a - 1) if token.content == '>': sel = list(view.sel())[0] view.sel().clear() view.sel().add(sel) if sel.a < sel.b: return row_at(view, sel.b - 1) else: return row_at(view, sel.b) st = State(view) rg = st.marks.get_as_encoded_address(token.content) if (isinstance(rg, sublime.Region)): return view.rowcol(rg.begin())[0] raise NotImplementedError()
def _next_empty_row(view, pt): r = utils.row_at(view, pt) while True: r += 1 pt = view.text_point(r, 0) if utils.row_at(view, pt) == utils.last_row(view): return view.size(), True if view.line(pt).empty(): return pt, False
def _prev_empty_row(view, pt): r = utils.row_at(view, pt) while True: r -= 1 pt = view.text_point(r, 0) if utils.row_at(view, pt) == utils.first_row(view): return pt, True if view.line(pt).empty(): return pt, False
def resolve_line_reference(self, view, line_reference, current=0): """ Calculates the line offset determined by @line_reference. @view The view where the calculation is made. @line_reference The sequence of tokens defining the line range to be calculated. @current Line number where we are now. """ last_token = None # XXX: what happens if there is no selection in the view? current = row_at(view, first_sel(view).b) for token in line_reference: # Make sure a search forward doesn't overlap with a match obtained # right before this search. if isinstance(last_token, TokenOfSearch) and isinstance(token, TokenOfSearch): if isinstance(token, TokenSearchForward): current += 1 current = self.resolve_notation(view, token, current) last_token = token return current
def get_visual_repeat_data(self): """ Returns the data needed to repeat a visual mode command in normal mode. """ if self.mode not in (modes.VISUAL, modes.VISUAL_LINE): return first_sel = self.view.sel()[0] lines = (utils.row_at(self.view, first_sel.end()) - utils.row_at(self.view, first_sel.begin())) if lines > 0: chars = self.view.rowcol(first_sel.end())[1] else: chars = first_sel.size() return (lines, chars, self.mode)
def resolve_line_reference(self, view, line_reference, current=0): ''' Calculates the line offset determined by @line_reference. @view The view where the calculation is made. @line_reference The sequence of tokens defining the line range to be calculated. @current Line number where we are now. ''' last_token = None # XXX: what happens if there is no selection in the view? current = row_at(view, first_sel(view).b) for token in line_reference: # Make sure a search forward doesn't overlap with a match obtained # right before this search. if isinstance(last_token, TokenOfSearch) and isinstance( token, TokenOfSearch): if isinstance(token, TokenSearchForward): current += 1 current = self.resolve_notation(view, token, current) last_token = token return current
def get_visual_repeat_data(self): """Returns the data needed to restore visual selections before repeating a visual mode command in normal mode. """ if self.mode not in (modes.VISUAL, modes.VISUAL_LINE): return first = first_sel(self.view) lines = (utils.row_at(self.view, first.end()) - utils.row_at(self.view, first.begin())) if lines > 0: chars = utils.col_at(self.view, first.end()) else: chars = first.size() return (lines, chars, self.mode)
def _prev_non_empty_row(view, pt): r = utils.row_at(view, pt) while True: r -= 1 reg = view.line(view.text_point(r, 0)) if r <= utils.first_row(view): return 0, True if not reg.empty(): return reg.a, False
def _next_non_empty_row(view, pt): r = utils.row_at(view, pt) while True: r += 1 reg = view.line(view.text_point(r, 0)) if r >= utils.last_row(view): return reg.a, True if not reg.empty(): return reg.a, False
def _prev_empty_row(view, pt): r = utils.row_at(view, pt) while True: r -= 1 if r == 0: return 0, True pt = view.text_point(r, 0) if view.line(pt).empty(): return pt, False
def _prev_non_empty_row(view, pt): r = utils.row_at(view, pt) while True: r -= 1 reg = view.line(view.text_point(r, 0)) # stop if we hit the first row if r <= 0: return 0, True if not reg.empty(): return reg.a, False
def resolve_mark(self, view, token): if token.content == '<': sel = list(view.sel())[0] view.sel().clear() view.sel().add(sel) if sel.a < sel.b: return row_at(view, sel.a) else: return row_at(view, sel.a - 1) if token.content == '>': sel = list(view.sel())[0] view.sel().clear() view.sel().add(sel) if sel.a < sel.b: return row_at(view, sel.b - 1) else: return row_at(view, sel.b) raise NotImplementedError()
def prev_paragraph_start(view, pt, count=1, skip_empty=True): if utils.row_at(view, pt) == utils.first_row(view): return 0 current_row = utils.row_at(view, pt) if view.line(view.text_point(current_row - 1, 0)).empty(): pt, _ = _prev_non_empty_row(view, pt) for i in range(count): pt, bol = _prev_empty_row(view, pt) if bol: return 0 if skip_empty and count > 1 and count != count - 1: pt, bol = _prev_non_empty_row(view, pt) if bol: return 0 offset = 1 if count > 1 else 0 return view.text_point(utils.row_at(view, pt) + offset, 0)
def resolve_mark(self, view, token): if token.content == "<": sel = list(view.sel())[0] view.sel().clear() view.sel().add(sel) if sel.a < sel.b: return row_at(view, sel.a) else: return row_at(view, sel.a - 1) if token.content == ">": sel = list(view.sel())[0] view.sel().clear() view.sel().add(sel) if sel.a < sel.b: return row_at(view, sel.b - 1) else: return row_at(view, sel.b) raise NotImplementedError()
def lines(view, s, count=1): """ Returns a region spanning @count full lines. Assumes we're operating in INTERNAL_NORMAL mode. @view Target view. @s Selection in @view taken as starting point. @count Number of lines to include in returned region. """ # assumes INTERNAL_NORMAL mode. a = view.line(s.b).a b = view.text_point(utils.row_at(view, s.b) + (count - 1), 0) # make sure we remove the last line if needed if ((utils.row_at(view, b) == utils.last_row(view)) and (view.substr(a - 1) == '\n')): a -= 1 return sublime.Region(a, view.full_line(b).b)
def resolve_notation(self, view, token, current): """ Returns a line number. """ if isinstance(token, TokenDot): pt = view.text_point(current, 0) return row_at(view, pt) if isinstance(token, TokenDigits): return max(int(str(token)) - 1, -1) if isinstance(token, TokenPercent): return row_at(view, view.size()) if isinstance(token, TokenDollar): return row_at(view, view.size()) if isinstance(token, TokenOffset): return current + sum(token.content) if isinstance(token, TokenSearchForward): start_pt = view.text_point(current, 0) match = view.find(str(token)[1:-1], start_pt) if not match: # TODO: Convert this to a VimError or something like that. raise ValueError("pattern not found") return row_at(view, match.a) if isinstance(token, TokenSearchBackward): start_pt = view.text_point(current, 0) match = reverse_search_by_pt(view, str(token)[1:-1], 0, start_pt) if not match: # TODO: Convert this to a VimError or something like that. raise ValueError("pattern not found") return row_at(view, match.a) if isinstance(token, TokenMark): return self.resolve_mark(view, token) raise NotImplementedError()
def resolve_notation(self, view, token, current): ''' Returns a line number. ''' if isinstance(token, TokenDot): pt = view.text_point(current, 0) return row_at(view, pt) if isinstance(token, TokenDigits): return max(int(str(token)) - 1, -1) if isinstance(token, TokenPercent): return row_at(view, view.size()) if isinstance(token, TokenDollar): return row_at(view, view.size()) if isinstance(token, TokenOffset): return current + sum(token.content) if isinstance(token, TokenSearchForward): start_pt = view.text_point(current, 0) match = view.find(str(token)[1:-1], start_pt) if not match: # TODO: Convert this to a VimError or something like that. raise ValueError('pattern not found') return row_at(view, match.a) if isinstance(token, TokenSearchBackward): start_pt = view.text_point(current, 0) match = reverse_search_by_pt(view, str(token)[1:-1], 0, start_pt) if not match: # TODO: Convert this to a VimError or something like that. raise ValueError('pattern not found') return row_at(view, match.a) if isinstance(token, TokenMark): return self.resolve_mark(view, token) raise NotImplementedError()
def restore_visual_data(self, data): rows, chars, old_mode = data first = first_sel(self.view) if old_mode == modes.VISUAL: if rows > 0: end = self.view.text_point( utils.row_at(self.view, first.b) + rows, chars) else: end = first.b + chars self.view.sel().add(sublime.Region(first.b, end)) self.mode = modes.VISUAL elif old_mode == modes.VISUAL_LINE: rows, _, old_mode = data begin = self.view.line(first.b).a end = self.view.text_point( utils.row_at(self.view, begin) + (rows - 1), 0) end = self.view.full_line(end).b self.view.sel().add(sublime.Region(begin, end)) self.mode = modes.VISUAL_LINE
def restore_visual_data(self, data): rows, chars, old_mode = data first = first_sel(self.view) if old_mode == modes.VISUAL: if rows > 0: end = self.view.text_point(utils.row_at(self.view, first.b) + rows, chars) else: end = first.b + chars self.view.sel().add(sublime.Region(first.b, end)) self.mode = modes.VISUAL elif old_mode == modes.VISUAL_LINE: rows, _, old_mode = data begin = self.view.line(first.b).a end = self.view.text_point(utils.row_at(self.view, begin) + (rows - 1), 0) end = self.view.full_line(end).b self.view.sel().add(sublime.Region(begin, end)) self.mode = modes.VISUAL_LINE
def prev_paragraph_start(view, pt, count=1, skip_empty=True): # first row? if utils.row_at(view, pt) == 0: return 0 current_row = utils.row_at(view, pt) if (view.line(view.text_point(current_row - 1, 0)).empty() and view.line(view.text_point(current_row, 0)).empty()): pt, bof = _prev_non_empty_row(view, pt) if bof: return 0 for i in range(count): pt, bof = _prev_empty_row(view, pt) if bof: return 0 if skip_empty and (count > 1) and (i != count - 1): pt, bof = _prev_non_empty_row(view, pt) if bof: return pt return view.text_point(utils.row_at(view, pt), 0)
def inner_lines(view, s, count=1): """ Returns a region spanning @count inner lines. Inner lines are lines excluding leading/trailing whitespace at outer ends. Assumes we're operating in INTERNAL_NORMAL mode. @view Target view. @s Selection in @view taken as starting point. @count Number of lines to include in returned region. """ end = view.text_point(utils.row_at(view, s.b) + (count - 1), 0) begin = view.line(s.b).a begin = utils.next_non_white_space_char(view, begin, white_space=' \t') return sublime.Region(begin, view.line(end).b)
def restore_visual_data(self, data): row_count, chars, old_mode = data first_sel = self.view.sel()[0] if old_mode == modes.VISUAL: if (data[0] > 0): end = self.view.text_point( self.view.rowcol(first_sel.b)[0] + data[0], data[1]) else: end = first_sel.b + data[1] self.view.sel().add(sublime.Region(first_sel.b, end)) self.mode = modes.VISUAL elif old_mode == modes.VISUAL_LINE: row_count, _, old_mode = data begin = self.view.line(first_sel.b).a end = self.view.text_point(utils.row_at(self.view, begin) + row_count - 1, 0) end = self.view.full_line(end).b self.view.sel().add(sublime.Region(begin, end)) self.mode = modes.VISUAL_LINE else: pass