Beispiel #1
0
    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
Beispiel #2
0
 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
Beispiel #3
0
    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()