def set_xpos(self, state): try: xpos = self._view.rowcol(self._view.sel()[0].b)[1] except Exception as e: console_message(str(e)) raise ValueError('could not set xpos') state.xpos = xpos
def update_xpos(self, force=False): if self.must_update_xpos or force: try: # TODO: we should check the current mode instead. ============ sel = self.view.sel()[0] pos = sel.b if not sel.empty(): if sel.a < sel.b: pos -= 1 # ============================================================ r = Region(self.view.line(pos).a, pos) counter = Counter(self.view.substr(r)) tab_size = self.view.settings().get('tab_size') xpos = (self.view.rowcol(pos)[1] + ((counter['\t'] * tab_size) - counter['\t'])) except Exception as e: console_message(str(e)) _log.exception('error setting xpos; default to 0') self.xpos = 0 return else: self.xpos = xpos
def run(self, key, repeat_count=None, do_eval=True, check_user_mappings=True): _log.info( 'key evt: %s repeat_count=%s do_eval=%s check_user_mappings=%s', key, repeat_count, do_eval, check_user_mappings) # noqa: E501 state = self.state # If the user has made selections with the mouse, we may be in an # inconsistent state. Try to remedy that. if (state.view.has_non_empty_selection_region() and state.mode not in (VISUAL, VISUAL_LINE, VISUAL_BLOCK, SELECT)): init_state(state.view) if key.lower() == '<esc>': self.window.run_command('_enter_normal_mode', {'mode': state.mode}) state.reset_command_data() return state.sequence += key state.display_status() if state.must_capture_register_name: _log.debug('capturing register name...') state.register = key state.partial_sequence = '' return if state.must_collect_input: _log.debug('collecting input...') state.process_input(key) if state.runnable(): _log.debug('state is runnable') if do_eval: _log.debug('evaluating state...') state.eval() state.reset_command_data() return if repeat_count: state.action_count = str(repeat_count) if self._handle_count(state, key, repeat_count): _log.debug('handled count') return state.partial_sequence += key if check_user_mappings and mappings_is_incomplete( state.mode, state.partial_sequence): _log.debug('found incomplete mapping') return command = mappings_resolve(state, check_user_mappings=check_user_mappings) if isinstance(command, ViOpenRegister): _log.debug('opening register...') state.must_capture_register_name = True return # XXX: This doesn't seem to be correct. If we are in OPERATOR_PENDING mode, we should # most probably not have to wipe the state. if isinstance(command, Mapping): _log.debug('found user mapping...') if do_eval: _log.debug('evaluating user mapping...') new_keys = command.mapping if state.mode == OPERATOR_PENDING: new_keys = state.sequence[:-len(state.partial_sequence )] + command.mapping reg = state.register acount = state.action_count mcount = state.motion_count state.reset_command_data() state.register = reg state.motion_count = mcount state.action_count = acount _log.info('user mapping %s -> %s', key, new_keys) # Support for basic Command-line mode mappings: # # `:Command<CR>` maps to Sublime Text command (starts with uppercase letter). # `:command<CR>` maps to Command-line mode command. if ':' in new_keys: match = re.match( '^\\:(?P<cmd_line_command>[a-zA-Z][a-zA-Z_]*)\\<CR\\>', new_keys) if match: cmd_line_command = match.group('cmd_line_command') if cmd_line_command[0].isupper(): # run regular sublime text command def _coerce_to_snakecase(string): string = re.sub(r"([A-Z]+)([A-Z][a-z])", r'\1_\2', string) string = re.sub(r"([a-z\d])([A-Z])", r'\1_\2', string) string = string.replace("-", "_") return string.lower() command = _coerce_to_snakecase(cmd_line_command) command_args = {} else: command = 'vi_colon_input' command_args = {'cmd_line': ':' + cmd_line_command} _log.info('run command -> %s %s', command, command_args) return self.window.run_command(command, command_args) if ':' == new_keys: return self.window.run_command('vi_colon_input') return console_message( 'invalid command line mapping %s -> %s (only `:[a-zA-Z][a-zA-Z_]*<CR>` is supported)' % (command.head, command.mapping)) # noqa: E501 self.window.run_command('process_notation', { 'keys': new_keys, 'check_user_mappings': False }) return if isinstance(command, ViOpenNameSpace): # Keep collecting input to complete the sequence. For example, we # may have typed 'g' _log.info('opening namespace') return elif isinstance(command, ViMissingCommandDef): _log.info('found missing command...') bare_seq = to_bare_command_name(state.sequence) if state.mode == OPERATOR_PENDING: # We might be looking at a command like 'dd'. The first 'd' is # mapped for normal mode, but the second is missing in # operator pending mode, so we get a missing command. Try to # build the full command now. # # Exclude user mappings, since they've already been given a # chance to evaluate. command = mappings_resolve(state, sequence=bare_seq, mode=NORMAL, check_user_mappings=False) else: command = mappings_resolve(state, sequence=bare_seq) if isinstance(command, ViMissingCommandDef): _log.debug('unmapped sequence %s', state.sequence) state.mode = NORMAL state.reset_command_data() return ui_blink() if (state.mode == OPERATOR_PENDING and isinstance(command, ViOperatorDef)): _log.info('found operator pending...') # TODO: This may be unreachable code by now. ??? # we're expecting a motion, but we could still get an action. # For example, dd, g~g~ or g~~ # remove counts action_seq = to_bare_command_name(state.sequence) _log.debug('action sequence %s', action_seq) command = mappings_resolve(state, sequence=action_seq, mode=NORMAL) # TODO: Make _missing a command. if isinstance(command, ViMissingCommandDef): _log.debug('unmapped sequence %s', state.sequence) state.reset_command_data() return if not command['motion_required']: state.mode = NORMAL state.set_command(command) if state.mode == OPERATOR_PENDING: state.reset_partial_sequence() if do_eval: _log.info('evaluating state...') state.eval()