def _execute_action( self, action, context, additional_locals={}, compiled_action=None ): mark_to_use = "`" with vim_helper.save_mark(mark_to_use): vim_helper.set_mark_from_pos(mark_to_use, vim_helper.get_cursor_pos()) cursor_line_before = vim_helper.buf.line_till_cursor locals = {"context": context} locals.update(additional_locals) snip = self._eval_code(action, locals, compiled_action) if snip.cursor.is_set(): vim_helper.buf.cursor = Position( snip.cursor._cursor[0], snip.cursor._cursor[1] ) else: new_mark_pos = vim_helper.get_mark_pos(mark_to_use) cursor_invalid = False if vim_helper._is_pos_zero(new_mark_pos): cursor_invalid = True else: vim_helper.set_cursor_from_pos(new_mark_pos) if cursor_line_before != vim_helper.buf.line_till_cursor: cursor_invalid = True if cursor_invalid: raise PebkacError( "line under the cursor was modified, but " + '"snip.cursor" variable is not set; either set set ' + '"snip.cursor" to new cursor position, or do not ' + "modify cursor line" ) return snip
def _do_edit(self, cmd, ctab=None): if self._done: # do as what parent class do TabStop._do_edit(self, cmd, ctab) return ctype, line, col, cmd_text = cmd cursor = vim_helper.get_cursor_pos() [buf_num, cursor_line] = map(int, cursor[0:2]) # trying to get what user inputted in current buffer if ctype == "I": self._input_chars.append(cmd_text) elif ctype == "D": line_text = vim_helper.buf[cursor_line - 1] self._input_chars = list(line_text[self._start.col:col]) inputted_text = "".join(self._input_chars) if not self._input_chars: return # if there are more than 9 selection candidates, # may need to wait for 2 inputs to determine selection number is_all_digits = True has_selection_terminator = False # input string sub string of pure digits inputted_text_for_num = inputted_text for [i, s] in enumerate(self._input_chars): if s == " ": # treat space as a terminator for selection has_selection_terminator = True inputted_text_for_num = inputted_text[0:i] elif not s.isdigit(): is_all_digits = False should_continue_input = False if is_all_digits or has_selection_terminator: index_strs = [ str(index) for index in list(range(1, len(self._choice_list) + 1)) ] matched_index_strs = list( filter(lambda s: s.startswith(inputted_text_for_num), index_strs)) remained_choice_list = [] if len(matched_index_strs) == 0: remained_choice_list = [] elif has_selection_terminator: if inputted_text_for_num: num = int(inputted_text_for_num) remained_choice_list = list(self._choice_list)[num - 1:num] elif len(matched_index_strs) == 1: num = int(inputted_text_for_num) remained_choice_list = list(self._choice_list)[num - 1:num] else: should_continue_input = True else: remained_choice_list = [] if should_continue_input: # will wait for further input return buf = vim_helper.buf if len(remained_choice_list) == 0: # no matched choice, should quit selection and go on with inputted text overwrite_text = inputted_text_for_num self._done = True elif len(remained_choice_list) == 1: # only one match matched_choice = remained_choice_list[0] overwrite_text = matched_choice self._done = True if overwrite_text is not None: old_end_col = self._end.col # change _end.col, thus `overwrite` won't alter texts after this tabstop displayed_text_end_col = self._start.col + len(inputted_text) self._end.col = displayed_text_end_col self.overwrite(buf, overwrite_text) # notify all tabstops those in the same line and after this to adjust their positions pivot = Position(line, old_end_col) diff_col = displayed_text_end_col - old_end_col self._parent._child_has_moved(self._parent.children.index(self), pivot, Position(0, diff_col)) vim_helper.set_cursor_from_pos( [buf_num, cursor_line, self._end.col + 1])