def registers_get_for_paste(view, register: str, mode: str) -> tuple: values = _get(view, register) linewise = _is_register_linewise(register) filtered = [] if values: # Populate unnamed register with the text we're about to paste into (the # text we're about to replace), but only if there was something in # requested register (not empty), and we're in VISUAL mode. if is_visual_mode(mode): current_content = _get_selected_text( view, linewise=(mode == VISUAL_LINE)) if current_content: _set(view, _UNNAMED, current_content, linewise=(mode == VISUAL_LINE)) for value in values: if mode == VISUAL: if linewise and value and value[0] != '\n': value = '\n' + value if mode == VISUAL_LINE: # Pasting characterwise content in visual line mode needs an # extra newline to account for visual line eol newline. if not linewise: value += '\n' filtered.append(value) return filtered, linewise
def extract_word(view, mode, sel): if is_visual_mode(mode): word = view.substr(sel) else: word = view.substr(view.word(sel)) return word
def get_for_big_p(self, register, mode): if not register: register = _UNNAMED as_str = '' values = self._get(register) linewise = _is_register_linewise(register) if values: # Populate unnamed register with the text we're about to paste into # (the text we're about to replace), but only if there was something # in requested register (not empty), and we're in VISUAL mode. if is_visual_mode(mode): current_content = self._get_selected_text(linewise=(mode == VISUAL_LINE)) if current_content: self._set(_UNNAMED, current_content, linewise=(mode == VISUAL_LINE)) # If register content is from a linewise operation, and in VISUAL # mode, and doesn't begin with newline, then a newline is prefixed. as_str = ''.join(values) if as_str and linewise and is_visual_mode(mode) and as_str[0] != '\n': as_str = '\n' + as_str return as_str, linewise
def get_for_p(self, register, mode): if not register: register = _UNNAMED values = self._get(register) linewise = _is_register_linewise(register) # Populate unnamed register with the text we're about to paste into (the # text we're about to replace), but only if there was something in # requested register (not empty), and we're in VISUAL mode. if values and is_visual_mode(mode): content = self._get_selected_text(linewise=(mode == VISUAL_LINE)) if content: self._set(_UNNAMED, content, linewise=(mode == VISUAL_LINE)) return values, linewise
def set_command(self, command): # type: (ViCommandDefBase) -> None # Set the current command. # # Args: # command (ViCommandDefBase): A command definition. # # Raises: # ValueError: If too many motions. # ValueError: If too many actions. # ValueError: Unexpected command type. assert isinstance( command, ViCommandDefBase), 'ViCommandDefBase expected, got {}'.format( type(command)) # FIXME # noqa: E501 is_runnable = self.runnable() if isinstance(command, ViMotionDef): if is_runnable: # We already have a motion, so this looks like an error. raise ValueError('too many motions') self.motion = command if self.mode == OPERATOR_PENDING: self.mode = NORMAL self._set_parsers(command) elif isinstance(command, ViOperatorDef): if is_runnable: # We already have an action, so this looks like an error. raise ValueError('too many actions') self.action = command if (self.action.motion_required and not is_visual_mode(self.mode)): self.mode = OPERATOR_PENDING self._set_parsers(command) else: raise ValueError('unexpected command type')
def set_command(self, command): # type: (ViCommandDefBase) -> None # Set the current command. # # Args: # command (ViCommandDefBase): A command definition. # # Raises: # ValueError: If too many motions. # ValueError: If too many actions. # ValueError: Unexpected command type. assert isinstance( command, ViCommandDefBase), 'ViCommandDefBase expected, got {}'.format( type(command)) is_runnable = self.runnable() if isinstance(command, ViMotionDef): if is_runnable: raise ValueError('too many motions') self.motion = command if self.mode == OPERATOR_PENDING: self.mode = NORMAL elif isinstance(command, ViOperatorDef): if is_runnable: raise ValueError('too many actions') self.action = command if command.motion_required and not is_visual_mode(self.mode): self.mode = OPERATOR_PENDING else: raise ValueError('unexpected command type') if not self.non_interactive: if command.accept_input and command.input_parser and command.input_parser.is_type_via_panel( ): command.input_parser.run_command()
def scroll_into_view(self): # type: () -> None view = active_window().active_view() if view: # Show the *last* cursor on screen. There is currently no way to # identify the "active" cursor of a multiple cursor selection. sel = view.sel()[-1] target_pt = sel.b # In VISUAL mode we need to make sure that any newline at the end of # the selection is NOT included in the target, because otherwise an # extra line after the target line will also be scrolled into view. if is_visual_mode(self.mode): if sel.b > sel.a: if view.substr(sel.b - 1) == '\n': target_pt = max(0, target_pt - 1) # Use the start point of the target line to avoid # horizontal scrolling. For example, this can happen in # VISUAL LINE mode when the EOL is off-screen. target_pt = max(0, view.line(target_pt).a) view.show(target_pt, False)
def evaluate_state(view) -> None: _log.debug('evaluating...') if not is_runnable(view): _log.debug('not runnable!') return action = get_action(view) motion = get_motion(view) if action and motion: # Evaluate action with motion: runs the action with the motion as an # argument. The motion's mode is set to INTERNAL_NORMAL and is run # by the action internally to make the selection it operates on. For # example the motion commands can be used after an operator command, # to have the command operate on the text that was moved over. action_cmd = action.translate(view) motion_cmd = motion.translate(view) _log.debug('action: %s', action_cmd) _log.debug('motion: %s', motion_cmd) set_mode(view, INTERNAL_NORMAL) if 'mode' in action_cmd['action_args']: action_cmd['action_args']['mode'] = INTERNAL_NORMAL if 'mode' in motion_cmd['motion_args']: motion_cmd['motion_args']['mode'] = INTERNAL_NORMAL args = action_cmd['action_args'] args['count'] = 1 # Let the action run the motion within its edit object so that we # don't need to worry about grouping edits to the buffer. args['motion'] = motion_cmd if get_glue_until_normal_mode( view) and not is_processing_notation(view): run_window_command('mark_undo_groups_for_gluing') add_macro_step(view, action_cmd['action'], args) run_window_command(action_cmd['action'], args) if is_interactive(view) and get_action(view).repeatable: set_repeat_data( view, ('vi', str(get_sequence(view)), get_mode(view), None)) reset_command_data(view) return # Nothing more to do. if motion: # Evaluate motion: Run it. motion_cmd = motion.translate(view) _log.debug('motion: %s', motion_cmd) add_macro_step(view, motion_cmd['motion'], motion_cmd['motion_args']) run_motion(view, motion_cmd) if action: # Evaluate action. Run it. action_cmd = action.translate(view) _log.debug('action: %s', action_cmd) if get_mode(view) == NORMAL: set_mode(view, INTERNAL_NORMAL) if 'mode' in action_cmd['action_args']: action_cmd['action_args']['mode'] = INTERNAL_NORMAL elif is_visual_mode(get_mode(view)): # Special-case exclusion: saving the previous selection would # overwrite the previous selection needed e.g. gv in a VISUAL # mode needs to expand or contract to previous selection. if action_cmd['action'] != '_vi_gv': save_previous_selection(view, get_mode(view)) # Some commands, like 'i' or 'a', open a series of edits that need # to be grouped together unless we are gluing a larger sequence # through _nv_process_notation. For example, aFOOBAR<Esc> should be # grouped atomically, but not inside a sequence like # iXXX<Esc>llaYYY<Esc>, where we want to group the whole sequence # instead. if get_glue_until_normal_mode( view) and not is_processing_notation(view): run_window_command('mark_undo_groups_for_gluing') sequence = get_sequence(view) visual_repeat_data = get_visual_repeat_data(view, get_mode(view)) action = get_action(view) add_macro_step(view, action_cmd['action'], action_cmd['action_args']) run_action(active_window(), action_cmd) if not (is_processing_notation(view) and get_glue_until_normal_mode(view)) and action.repeatable: set_repeat_data( view, ('vi', sequence, get_mode(view), visual_repeat_data)) if get_mode(view) == INTERNAL_NORMAL: set_mode(view, NORMAL) reset_command_data(view)
def eval(self): # type: () -> None # Run data as a command if possible. if not self.runnable(): return if self.action and self.motion: action_cmd = self.action.translate(self) motion_cmd = self.motion.translate(self) _log.debug('changing to INTERNAL_NORMAL...') self.mode = INTERNAL_NORMAL # TODO Make motions and actions require a 'mode' param. if 'mode' in action_cmd['action_args']: _log.debug('action has a mode, changing to INTERNAL_NORMAL...') action_cmd['action_args']['mode'] = INTERNAL_NORMAL if 'mode' in motion_cmd['motion_args']: _log.debug('motion has a mode, changing to INTERNAL_NORMAL...') motion_cmd['motion_args']['mode'] = INTERNAL_NORMAL args = action_cmd['action_args'] args['count'] = 1 # Let the action run the motion within its edit object so that we # don't need to worry about grouping edits to the buffer. args['motion'] = motion_cmd if self.glue_until_normal_mode and not self.processing_notation: # Tell Sublime Text that it should group all the next edits # until we enter normal mode again. run_window_command('mark_undo_groups_for_gluing') self.add_macro_step(action_cmd['action'], args) run_window_command(action_cmd['action'], args) if not self.non_interactive: if self.action.repeatable: _log.debug('action is repeatable, setting repeat data...') self.repeat_data = ('vi', str(self.sequence), self.mode, None) self.reset_command_data() return if self.motion: motion_cmd = self.motion.translate(self) self.add_macro_step(motion_cmd['motion'], motion_cmd['motion_args']) # All motions are subclasses of ViTextCommandBase, so it's safe to # run the command via the current view. run_view_command(self.view, motion_cmd['motion'], motion_cmd['motion_args']) if self.action: action_cmd = self.action.translate(self) if self.mode == NORMAL: _log.debug('is NORMAL, changing to INTERNAL_NORMAL...') self.mode = INTERNAL_NORMAL if 'mode' in action_cmd['action_args']: _log.debug( 'action has a mode, changing to INTERNAL_NORMAL...') action_cmd['action_args']['mode'] = INTERNAL_NORMAL elif is_visual_mode(self.mode): # Special-case exclusion: saving the previous selection would # overwrite the previous selection needed e.g. gv in a VISUAL # mode needs to expand or contract to previous selection. if action_cmd['action'] != '_vi_gv': _log.debug('is VISUAL, saving selection...') save_previous_selection(self.view, self.mode) # Some commands, like 'i' or 'a', open a series of edits that need # to be grouped together unless we are gluing a larger sequence # through _nv_process_notation. For example, aFOOBAR<Esc> should be # grouped atomically, but not inside a sequence like # iXXX<Esc>llaYYY<Esc>, where we want to group the whole sequence # instead. if self.glue_until_normal_mode and not self.processing_notation: # Tell Sublime Text that it should group all the next edits # until we enter normal mode again. run_window_command('mark_undo_groups_for_gluing') seq = self.sequence visual_repeat_data = self.get_visual_repeat_data() action = self.action self.add_macro_step(action_cmd['action'], action_cmd['action_args']) run_window_command(action_cmd['action'], action_cmd['action_args']) if not (self.processing_notation and self.glue_until_normal_mode): if action.repeatable: _log.debug('action is repeatable, setting repeat data...') self.repeat_data = ('vi', seq, self.mode, visual_repeat_data) if self.mode == INTERNAL_NORMAL: _log.debug('is INTERNAL_NORMAL, changing to NORMAL...') self.enter_normal_mode() self.reset_command_data()