def _do_ys(view, edit, mode=None, motion=None, replacement='"', count=1): def surround(view, edit, s, replacement): open_, close_ = _get_punctuation_mark_replacements(replacement) # Takes <q class="foo"> and produces: <q class="foo">text</q> if open_.startswith('<'): name = open_[1:].strip()[:-1].strip() name = name.split(' ', 1)[0] view.insert(edit, s.b, "</{0}>".format(name)) view.insert(edit, s.a, replacement) return view.insert(edit, s.end(), close_) view.insert(edit, s.begin(), open_) def f(view, s): if mode == INTERNAL_NORMAL: surround(view, edit, s, replacement) return Region(s.begin()) elif mode in (VISUAL, VISUAL_BLOCK): surround(view, edit, s, replacement) return Region(s.begin()) return s if not motion and not view.has_non_empty_selection_region(): enter_normal_mode(view, mode) raise ValueError('motion required') if mode == INTERNAL_NORMAL: run_motion(view, motion) if replacement: _rsynced_regions_transformer(view, f) enter_normal_mode(view, mode)
def _do_C(view, edit, mode, count=1, motion=None): def f(view, s): return Region(s.begin()) if motion: run_motion(view, motion) elif mode not in (VISUAL, VISUAL_LINE): return ui_bell() view.run_command('toggle_comment', {'block': True}) regions_transformer(view, f) enter_normal_mode(view, mode)
def _do_c(view, edit, mode, count=1, motion=None): def f(view, s): return Region(s.begin()) if motion: run_motion(view, motion) elif mode not in (VISUAL, VISUAL_LINE): return ui_bell() view.run_command('toggle_comment', {'block': False}) regions_transformer(view, f) line = view.line(view.sel()[0].begin()) pt = line.begin() if line.size() > 0: line = view.find('^\\s*', line.begin()) pt = line.end() set_selection(view, pt) enter_normal_mode(view, mode)
def _do_ys(view, edit, mode: str = None, motion=None, replacement: str = '"', count: int = 1) -> None: def _surround(view, edit, s, replacement: str) -> None: replacement_open, replacement_close = _get_punctuation_mark_replacements( replacement) if replacement_open.startswith('<'): view.insert(edit, s.b, replacement_close) view.insert(edit, s.a, replacement_open) return view.insert(edit, s.end(), replacement_close) view.insert(edit, s.begin(), replacement_open) def f(view, s): if mode == INTERNAL_NORMAL: _surround(view, edit, s, replacement) return Region(s.begin()) elif mode in (VISUAL, VISUAL_BLOCK): _surround(view, edit, s, replacement) return Region(s.begin()) return s if not motion and not view.has_non_empty_selection_region(): enter_normal_mode(view, mode) raise ValueError('motion required') if mode == INTERNAL_NORMAL: run_motion(view, motion) if replacement: _rsynced_regions_transformer(view, f) enter_normal_mode(view, mode)
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 if not self.runnable(): return if self.action and self.motion: action_cmd = self.action.translate(self) _log.debug('action_cmd = %s', action_cmd) motion_cmd = self.motion.translate(self) _log.debug('motion_cmd = %s', motion_cmd) _log.debug('changing to INTERNAL_NORMAL...') self.mode = 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 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') macros.add_step(self, 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...') set_repeat_data( self.view, ('vi', str(self.sequence), self.mode, None)) self.reset_command_data() return if self.motion: motion_cmd = self.motion.translate(self) macros.add_step(self, 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_motion(self.view, motion_cmd) 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 macros.add_step(self, action_cmd['action'], action_cmd['action_args']) run_action(active_window(), action_cmd) if not (self.processing_notation and self.glue_until_normal_mode): if action.repeatable: _log.debug('action is repeatable, setting repeat data...') set_repeat_data(self.view, ('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()