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)
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)
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()
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()
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)