def _is_insert_mode(view, operator, operand, match_all): # TODO This currently returns true for all non-normal modes e.g. Replace # mode. Fixing this will break things, for example <Esc> in replace mode # would break, a few things need to be reworked to fix this. return _check_query_context_value( (not view.settings().get('command_mode') and is_view(view)), operator, operand, match_all)
def _is_command_mode(view, operator=OP_EQUAL, operand=True, match_all=False): return _check_query_context_value( (view.settings().get('command_mode') and is_view(view)), operator, operand, match_all )
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 is_view(view): 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, get_mode(other_view)) # Initialise view. init_state(view)
def init_state(view) -> None: # Initialise view state. # # Runs every time a view is activated, loaded, etc. # Don't initialise if we get a console, widget, panel, or any other view # where Vim modes are not relevant. Some related initialised settings that # may cause unexpected behaviours if they exist are erased "cleaned" too. if not is_view(view): try: # TODO "cleaning" views that are not initialised shouldn't be necessary? clean_view(view) except Exception: _log.debug( 'could not clean an object: console, widget, panel, etc.') finally: return if not get_reset_during_init(view): # Probably exiting from an input panel, like when using '/'. Don't reset # the global state, as it may contain data needed to complete the # command that's being built. set_reset_during_init(view, True) return mode = get_mode(view) # Does user want to reset mode (to normal mode) when initialising state? if mode not in (NORMAL, UNKNOWN) and not get_setting( view, 'reset_mode_when_switching_tabs'): return # Fix malformed selection: if we have no selections, add one. if len(view.sel()) == 0: view.sel().add(0) if get_setting(view, 'default_mode') == 'insert': if mode in (NORMAL, UNKNOWN): enter_insert_mode(view, mode) elif mode in (VISUAL, VISUAL_LINE, VISUAL_BLOCK): # Visual modes are not reset (to normal mode), because actions like # pressing the super key or opening a command-palette/overlay will cause # the active view to lose focus and when focus is received again it # triggers the on_activated() event, this in turn initialises the view' # state, which would reset the visual mode to normal mode, therefore, # for example, any command run from the command palette that expects to # operate on a visual selection wouldn't work because the visual # selection is reset to normal mode before the command has time to run. # See https://github.com/NeoVintageous/NeoVintageous/issues/547 pass elif mode in (INSERT, REPLACE): # NOTE that the mode is not passed as an argument because it causes the # cursor to move back one point from it's current position, for example # when pressing i<Esc>i<Esc>i<Esc> the cursor moves one point each time, # which is expected, but not expected when initialising state. But not # passing the mode may also be causing some other hidden bugs too. view.window().run_command('_enter_normal_mode', {'from_init': True}) elif mode != VISUAL and view.has_non_empty_selection_region(): # Try to fixup a malformed visual state. For example, apparently this # can happen when a search is performed via a search panel and "Find # All" is pressed. In that case, multiple selections may need fixing. view.window().run_command('_enter_visual_mode', {'mode': mode}) else: # This may be run when we're coming from cmdline mode. mode = VISUAL if view.has_non_empty_selection_region() else mode view.window().run_command('_enter_normal_mode', { 'mode': mode, 'from_init': True }) reset_command_data(view)
def init_state(view): # type: (...) -> None # Initialise view state. # # Runs at startup and every time a view gets activated, loaded, etc. # # Args: # :view (sublime.View): if not is_view(view): # Abort if we got a console, widget, panel... try: # XXX: All this seems to be necessary here. if not is_ignored_but_command_mode(view): view.settings().set('command_mode', False) view.settings().set('inverse_caret_state', False) view.settings().erase('vintage') except Exception: # TODO [review] Exception handling _log.debug( 'error initialising irregular view i.e. console, widget, panel, etc.' ) finally: return state = State(view) if not get_reset_during_init(view): # Probably exiting from an input panel, like when using '/'. Don't # reset the global state, as it may contain data needed to complete # the command that's being built. set_reset_during_init(view, True) return mode = state.mode # Non-standard user setting. reset = get_setting(view, 'reset_mode_when_switching_tabs') # XXX: If the view was already in normal mode, we still need to run the # init code. I believe this is due to Sublime Text (intentionally) not # serializing the inverted caret state and the command_mode setting when # first loading a file. # If the mode is unknown, it might be a new file. Let normal mode setup # continue. if not reset and (mode not in (NORMAL, UNKNOWN)): return # If we have no selections, add one. if len(view.sel()) == 0: view.sel().add(0) if get_setting(view, 'default_mode') == 'insert': if mode in (NORMAL, UNKNOWN): enter_insert_mode(view, mode) elif mode in (VISUAL, VISUAL_LINE): # This was commented out to fix the issue of visual selections being # lost because some keys, like the super key, cause Sublime to lose # focus, and when focus comes back it triggers the on_activated() event, # which then initializes state, which then causes visual mode to enter # normal mode. Note that there may be regressions as a side effect. # See nv/events.py#NeoVintageousEvents::on_activated(). # See https://github.com/NeoVintageous/NeoVintageous/issues/547 # view.window().run_command('_enter_normal_mode', {'from_init': True}) _log.debug('initializing %s state', mode) elif mode in (INSERT, REPLACE): # TODO: Don't we need to pass a mode here? view.window().run_command('_enter_normal_mode', {'from_init': True}) elif view.has_non_empty_selection_region() and mode != VISUAL: # Runs, for example, when we've performed a search via ST3 search panel # and we've pressed 'Find All'. In this case, we want to ensure a # consistent state for multiple selections. # TODO We could end up with multiple selections in other ways that bypass init_state. state.mode = VISUAL else: # This may be run when we're coming from cmdline mode. mode = VISUAL if view.has_non_empty_selection_region() else mode state.enter_normal_mode() view.window().run_command('_enter_normal_mode', { 'mode': mode, 'from_init': True }) state.reset_command_data()
def init_state(view): # type: (...) -> None # Initialise view state. # # Runs at startup and every time a view gets activated, loaded, etc. # # Args: # :view (sublime.View): if not is_view(view): # Abort if we got a console, widget, panel... try: # XXX: All this seems to be necessary here. if not is_ignored_but_command_mode(view): view.settings().set('command_mode', False) view.settings().set('inverse_caret_state', False) view.settings().erase('vintage') except Exception: # TODO [review] Exception handling _log.debug( 'error initialising irregular view i.e. console, widget, panel, etc.' ) finally: return state = State(view) if not state.reset_during_init: # Probably exiting from an input panel, like when using '/'. Don't # reset the global state, as it may contain data needed to complete # the command that's being built. state.reset_during_init = True return mode = state.mode # Non-standard user setting. reset = state.settings.view['vintageous_reset_mode_when_switching_tabs'] # XXX: If the view was already in normal mode, we still need to run the # init code. I believe this is due to Sublime Text (intentionally) not # serializing the inverted caret state and the command_mode setting when # first loading a file. # If the mode is unknown, it might be a new file. Let normal mode setup # continue. if not reset and (mode not in (NORMAL, UNKNOWN)): return # If we have no selections, add one. if len(view.sel()) == 0: view.sel().add(Region(0)) if mode in (VISUAL, VISUAL_LINE): # TODO: Don't we need to pass a mode here? view.window().run_command('_enter_normal_mode', {'from_init': True}) elif mode in (INSERT, REPLACE): # TODO: Don't we need to pass a mode here? view.window().run_command('_enter_normal_mode', {'from_init': True}) elif view.has_non_empty_selection_region() and mode != VISUAL: # Runs, for example, when we've performed a search via ST3 search panel # and we've pressed 'Find All'. In this case, we want to ensure a # consistent state for multiple selections. # TODO We could end up with multiple selections in other ways that bypass init_state. state.mode = VISUAL else: # This may be run when we're coming from cmdline mode. mode = VISUAL if view.has_non_empty_selection_region() else mode state.enter_normal_mode() view.window().run_command('_enter_normal_mode', { 'mode': mode, 'from_init': True }) state.reset_command_data()
def on_post_save(self, view): if is_view(view): # Ensure the carets are within valid bounds. For instance, this is a # concern when 'trim_trailing_white_space_on_save' is set to true. fix_eol_cursor(view, get_mode(view))
def on_load(self, view): if is_view(view) and get_option(view, 'modeline'): do_modeline(view)