def update(self): line, col = vim_cursor() line -= 1 abs_pos = Position(line,col) if self._abs_pos: self._moved = abs_pos - self._abs_pos self._abs_pos = abs_pos # Update buffer infos cols = len(as_unicode(vim.current.buffer[line])) if self._cols: self._dcols = cols - self._cols self._cols = cols lines = len(vim.current.buffer) if self._lines: self._dlines = lines - self._lines self._lines = lines # Check if the buffer has changed in any ways self._text_changed = False # does it have more lines? if self._dlines: self._text_changed = True # did we stay in the same line and it has more columns now? elif not self.moved.line and self._dcols: self._text_changed = True # If the length didn't change but we moved a column, check if # the char under the cursor has changed (might be one char tab). elif self.moved.col == 1: self._text_changed = self._cline != as_unicode(vim.current.buffer[line]) self._lline = self._cline self._cline = as_unicode(vim.current.buffer[line])
def cursor_moved(self): self._vstate.update() if not self._vstate.buf_changed and not self._expect_move_wo_change: self._check_if_still_inside_snippet() if not self._ctab: return if self._vstate.buf_changed and self._ctab: # Detect a carriage return if self._vstate.moved.col <= 0 and self._vstate.moved.line == 1: # Multiple things might have happened: either the user entered # a newline character or pasted some text which means we have # to copy everything he entered on the last line and keep the # indent vim chose for this line. lline = as_unicode(vim.current.buffer[self._vstate.ppos.line]) # Another thing that might have happened is that a word # wrapped, in this case the last line is shortened and we must # delete what Vim deleted there line_was_shortened = len(self._vstate.last_line) > len(lline) # Another thing that might have happened is that vim has # adjusted the indent of the last line and therefore the line # effectively got longer. This means a newline was entered and # we quite definitively do not want the indent that vim added line_was_lengthened = len(lline) > len(self._vstate.last_line) user_didnt_enter_newline = len(lline) != self._vstate.ppos.col cline = as_unicode(vim.current.buffer[self._vstate.pos.line]) if line_was_lengthened: this_entered = vim.current.line[:self._vstate.pos.col] self._chars_entered('\n' + cline + this_entered, 1) if line_was_shortened and user_didnt_enter_newline: nchars_deleted_in_lline = self._vstate.ppos.col - len(lline) self._backspace(nchars_deleted_in_lline) nchars_wrapped_from_lline_after_cursor = \ len(self._vstate.last_line) - self._vstate.ppos.col self._chars_entered('\n' + cline [:len(cline)-nchars_wrapped_from_lline_after_cursor], 1) else: pentered = lline[self._vstate.ppos.col:] this_entered = vim.current.line[:self._vstate.pos.col] self._chars_entered(pentered + '\n' + this_entered) elif self._vstate.moved.line == 0 and self._vstate.moved.col<0: # Some deleting was going on self._backspace(-self._vstate.moved.col) elif self._vstate.moved.line < 0: # Backspace over line end self._backspace(1) else: line = as_unicode(vim.current.line) chars = line[self._vstate.pos.col - self._vstate.moved.col: self._vstate.pos.col] self._chars_entered(chars) self._expect_move_wo_change = False
def __init__(self, trigger, value, descr, options, globals): self._t = as_unicode(trigger) self._v = as_unicode(value) self._d = as_unicode(descr) self._opts = options self._matched = "" self._last_re = None self._globals = globals
def select_span(self, r): self._unmap_select_mode_mapping() delta = r.end - r.start lineno, col = r.start.line, r.start.col set_vim_cursor(lineno + 1, col) if delta.line == delta.col == 0: if col == 0 or vim.eval("mode()") != 'i' and \ col < len(as_unicode(vim.current.buffer[lineno])): feedkeys(r"\<Esc>i") else: feedkeys(r"\<Esc>a") else: # If a tabstop immediately starts with a newline, the selection # must start after the last character in the current line. But if # we are in insert mode and <Esc> out of it, we cannot go past the # last character with move_one_right and therefore cannot # visual-select this newline. We have to hack around this by adding # an extra space which we can select. Note that this problem could # be circumvent by selecting the tab backwards (that is starting # at the end); one would not need to modify the line for this. if col >= len(as_unicode(vim.current.buffer[lineno])): vim.current.buffer[lineno] += " " if delta.line: move_lines = "%ij" % delta.line else: move_lines = "" # Depending on the current mode and position, we # might need to move escape out of the mode and this # will move our cursor one left if col != 0 and vim.eval("mode()") == 'i': move_one_right = "l" else: move_one_right = "" # After moving to the correct line, we go back to column 0 # and select right from there. Note that the we have to select # one column less since vim's visual selection is including the # ending while Python slicing is excluding the ending. if r.end.col == 0 and not len(as_unicode(vim.current.buffer[r.end.line])): # Selecting should end on an empty line -> Select the previous # line till its end do_select = "k$" elif r.end.col > 1: do_select = "0%il" % (r.end.col-1) else: do_select = "0" move_cmd = LangMapTranslator().translate( r"\<Esc>%sv%s%s\<c-g>" % (move_one_right, move_lines, do_select) ) feedkeys(move_cmd)
def _get_before_after(self): """ Returns the text before and after the cursor as a tuple. """ lineno, col = vim.current.window.cursor # Note: we want byte position here line = vim.current.line # Get the word to the left of the current edit position before, after = as_unicode(line[:col]), as_unicode(line[col:]) return before, after
def reset(self, test_error=False): self._test_error = test_error self._snippets = {} self._visual_content = as_unicode("") while len(self._csnippets): self._current_snippet_is_done() self._reinit()
def _ask_snippets(self, snippets): """ Given a list of snippets, ask the user which one they want to use, and return it. """ # make a python list display = [ "%i: %s" % (i+1,s.description) for i,s in enumerate(snippets)] try: # let vim_string format it as a vim list rv = vim.eval(make_suitable_for_vim(as_unicode("inputlist(%s)") % vim_string(display))) if rv is None or rv == '0': return None rv = int(rv) if rv > len(snippets): rv = len(snippets) return snippets[rv-1] except vim.error as e: if str(e) == 'invalid expression': return None raise
def _vim_line_with_eol(ln): return as_unicode(vim.current.buffer[ln] + '\n')