def next_paragraph_start(view, pt, count=1, skip_empty=True): if row_at(view, pt) == 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 = 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 prev_paragraph_start(view, pt: int, count: int = 1, skip_empty: bool = True) -> int: # first row? if row_at(view, pt) == 0: return 0 current_row = 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(row_at(view, pt), 0)
def _next_empty_row(view, pt): r = row_at(view, pt) while True: r += 1 pt = view.text_point(r, 0) if row_at(view, pt) == last_row(view): return view.size(), True if view.line(pt).empty(): return pt, False
def f(view, s): if mode == INTERNAL_NORMAL: view.run_command('toggle_comment') if row_at(view, s.a) != row_at(view, view.size()): pt = next_non_blank(view, s.a) else: pt = next_non_blank(view, view.line(s.a).a) return Region(pt) return s
def _resolve_line_number(view, token, current: int) -> int: # Args: # view (View): The view where the calculation is made. # token (Token): # current (int): Line number where we are now. if isinstance(token, TokenDot): return row_at(view, view.text_point(current, 0)) if isinstance(token, TokenDigits): return max(int(token.content) - 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): match = view.find(token.content, view.text_point(current, 0)) if not match: raise ValueError('E385: Search hit BOTTOM without match for: ' + token.content) return row_at(view, match.a) if isinstance(token, TokenSearchBackward): match = reverse_search_by_pt(view, token.content, 0, view.text_point(current, 0)) if not match: raise ValueError('E384: Search hit TOP without match for: ' + token.content) return row_at(view, match.a) if isinstance(token, TokenMark): 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) elif 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) elif token.content in tuple('abcdefghijklmnopqrstuvwxyz'): mark = get_mark(view, token.content) if not isinstance(mark, Region): raise ValueError('E20: mark not set') return view.rowcol(mark.b)[0] raise NotImplementedError()
def _resolve_line_number(view, token, current): # type: (...) -> int # Args: # view (View): The view where the calculation is made. # token (Token): # current (int): Line number where we are now. if isinstance(token, TokenDot): return row_at(view, view.text_point(current, 0)) if isinstance(token, TokenDigits): return max(int(token.content) - 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): match = view.find(token.content, view.text_point(current, 0)) if not match: raise ValueError('pattern not found') return row_at(view, match.a) if isinstance(token, TokenSearchBackward): match = reverse_search_by_pt(view, token.content, 0, view.text_point(current, 0)) if not match: raise ValueError('pattern not found') return row_at(view, match.a) if isinstance(token, TokenMark): 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) elif 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) elif token.content in tuple('abcdefghijklmnopqrstuvwxyz'): return view.rowcol( get_mark_as_encoded_address(view, token.content).b)[0] raise NotImplementedError()
def f(view, s): if mode == INTERNAL_NORMAL: end = view.text_point(row_at(view, s.b) + (count - 1), 0) begin = view.line(s.b).a row_at_end = row_at(view, end) row_at_size = row_at(view, view.size()) if ((row_at_end == row_at_size) and (view.substr(begin - 1) == '\n')): begin -= 1 return Region(begin, view.full_line(end).b) return s
def _prev_empty_row(view, pt): r = 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 _next_non_empty_row(view, pt): r = row_at(view, pt) while True: r += 1 reg = view.line(view.text_point(r, 0)) if r >= last_row(view): return view.size(), True if not reg.empty(): return reg.a, False
def _prev_non_empty_row(view, pt): r = 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 get_visual_repeat_data(self): # Return the data needed to restore visual selections. # # Before repeating a visual mode command in normal mode. # # Returns: # 3-tuple (lines, chars, mode) if self.mode not in (VISUAL, VISUAL_LINE): return first = self.view.sel()[0] lines = (row_at(self.view, first.end()) - row_at(self.view, first.begin())) if lines > 0: chars = col_at(self.view, first.end()) else: chars = first.size() return (lines, chars, self.mode)
def lines(view, s, count=1): """ Return 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(row_at(view, s.b) + (count - 1), 0) # make sure we remove the last line if needed if ((row_at(view, b) == last_row(view)) and (view.substr(a - 1) == '\n')): a -= 1 return Region(a, view.full_line(b).b)
def restore_visual_data(self, data): rows, chars, old_mode = data first = self.view.sel()[0] if old_mode == VISUAL: if rows > 0: end = self.view.text_point( row_at(self.view, first.b) + rows, chars) else: end = first.b + chars self.view.sel().add(Region(first.b, end)) self.mode = VISUAL elif old_mode == VISUAL_LINE: rows, _, old_mode = data begin = self.view.line(first.b).a end = self.view.text_point( row_at(self.view, begin) + (rows - 1), 0) end = self.view.full_line(end).b self.view.sel().add(Region(begin, end)) self.mode = VISUAL_LINE
def inner_lines(view, s, count=1): """ Return 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(row_at(view, s.b) + (count - 1), 0) begin = view.line(s.b).a begin = next_non_blank(view, begin) return Region(begin, view.line(end).b)
def _resolve_line_reference(view, line_reference, current: int = 0) -> int: # Args: # view (View): The view where the calculation is made. # line_reference (list): The sequence of tokens defining the line range to be calculated. # current (int): Line number where we are now. last_token = None # XXX: what happens if there is no selection in the view? current = row_at(view, view.sel()[0].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 = _resolve_line_number(view, token, current) last_token = token return current
def _resolve_line_number(view, token, current): # type: (...) -> int # Args: # view (View): The view where the calculation is made. # token (Token): # current (int): Line number where we are now. if isinstance(token, TokenDot): return row_at(view, view.text_point(current, 0)) if isinstance(token, TokenDigits): return max(int(token.content) - 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): match = view.find(token.content, view.text_point(current, 0)) if not match: raise ValueError('pattern not found') return row_at(view, match.a) if isinstance(token, TokenSearchBackward): match = reverse_search_by_pt(view, token.content, 0, view.text_point(current, 0)) if not match: raise ValueError('pattern not found') return row_at(view, match.a) if isinstance(token, TokenMark): 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) elif 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) elif token.content in tuple('abcdefghijklmnopqrstuvwxyz'): # The state class is intentionally imported here instead of at the # begining of the file to avoid circular imports errors. The State # needs to refactored and replaced with some less god-like from NeoVintageous.nv.state import State address = State(view).marks.get_as_encoded_address(token.content) return view.rowcol(address.b)[0] raise NotImplementedError()