示例#1
0
    def on_activated(self, view):

        # Clear any visual selections in the view we are leaving. This mirrors
        # Vim behaviour. We can't put this functionality in the
        # view.on_deactivate() event, because that event is triggered when the
        # user right button clicks the view with the mouse, and we don't want
        # visual selections to be cleared on mouse right button clicks.
        if not view.settings().get('is_widget'):
            window = view.window()
            if window:
                active_group = window.active_group()
                for group in range(window.num_groups()):
                    if group != active_group:
                        other_view = window.active_view_in_group(group)
                        if other_view and other_view != view:
                            sel = other_view.sel()
                            if len(sel) > 0 and any([not s.empty() for s in sel]):
                                enter_normal_mode(other_view, State(other_view).mode)

        # Initialise view state.
        init_state(view)
示例#2
0
    def on_activated(self, view):

        # Clear any visual selections in the view we are leaving. This mirrors
        # Vim behaviour. We can't put this functionality in the
        # view.on_deactivate() event, because that event is triggered when the
        # user right button clicks the view with the mouse, and we don't want
        # visual selections to be cleared on mouse right button clicks.
        window = view.window()
        if window:
            active_group = window.active_group()
            for group in range(window.num_groups()):
                if group != active_group:
                    other_view = window.active_view_in_group(group)
                    if other_view and other_view != view:
                        sel = other_view.sel()
                        if len(sel) > 0:
                            sels_begin_at_pt = sel[0].begin()
                            sel.clear()
                            sel.add(sels_begin_at_pt)

        # Initialise view state.
        init_state(view)
示例#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()
示例#4
0
    def _feed_key(self,
                  key,
                  repeat_count=None,
                  do_eval=True,
                  check_user_mappings=True):
        # Args:
        #   key (str): Key pressed.
        #   repeat_count (int): Count to be used when repeating through the '.' command.
        #   do_eval (bool): Whether to evaluate the global state when it's in a
        #       runnable state. Most of the time, the default value of `True` should
        #       be used. Set to `False` when you want to manually control the global
        #       state's evaluation. For example, this is what the _nv_feed_key
        #       command does.
        #   check_user_mappings (bool):
        state = self.state

        mode = state.mode

        _log.debug('mode: %s', mode)

        # 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 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': 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)
        _log.debug('command %s %s', command, command.__class__.__mro__)

        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 (mode=%s)...', state.mode)

                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', command.sequence, new_keys)

                if ':' in new_keys:
                    do_ex_user_cmdline(self.window, new_keys)

                    return

                self.window.run_command('_nv_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)
            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()
示例#5
0
def plugin_loaded():

    try:
        pc_event = None
        from package_control import events
        if events.install('NeoVintageous'):
            pc_event = 'install'
        if events.post_upgrade('NeoVintageous'):
            pc_event = 'post_upgrade'
    except ImportError:
        pass  # Package Control isn't available (PC is not required)
    except Exception:
        import traceback
        traceback.print_exc()

    try:
        _update_ignored_packages()
    except Exception:
        import traceback
        traceback.print_exc()

    try:
        _exception = None

        view = sublime.active_window().active_view()
        # We can't expect a valid view to be returned from active_view(),
        # especially at startup e.g. at startup if the active view is an image
        # then active_view() returns None, because images are not *views*, they
        # are *sheets* (they can be retrieved via active_sheet()).
        # See https://github.com/SublimeTextIssues/Core/issues/2116.
        # TODO [review] Is it necessary to initialise the active view in plugin_loaded()? Doesn't the on_activated() event initialize activated views?  # noqa: E501
        if view:
            init_state(view, new_session=True)

    except Exception as e:
        _exception = e
        import traceback
        traceback.print_exc()

    if _EXCEPTION or _exception:

        try:
            _cleanup_views()
        except Exception:
            import traceback
            traceback.print_exc()

        if isinstance(_EXCEPTION, ImportError) or isinstance(
                _exception, ImportError):
            if pc_event == 'post_upgrade':
                message = "Failed to load some modules trying to upgrade NeoVintageous. "\
                          "Please restart Sublime Text to finish the upgrade."
            else:
                message = "Failed to load some NeoVintageous modules. "\
                          "Please restart Sublime Text."
        else:
            if pc_event == 'post_upgrade':
                message = "An error occurred trying to upgrade NeoVintageous. "\
                          "Please restart Sublime Text to finish the upgrade."
            else:
                message = "An error occurred trying to load NeoVintageous. "\
                          "Please restart Sublime Text."

        print('NeoVintageous: ERROR', message)
        sublime.message_dialog(message)