def run(self): # We define our own transformer here because we want to handle undo as a special case. # TODO: I don't know if it needs to be an special case in reality. def f(view, s): # Compensates the move issued below. if s.a < s.b : return sublime.Region(s.a + 1, s.a + 1) else: return sublime.Region(s.a, s.a) state = VintageState(self.view) for i in range(state.count): self.view.run_command('undo') if self.view.has_non_empty_selection_region(): regions_transformer(self.view, f) # !! HACK !! ///////////////////////////////////////////////////////// # This is a hack to work around an issue in Sublime Text: # When undoing in normal mode, Sublime Text seems to prime a move by chars # forward that has never been requested by the user or Vintageous. # As far as I can tell, Vintageous isn't at fault here, but it seems weird # to think that Sublime Text is wrong. self.view.run_command('move', {'by': 'characters', 'forward': False}) # //////////////////////////////////////////////////////////////////// state.update_xpos() # Ensure that we wipe the count, if any. state.reset()
def run(self): # We define our own transformer here because we want to handle undo as a special case. # TODO: I don't know if it needs to be an special case in reality. def f(view, s): # Compensates the move issued below. if s.a < s.b: return sublime.Region(s.a + 1, s.a + 1) else: return sublime.Region(s.a, s.a) state = VintageState(self.view) for i in range(state.count): self.view.run_command('undo') if self.view.has_non_empty_selection_region(): regions_transformer(self.view, f) # !! HACK !! ///////////////////////////////////////////////////////// # This is a hack to work around an issue in Sublime Text: # When undoing in normal mode, Sublime Text seems to prime a move by chars # forward that has never been requested by the user or Vintageous. # As far as I can tell, Vintageous isn't at fault here, but it seems weird # to think that Sublime Text is wrong. self.view.run_command('move', { 'by': 'characters', 'forward': False }) # //////////////////////////////////////////////////////////////////// state.update_xpos() # Ensure that we wipe the count, if any. state.reset()
def run(self): state = VintageState(self.view) try: cmd, args, _ = state.repeat_command except TypeError: # Unreachable. return if not cmd: return elif cmd == 'vi_run': args['next_mode'] = MODE_NORMAL args['follow_up_mode'] = 'vi_enter_normal_mode' args['count'] = state.count * args['count'] self.view.run_command(cmd, args) elif cmd == 'sequence': for i, _ in enumerate(args['commands']): # Access this shape: {"commands":[['vi_run', {"foo": 100}],...]} args['commands'][i][1]['next_mode'] = MODE_NORMAL args['commands'][i][1][ 'follow_up_mode'] = 'vi_enter_normal_mode' # TODO: Implement counts properly for 'sequence' command. for i in range(state.count): self.view.run_command(cmd, args) # Ensure we wipe count data if any. state.reset() # XXX: Needed here? Maybe enter_... type commands should be IrreversibleTextCommands so we # must/can call them whenever we need them withouth affecting the undo stack. self.view.run_command('vi_enter_normal_mode')
def run(self, edit): state = VintageState(self.view) state.enter_insert_mode() self.view.run_command('collapse_to_direction') # 5i and friends don't enter INSERTMODE through this command, so it's fine resetting here. # We need to reset so that things like CTRL+R,ESC (INSERTMODE) cancel pending state. state.reset()
def run(self): state = VintageState(self.view) try: cmd, args, _ = state.repeat_command except TypeError: # Unreachable. return if not cmd: return elif cmd == 'vi_run': args['next_mode'] = MODE_NORMAL args['follow_up_mode'] = 'vi_enter_normal_mode' args['count'] = state.count * args['count'] self.view.run_command(cmd, args) elif cmd == 'sequence': for i, _ in enumerate(args['commands']): # We can have either 'vi_run' commands or plain insert mode commands. if args['commands'][i][0] == 'vi_run': # Access this shape: {"commands":[['vi_run', {"foo": 100}],...]} args['commands'][i][1]['next_mode'] = MODE_NORMAL args['commands'][i][1]['follow_up_mode'] = 'vi_enter_normal_mode' # TODO: Implement counts properly for 'sequence' command. for i in range(state.count): self.view.run_command(cmd, args) # Ensure we wipe count data if any. state.reset() # XXX: Needed here? Maybe enter_... type commands should be IrreversibleTextCommands so we # must/can call them whenever we need them withouth affecting the undo stack. self.view.run_command('vi_enter_normal_mode')
def run(self, edit, **vi_cmd_data): self.debug("Data in ViRunCommand:", vi_cmd_data) try: if vi_cmd_data["restore_original_carets"]: self.save_caret_pos() # XXX: Fix this. When should we run the motion exactly? if vi_cmd_data["action"]: # If no motion is present, we know we just have to run the action (like ctrl+w, v). if (vi_cmd_data["motion"]) or ( vi_cmd_data["motion_required"] and not view.has_non_empty_selection_region() ): self.enter_visual_mode_if_needed(vi_cmd_data) self.do_whole_motion(vi_cmd_data) # The motion didn't change the selections: abort action if so required. # TODO: What to do with .post_action() and .do_follow_up_mode() in this event? if ( vi_cmd_data["mode"] == _MODE_INTERNAL_NORMAL and all([v.empty() for v in self.view.sel()]) and vi_cmd_data["cancel_action_if_motion_fails"] ): return self.do_action(vi_cmd_data) else: self.do_whole_motion(vi_cmd_data) finally: # XXX: post_action should be run only if do_action succeeds (?). self.do_post_action(vi_cmd_data) if vi_cmd_data["must_update_xpos"]: state = VintageState(self.view) first_sel = self.view.sel()[0] xpos = 0 if state.mode == MODE_VISUAL: if first_sel.a < first_sel.b: xpos = self.view.rowcol(first_sel.b - 1)[1] elif first_sel.a > first_sel.b: xpos = self.view.rowcol(first_sel.b)[1] elif state.mode == MODE_NORMAL: xpos = self.view.rowcol(first_sel.b)[1] state.xpos = xpos self.do_modify_selections(vi_cmd_data) self.do_follow_up_mode(vi_cmd_data) if vi_cmd_data["scroll_into_view"]: # TODO: If moving by lines, scroll the minimum amount to display the new sels. self.view.show(self.view.sel()[0]) state = VintageState(self.view) state.reset(next_mode=vi_cmd_data["next_mode"])
def run(self): state = VintageState(self.view) for i in range(state.count): self.view.run_command('redo') state.update_xpos() # Ensure that we wipe the count, if any. state.reset() self.view.run_command('vi_enter_normal_mode')
def run(self): state = VintageState(self.view) for i in range(state.count): self.view.run_command('redo') state.update_xpos() # Ensure that we wipe the count, if any. state.reset() self.view.run_command('vi_enter_normal_mode')
def on_done(s): state = VintageState(self.view) try: rv = [str(eval(s, None, None)),] if not insert: # TODO: We need to sort out the values received and sent to registers. When pasting, # we assume a list... This should be encapsulated in Registers. state.registers[REG_EXPRESSION] = rv else: self.view.run_command('insert_snippet', {'contents': str(rv[0])}) state.reset() except: sublime.status_message("Vintageous: Invalid expression.") on_cancel()
def run(self, edit): state = VintageState(self.view) # We've recorded what the user has typed into the buffer. Turn macro recording off. self.view.run_command('toggle_record_macro') for i in range(state.count - 1): self.view.run_command('run_macro') # Ensure the count will be deleted. state.mode = MODE_NORMAL # Delete the count now. state.reset() self.view.run_command('vi_enter_normal_mode_from_insert_mode')
def on_done(s): state = VintageState(self.view) try: rv = [str(eval(s, None, None)),] if not insert: # TODO: We need to sort out the values received and sent to registers. When pasting, # we assume a list... This should be encapsulated in Registers. state.registers[REG_EXPRESSION] = rv else: self.view.run_command('insert_snippet', {'contents': str(rv[0])}) state.reset() except: sublime.status_message("Vintageous: Invalid expression.") on_cancel()
def run(self, edit): state = VintageState(self.view) # We've recorded what the user has typed into the buffer. Turn macro recording off. self.view.run_command('glue_marked_undo_groups') # FIXME: We can't repeat 5ifoo<esc> after we're done. for i in range(state.count - 1): self.view.run_command('repeat') # Ensure the count will be deleted. state.mode = MODE_NORMAL # Delete the count now. state.reset() self.view.run_command('vi_enter_normal_mode_from_insert_mode')
def run(self, edit): state = VintageState(self.view) # We've recorded what the user has typed into the buffer. Turn macro recording off. self.view.run_command('glue_marked_undo_groups') # FIXME: We can't repeat 5ifoo<esc> after we're done. for i in range(state.count - 1): self.view.run_command('repeat') # Ensure the count will be deleted. state.mode = MODE_NORMAL # Delete the count now. state.reset() self.view.run_command('vi_enter_normal_mode_from_insert_mode')
def run(self, name=None): state = VintageState(self.view) if name == None and not state.is_recording: return if not state.is_recording: state._latest_macro_name = name state.is_recording = True self.view.run_command('start_record_macro') return if state.is_recording: self.view.run_command('stop_record_macro') state.is_recording = False state.reset() # Store the macro away. modifying_cmd = self.view.command_history(0, True) state.latest_macro = modifying_cmd
def run(self, name=None): state = VintageState(self.view) if name == None and not state.is_recording: return if not state.is_recording: self.view.run_command('unmark_undo_groups_for_gluing') state.latest_macro_name = name state.is_recording = True self.view.run_command('start_record_macro') return if state.is_recording: self.view.run_command('stop_record_macro') state.is_recording = False self.view.run_command('unmark_undo_groups_for_gluing') state.reset() # Store the macro away. state.macros[state.latest_macro_name] = sublime.get_macro()
def run(self, name=None): state = VintageState(self.view) if name == None and not state.is_recording: return if not state.is_recording: self.view.run_command('unmark_undo_groups_for_gluing') state.latest_macro_name = name state.is_recording = True self.view.run_command('start_record_macro') return if state.is_recording: self.view.run_command('stop_record_macro') state.is_recording = False self.view.run_command('unmark_undo_groups_for_gluing') state.reset() # Store the macro away. state.macros[state.latest_macro_name] = sublime.get_macro()
def run(self): state = VintageState(self.view) try: cmd, args, _ = state.repeat_command except TypeError: # Unreachable. return # Signal that we're not simply issuing an interactive command, but rather repeating one. # This is necessary, for example, to notify _vi_k that it should become _vi_j instead # if the former was run in visual mode. state.settings.vi['_is_repeating'] = True if not cmd: return elif cmd == 'vi_run': args['next_mode'] = MODE_NORMAL args['follow_up_mode'] = 'vi_enter_normal_mode' args['count'] = state.count * args['count'] self.view.run_command(cmd, args) elif cmd == 'sequence': for i, _ in enumerate(args['commands']): # We can have either 'vi_run' commands or plain insert mode commands. if args['commands'][i][0] == 'vi_run': # Access this shape: {"commands":[['vi_run', {"foo": 100}],...]} args['commands'][i][1]['next_mode'] = MODE_NORMAL args['commands'][i][1][ 'follow_up_mode'] = 'vi_enter_normal_mode' # TODO: Implement counts properly for 'sequence' command. for i in range(state.count): self.view.run_command(cmd, args) # Ensure we wipe count data if any. state.reset() # XXX: Needed here? Maybe enter_... type commands should be IrreversibleTextCommands so we # must/can call them whenever we need them withouth affecting the undo stack. self.view.run_command('vi_enter_normal_mode') state.settings.vi['_is_repeating'] = False
def run(self): state = VintageState(self.view) try: cmd, args, _ = state.repeat_command except TypeError: # Unreachable. return # Signal that we're not simply issuing an interactive command, but rather repeating one. # This is necessary, for example, to notify _vi_k that it should become _vi_j instead # if the former was run in visual mode. state.settings.vi['_is_repeating'] = True if not cmd: return elif cmd == 'vi_run': args['next_mode'] = MODE_NORMAL args['follow_up_mode'] = 'vi_enter_normal_mode' args['count'] = state.count * args['count'] self.view.run_command(cmd, args) elif cmd == 'sequence': for i, _ in enumerate(args['commands']): # We can have either 'vi_run' commands or plain insert mode commands. if args['commands'][i][0] == 'vi_run': # Access this shape: {"commands":[['vi_run', {"foo": 100}],...]} args['commands'][i][1]['next_mode'] = MODE_NORMAL args['commands'][i][1]['follow_up_mode'] = 'vi_enter_normal_mode' # TODO: Implement counts properly for 'sequence' command. for i in range(state.count): self.view.run_command(cmd, args) # Ensure we wipe count data if any. state.reset() # XXX: Needed here? Maybe enter_... type commands should be IrreversibleTextCommands so we # must/can call them whenever we need them withouth affecting the undo stack. self.view.run_command('vi_enter_normal_mode') state.settings.vi['_is_repeating'] = False
def run(self, edit): state = VintageState(self.view) state.enter_replace_mode() # XXX: Shouldn't this be done from within VintageState? self.view.run_command('collapse_to_direction') state.reset()
def on_cancel(): state = VintageState(self.view) state.reset(next_mode=MODE_INSERT)
def on_cancel(): state = VintageState(self.view) state.reset()
def run(self, edit): state = VintageState(self.view) state.enter_replace_mode() self.view.run_command('collapse_to_direction') state.reset()
def run(self, edit): state = VintageState(self.view) self.view.run_command('collapse_to_direction') self.view.run_command('dont_stay_on_eol_backward') state.reset() state.enter_normal_mode()
class Test_reset(unittest.TestCase): def setUp(self): TestsState.view.settings().erase('vintage') TestsState.view.window().settings().erase('vintage') self.state = VintageState(TestsState.view) def testResetsData(self): self.state.action = 'action' self.state.motion = 'motion' self.state.register = 'register' self.state.user_input = 'user_input' self.state.expecting_register = 'expecting_register' self.state.expecting_user_input = 'expecting_user_input' self.state.cancel_action = 'cancel_action' self.state.mode = 'mode' self.state.next_mode = 'next_mode' self.state.next_mode_command = 'next_mode_command' self.state.reset() self.assertEqual(self.state.action, None) self.assertEqual(self.state.motion, None) self.assertEqual(self.state.register, None) self.assertEqual(self.state.user_input, None) self.assertEqual(self.state.expecting_register, False) self.assertEqual(self.state.expecting_user_input, False) self.assertEqual(self.state.cancel_action, False) self.assertEqual(self.state.mode, 'mode') self.assertEqual(self.state.next_mode, MODE_NORMAL) self.assertEqual(self.state.next_mode_command, None) def testCallsCorrectModeChangeMethod(self): self.state.next_mode = MODE_INSERT self.state.next_mode_command = 'foo' # XXX Check the code. Do we actually need to call this method at this point? with mock.patch.object(self.state.view, 'run_command') as rc: self.state.reset() rc.assert_called_once_with('foo') self.state.reset() self.state.next_mode = MODE_NORMAL self.state.next_mode_command = 'bar' with mock.patch.object(self.state.view, 'run_command') as m: self.state.reset() m.assert_called_once_with('bar') def testDoesNotCallAnyModeChangeCommandForOtherModes(self): self.state.next_mode = MODE_VISUAL_LINE self.state.next_mode_command = 'foo' with mock.patch.object(self.state.view, 'run_command') as rc: self.state.reset() self.assertEqual(rc.call_count, 0) def testDoesNotCallAnyModeChangeCommandIfNotSpecified(self): self.state.next_mode = MODE_NORMAL with mock.patch.object(self.state.view, 'run_command') as rc: self.state.reset() self.assertEqual(rc.call_count, 0) self.state.next_mode = MODE_VISUAL with mock.patch.object(self.state.view, 'run_command') as rc: self.state.reset() self.assertEqual(rc.call_count, 0) def testUpdatesRepeatCommandIfThereWasAnAction(self): self.state.action = 'foo' with mock.patch.object(self.state, 'update_repeat_command') as m: self.state.reset() self.assertEqual(m.call_count, 1) def testDoesNotUpdateRepeatCommandIfThereWasNoAction(self): with mock.patch.object(self.state, 'update_repeat_command') as m: self.state.reset() self.assertEqual(m.call_count, 0)
def on_cancel(): state = VintageState(self.view) state.reset()
def run(self, edit): state = VintageState(self.view) state.enter_replace_mode() self.view.run_command('collapse_to_direction') state.reset()