예제 #1
0
    def on_done(self, idx):
        """Save selected value to `"` register."""
        if idx == -1:
            return

        state = State(self.view)
        value = list(state.registers.to_dict().values())[idx]
        state.registers['"'] = value
예제 #2
0
 def setUp(self):
     super().setUp()
     sublime.set_clipboard('')
     registers._REGISTER_DATA = {}
     self.view.settings().erase('vintage')
     self.view.settings().erase('vintageous_use_sys_clipboard')
     self.regs = State(self.view).registers
     self.regs.view = mock.Mock()
예제 #3
0
    def on_done(self, idx):
        """Save selected value to `"` register."""
        if idx == -1:
            return

        state = State(self.view)
        value = list(state.registers.to_dict().values())[idx]
        state.registers['"'] = value
예제 #4
0
 def run(self, key=None):
     state = State(self.window.active_view())
     state.motion = cmd_defs[state.mode][cmds.QUESTION_MARK_IMPL]
     state.last_buffer_search = state.user_input or state.last_buffer_search
     # XXX: Is this right?
     if state.input_parsers:
         new_parsers = state.input_parsers
         new_parsers.pop()
         state.input_parsers = new_parsers
예제 #5
0
 def setUp(self):
     super().setUp()
     sublime.set_clipboard('')
     registers._REGISTER_DATA = {}
     self.view.settings().erase('vintage')
     self.view.settings().erase('vintageous_use_sys_clipboard')
     # self.regs = Registers(view=self.view,
     # settings=SettingsManager(view=self.view))
     self.regs = State(self.view).registers
예제 #6
0
 def run(self, key=None):
     state = State(self.window.active_view())
     state.motion = cmd_defs[state.mode][cmds.QUESTION_MARK_IMPL]
     state.last_buffer_search = state.user_input or state.last_buffer_search
     # XXX: Is this right?
     if state.input_parsers:
         new_parsers = state.input_parsers
         new_parsers.pop()
         state.input_parsers = new_parsers
예제 #7
0
    def run(self, edit, line_range, register=None, count=None):
        if not register:
            register = '"'

        regs = get_region_by_range(self.view, line_range)
        text = '\n'.join([self.view.substr(line) for line in regs]) + '\n'

        state = State(self.view)
        state.registers[register] = [text]
        if register == '"':
            state.registers['0'] = [text]
예제 #8
0
    def run(self, edit, line_range, register=None, count=None):
        if not register:
            register = '"'

        regs = get_region_by_range(self.view, line_range)
        text = '\n'.join([self.view.substr(line) for line in regs]) + '\n'

        state = State(self.view)
        state.registers[register] = [text]
        if register == '"':
            state.registers['0'] = [text]
예제 #9
0
    def testFromVisualModeToNormalMode(self):
        self.write('abc\nxxx\nabc\nabc')
        self.clear_sel()
        self.add_sel(self.R((1, 0), (1, 1)))

        state = State(self.view)
        state.enter_visual_mode()
        prev_mode = state.mode

        self.view.run_command('ex_move', {'command_line': 'move3'})

        state = State(self.view)
        new_mode = state.mode
        self.assertNotEqual(prev_mode, new_mode)
예제 #10
0
    def testFromVisualModeToNormalMode(self):
        self.write('abc\nxxx\nabc\nabc')
        self.clear_sel()
        self.add_sel(self.R((1, 0), (1, 1)))

        state = State(self.view)
        state.enter_visual_mode()
        prev_mode = state.mode

        self.view.run_command('ex_copy', {'address': '3'})

        state = State(self.view)
        new_mode = state.mode
        self.assertNotEqual(prev_mode, new_mode)
        self.assertEqual(new_mode, modes.NORMAL)
예제 #11
0
    def select(self, regions, register):
        self.view.sel().clear()
        to_store = []
        for r in regions:
            self.view.sel().add(r)
            if register:
                to_store.append(self.view.substr(self.view.full_line(r)))

        if register:
            text = ''.join(to_store)
            if not text.endswith('\n'):
                text = text + '\n'

            state = State(self.view)
            state.registers[register] = [text]
예제 #12
0
    def select(self, regions, register):
        self.view.sel().clear()
        to_store = []
        for r in regions:
            self.view.sel().add(r)
            if register:
                to_store.append(self.view.substr(self.view.full_line(r)))

        if register:
            text = ''.join(to_store)
            if not text.endswith('\n'):
                text = text + '\n'

            state = State(self.view)
            state.registers[register] = [text]
    def testCaretEndsInExpectedRegion(self):
        self.write(''.join(('foo bar\nfoo bar\nfoo bar\n',)))
        self.clear_sel()
        self.add_sel(self.R((1, 3), (1, 0)))

        state = State(self.view)
        state.enter_visual_mode()

        # TODO: we should bypass vi_r and define the values directly.
        data = CmdData(state)
        # data = vi_r(data)
        data['action']['args']['character'] = 'X'

        self.view.run_command('vi_run', data)

        self.assertEqual(self.R((1, 0), (1, 0)), first_sel(self.view))
예제 #14
0
    def testFromNormalModeToNormalMode(self):
        self.write('abc\nxxx\nabc\nabc')
        self.clear_sel()
        self.add_sel(self.R((1, 0), (1, 0)))

        state = State(self.view)
        state.enter_normal_mode()

        self.view.run_command('vi_enter_normal_mode')
        prev_mode = state.mode

        self.view.run_command('ex_move', {'address': '3'})

        state = State(self.view)
        new_mode = state.mode
        self.assertEqual(prev_mode, new_mode)
    def testCaretEndsInExpectedRegion(self):
        self.write("".join(("foo bar\nfoo bar\nfoo bar\n",)))
        self.clear_sel()
        self.add_sel(self.R((1, 3), (1, 0)))

        state = State(self.view)
        state.enter_visual_mode()

        # TODO: we should bypass vi_r and define the values directly.
        data = CmdData(state)
        # data = vi_r(data)
        data["action"]["args"]["character"] = "X"

        self.view.run_command("vi_run", data)

        self.assertEqual(self.R((1, 0), (1, 0)), first_sel(self.view))
예제 #16
0
파일: nodes.py 프로젝트: pizchen/Vintageous
    def resolve_mark(self, view, token):
        if token.content == '<':
            sel = list(view.sel())[0]
            view.sel().clear()
            view.sel().add(sel)
            if sel.a < sel.b:
                return row_at(view, sel.a)
            else:
                return row_at(view, sel.a - 1)

        if token.content == '>':
            sel = list(view.sel())[0]
            view.sel().clear()
            view.sel().add(sel)
            if sel.a < sel.b:
                return row_at(view, sel.b - 1)
            else:
                return row_at(view, sel.b)

        st = State(view)
        rg = st.marks.get_as_encoded_address(token.content)

        if (isinstance(rg, sublime.Region)):
            return view.rowcol(rg.begin())[0]

        raise NotImplementedError()
예제 #17
0
    def run(self, path=None, forced=False):
        if self.view.is_dirty() and not forced:
            ex_error.display_error(ex_error.ERR_UNSAVED_CHANGES)
            return

        state = State(self.view)

        if not path:
            state.settings.vi['_cmdline_cd'] = os.path.expanduser("~")
            self.view.run_command('ex_print_working_dir')
            return

        # TODO: It seems there a few symbols that are always substituted when they represent a
        # filename. We should have a global method of substiting them.
        if path == '%:h':
            fname = self.view.file_name()
            if fname:
                state.settings.vi['_cmdline_cd'] = os.path.dirname(fname)
                self.view.run_command('ex_print_working_dir')
            return

        path = os.path.realpath(os.path.expandvars(os.path.expanduser(path)))
        if not os.path.exists(path):
            # TODO: Add error number in ex_error.py.
            ex_error.display_error(ex_error.ERR_CANT_FIND_DIR_IN_CDPATH)
            return

        state.settings.vi['_cmdline_cd'] = path
        self.view.run_command('ex_print_working_dir')
예제 #18
0
    def inner(*args, **kwargs):
        try:
            state = State(args[0].view)
        except AttributeError:
            state = State(args[0].window.active_view())

        old = os.getcwd()
        try:
            # FIXME: Under some circumstances, like when switching projects to
            # a file whose _cmdline_cd has not been set, _cmdline_cd might
            # return 'None'. In such cases, change to the actual current
            # directory as a last measure. (We should probably fix this anyway).
            os.chdir(state.settings.vi['_cmdline_cd'] or old)
            f(*args, **kwargs)
        finally:
            os.chdir(old)
예제 #19
0
    def testCaretEndsInExpectedRegion(self):
        self.write(''.join(('foo bar\nfoo bar\nfoo bar\n', )))
        self.clear_sel()
        self.add_sel(self.R((1, 3), (1, 0)))

        state = State(self.view)
        state.enter_visual_mode()

        # TODO: we should bypass vi_r and define the values directly.
        data = CmdData(state)
        # data = vi_r(data)
        data['action']['args']['character'] = 'X'

        self.view.run_command('vi_run', data)

        self.assertEqual(self.R((1, 0), (1, 0)), first_sel(self.view))
예제 #20
0
 def run(self, edit, line_range=None):
     if not line_range['text_range']:
         # No-op: user issued ":".
         return
     ranges, _ = ex_range.new_calculate_range(self.view, line_range)
     a, b = ranges[0]
     # FIXME: This should be handled by the parser.
     # FIXME: In Vim, 0 seems to equal 1 in ranges.
     b = b if line_range['text_range'] != '0' else 1
     state = State(self.view)
     # FIXME: In Visual mode, goto line does some weird stuff.
     if state.mode == MODE_NORMAL:
         # TODO: push all this code down to ViGoToLine?
         self.view.window().run_command('_vi_add_to_jump_list')
         self.view.run_command('_vi_go_to_line', {
             'line': b,
             'mode': state.mode
         })
         self.view.window().run_command('_vi_add_to_jump_list')
         self.view.show(self.view.sel()[0])
     elif state.mode in (MODE_VISUAL,
                         MODE_VISUAL_LINE) and line_range['right_offset']:
         # TODO: push all this code down to ViGoToLine?
         self.view.window().run_command('_vi_add_to_jump_list')
         # FIXME: The parser fails with '<,'>100. 100 is not the right_offset, but an argument.
         b = self.view.rowcol(self.view.sel()[0].b -
                              1)[0] + line_range['right_offset'] + 1
         self.view.run_command('_vi_go_to_line', {
             'line': b,
             'mode': state.mode
         })
         self.view.window().run_command('_vi_add_to_jump_list')
         self.view.show(self.view.sel()[0])
예제 #21
0
    def on_text_command(self, view, command, args):
        if command == 'drag_select':
            state = State(view)

            if state.mode in (modes.VISUAL, modes.VISUAL_LINE,
                              modes.VISUAL_BLOCK):
                if (args.get('extend') or (args.get('by') == 'words')
                        or args.get('additive')):
                    return

                elif not args.get('extend'):
                    return ('sequence', {
                        'commands':
                        [['drag_select', args],
                         ['_enter_normal_mode', {
                             'mode': state.mode
                         }]]
                    })

            elif state.mode == modes.NORMAL:
                # TODO(guillermooo): Dragging the mouse does not seem to
                # fire a different event than simply clicking. This makes it
                # hard to update the xpos.
                if args.get('extend') or (args.get('by') == 'words'):
                    return ('sequence', {
                        'commands':
                        [['drag_select', args],
                         ['_enter_visual_mode', {
                             'mode': state.mode
                         }]]
                    })
 def setUp(self):
     super().setUp()
     sublime.set_clipboard('')
     registers._REGISTER_DATA = {}
     self.view.settings().erase('vintage')
     self.view.settings().erase('vintageous_use_sys_clipboard')
     self.regs = State(self.view).registers
     self.regs.view = mock.Mock()
예제 #23
0
 def run(self, edit, mode=None, count=None, cmd=''):
     mappings = Mappings(State(self.view))
     try:
         mappings.remove(modes.VISUAL, cmd)
         mappings.remove(modes.VISUAL_LINE, cmd)
         mappings.remove(modes.VISUAL_BLOCK, cmd)
     except KeyError:
         sublime.status_message('Vintageous: Mapping  not found.')
예제 #24
0
    def testCaretEndsInExpectedRegion(self):
        self.write('foo bar\nfoo bar\nfoo bar\n')
        self.clear_sel()
        self.add_sel(self.R((1, 0), (1, 3)))

        State(self.view).mode = MODE_VISUAL

        self.view.run_command('_enter_normal_mode', {'mode': MODE_VISUAL})
        self.assertEqual(self.R((1, 2), (1, 2)), first_sel(self.view))
 def setUp(self):
     super().setUp()
     sublime.set_clipboard('')
     registers._REGISTER_DATA = {}
     self.view.settings().erase('vintage')
     self.view.settings().erase('vintageous_use_sys_clipboard')
     # self.regs = Registers(view=self.view,
                           # settings=SettingsManager(view=self.view))
     self.regs = State(self.view).registers
예제 #26
0
 def run(self, forced=False):
     if self.view.is_dirty() and not forced:
         ex_error.display_error(ex_error.ERR_UNSAVED_CHANGES)
         return
     path = os.path.dirname(self.view.file_name())
     state = State(self.view)
     try:
         state.settings.vi['_cmdline_cd'] = path
         self.view.run_command('ex_print_working_dir')
     except IOError:
         ex_error.display_error(ex_error.ERR_CANT_FIND_DIR_IN_CDPATH)
예제 #27
0
 def run(self, edit, mode=None, count=None, cmd=''):
     try:
         keys, command = cmd.lstrip().split(' ', 1)
     except ValueError:
         sublime.status_message('Vintageous: Bad mapping format')
         return
     else:
         mappings = Mappings(State(self.view))
         mappings.add(modes.NORMAL, keys, command)
         mappings.add(modes.OPERATOR_PENDING, keys, command)
         mappings.add(modes.VISUAL, keys, command)
예제 #28
0
    def run(self, initial_text=':', cmd_line=''):
        # non-interactive call
        if cmd_line:
            self.non_interactive = True
            self.on_done(cmd_line)
            return

        FsCompletion.invalidate()

        state = State(self.window.active_view())
        if state.mode in (modes.VISUAL, modes.VISUAL_LINE):
            initial_text = ":'<,'>" + initial_text[1:]

        v = mark_as_widget(show_ipanel(self.window,
                                       initial_text=initial_text,
                                       on_done=self.on_done,
                                       on_change=self.on_change))
        v.set_syntax_file('Packages/Vintageous/VintageousEx Cmdline.tmLanguage')
        v.settings().set('gutter', False)
        v.settings().set('rulers', [])

        state.reset_during_init = False
예제 #29
0
 def run(self, edit, mode=None, count=None, cmd=''):
     try:
         # TODO(guillermooo): Instead of parsing this here, add parsers
         # to ex command defs and reuse them here.
         keys, command = cmd.lstrip().split(' ', 1)
     except ValueError:
         sublime.status_message('Vintageous: Bad mapping format')
         return
     else:
         mappings = Mappings(State(self.view))
         mappings.add(modes.NORMAL, keys, command)
         mappings.add(modes.OPERATOR_PENDING, keys, command)
         mappings.add(modes.VISUAL, keys, command)
예제 #30
0
    def run(self, edit):
        if self.view.score_selector(0, 'text.excmdline') == 0:
            return

        state = State(self.view)
        FsCompletion.frozen_dir = (FsCompletion.frozen_dir
                                   or (state.settings.vi['_cmdline_cd'] + '/'))

        cmd, prefix, only_dirs = parse(self.view.substr(self.view.line(0)))
        if not cmd:
            return

        if not (FsCompletion.prefix or FsCompletion.items) and prefix:
            FsCompletion.prefix = prefix
            FsCompletion.is_stale = True

        if prefix == '..':
            FsCompletion.prefix = '../'
            self.view.run_command('write_fs_completion', {
                'cmd': cmd,
                'completion': '../'
            })

        if prefix == '~':
            path = os.path.expanduser(prefix) + '/'
            FsCompletion.prefix = path
            self.view.run_command('write_fs_completion', {
                'cmd': cmd,
                'completion': path
            })
            return

        if (not FsCompletion.items) or FsCompletion.is_stale:
            FsCompletion.items = iter_paths(from_dir=FsCompletion.frozen_dir,
                                            prefix=FsCompletion.prefix,
                                            only_dirs=only_dirs)
            FsCompletion.is_stale = False

        try:
            self.view.run_command('write_fs_completion', {
                'cmd': cmd,
                'completion': next(FsCompletion.items)
            })
        except StopIteration:
            FsCompletion.items = iter_paths(prefix=FsCompletion.prefix,
                                            from_dir=FsCompletion.frozen_dir,
                                            only_dirs=only_dirs)
            self.view.run_command('write_fs_completion', {
                'cmd': cmd,
                'completion': FsCompletion.prefix
            })
예제 #31
0
    def run(self, initial_text=':', cmd_line=''):
        if cmd_line:
            # The caller has provided a command, to we're not in interactive
            # mode -- just run the command.
            ViColonInput.interactive_call = False
            self.on_done(cmd_line)
            return
        else:
            ViColonInput.interactive_call = True

        FsCompletion.invalidate()

        v = mark_as_widget(show_ipanel(self.window,
               initial_text=self.adjust_initial_text(initial_text),
               on_done=self.on_done,
               on_change=self.on_change))

        v.set_syntax_file('Packages/Vintageous/VintageousEx Cmdline.tmLanguage')
        v.settings().set('gutter', False)
        v.settings().set('rulers', [])

        state = State(self.window.active_view())
        state.reset_during_init = False
예제 #32
0
    def run(self, initial_text=':', cmd_line=''):
        if cmd_line:
            # The caller has provided a command, to we're not in interactive
            # mode -- just run the command.
            ViColonInput.interactive_call = False
            self.on_done(cmd_line)
            return
        else:
            ViColonInput.interactive_call = True

        FsCompletion.invalidate()

        v = mark_as_widget(show_ipanel(self.window,
               initial_text=self.adjust_initial_text(initial_text),
               on_done=self.on_done,
               on_change=self.on_change))

        v.set_syntax_file('Packages/Vintageous/VintageousEx Cmdline.tmLanguage')
        v.settings().set('gutter', False)
        v.settings().set('rulers', [])

        state = State(self.window.active_view())
        state.reset_during_init = False
예제 #33
0
    def run(self, initial_text=':', cmd_line=''):
        # non-interactive call
        if cmd_line:
            self.non_interactive = True
            self.on_done(cmd_line)
            return

        FsCompletion.invalidate()

        state = State(self.window.active_view())
        if state.mode in (modes.VISUAL, modes.VISUAL_LINE):
            initial_text = ":'<,'>" + initial_text[1:]

        v = mark_as_widget(
            show_ipanel(self.window,
                        initial_text=initial_text,
                        on_done=self.on_done,
                        on_change=self.on_change))
        v.set_syntax_file(
            'Packages/Vintageous/VintageousEx Cmdline.tmLanguage')
        v.settings().set('gutter', False)
        v.settings().set('rulers', [])

        state.reset_during_init = False
예제 #34
0
    def run(self, edit):
        def show_lines(line_count):
            lines_display = '... [+{0}]'.format(line_count - 1)
            return lines_display if line_count > 1 else ''

        state = State(self.view)
        pairs = [(k, v) for (k, v) in state.registers.to_dict().items() if v]
        pairs = [(k, repr(v[0]), len(v)) for (k, v) in pairs]
        pairs = [
            '"{0}  {1}  {2}'.format(k, v, show_lines(lines))
            for (k, v, lines) in pairs
        ]

        self.view.window().show_quick_panel(pairs,
                                            self.on_done,
                                            flags=sublime.MONOSPACE_FONT)
예제 #35
0
    def run(self, forced=False, file_name=None):
        if file_name:
            file_name = os.path.expanduser(os.path.expandvars(file_name))
            if self.view.is_dirty() and not forced:
                ex_error.display_error(ex_error.ERR_UNSAVED_CHANGES)
                return
            file_name = os.path.expanduser(file_name)
            if os.path.isdir(file_name):
                sublime.status_message(
                    'Vintageous: "{0}" is a directory'.format(file_name))
                return

            message = ''

            if not os.path.isabs(file_name):
                file_name = os.path.join(
                    State(self.view).settings.vi['_cmdline_cd'], file_name)

            if not os.path.exists(file_name):
                message = '[New File]'
                path = os.path.dirname(file_name)
                if path and not os.path.exists(path):
                    message = '[New DIRECTORY]'
                self.view.window().open_file(file_name)

                # TODO: Collect message and show at the end of the command.
                def show_message():
                    sublime.status_message('Vintageous: "{0}" {1}'.format(
                        (file_name, message)))

                sublime.set_timeout(show_message, 250)
                return
        else:
            if forced or not self.view.is_dirty():
                self.view.run_command('revert')
                return
            elif not file_name and self.view.is_dirty():
                ex_error.display_error(ex_error.ERR_UNSAVED_CHANGES)
                return

        if forced or not self.view.is_dirty():
            self.view.window().open_file(file_name)
            return
        ex_error.display_error(ex_error.ERR_UNSAVED_CHANGES)
예제 #36
0
    def testFromVisualModeToNormalMode(self):
        self.write('abc\nxxx\nabc\nabc')
        self.clear_sel()
        self.add_sel(self.R((1, 0), (1, 1)))

        state = State(self.view)
        state.enter_visual_mode()
        prev_mode = state.mode

        self.view.run_command('ex_move', {'address': '3'})

        state = State(self.view)
        new_mode = state.mode
        self.assertNotEqual(prev_mode, new_mode)
예제 #37
0
    def testFromVisualModeToNormalMode(self):
        self.write('abc\nxxx\nabc\nabc')
        self.clear_sel()
        self.add_sel(self.R((1, 0), (1, 1)))

        state = State(self.view)
        state.enter_visual_mode()
        prev_mode = state.mode

        self.view.run_command('ex_copy', {'command_line': 'copy3'})

        state = State(self.view)
        new_mode = state.mode
        self.assertNotEqual(prev_mode, new_mode)
        self.assertEqual(new_mode, modes.NORMAL)
예제 #38
0
    def testFromNormalModeToNormalMode(self):
        self.write('abc\nxxx\nabc\nabc')
        self.clear_sel()
        self.add_sel(self.R((1, 0), (1, 0)))

        state = State(self.view)
        state.enter_normal_mode()

        self.view.run_command('vi_enter_normal_mode')
        prev_mode = state.mode

        self.view.run_command('ex_copy', {'address': '3'})

        state = State(self.view)
        new_mode = state.mode
        self.assertEqual(prev_mode, new_mode, modes.NORMAL)
예제 #39
0
    def testFromNormalModeToNormalMode(self):
        self.write('abc\nxxx\nabc\nabc')
        self.clear_sel()
        self.add_sel(self.R((1, 0), (1, 0)))

        state = State(self.view)
        state.enter_normal_mode()

        self.view.run_command('vi_enter_normal_mode')
        prev_mode = state.mode

        self.range['left_offset'] = 2
        self.range['text_range'] = '2'
        self.view.run_command('ex_delete', {'line_range': self.range})

        state = State(self.view)
        new_mode = state.mode
        self.assertEqual(prev_mode, new_mode)
예제 #40
0
    def testFromVisualModeToNormalMode(self):
        self.write('abc\nxxx\nabc\nabc')
        self.clear_sel()
        self.add_sel(self.R((1, 0), (1, 1)))

        state = State(self.view)
        state.enter_visual_mode()
        prev_mode = state.mode

        self.range['left_ref'] = "'<"
        self.range['right_ref'] = "'>"
        self.range['text_range'] = "'<,'>"
        self.view.run_command('ex_delete', {'line_range': self.range})

        state = State(self.view)
        new_mode = state.mode
        self.assertNotEqual(prev_mode, new_mode)
        self.assertEqual(new_mode, MODE_NORMAL)
예제 #41
0
    def run(self,
            line_range=None,
            forced=False,
            file_name='',
            plusplus_args='',
            operator='',
            target_redirect='',
            subcmd=''):

        if file_name and target_redirect:
            sublime.status_message('Vintageous: Too many arguments.')
            return

        appending = operator == '>>'
        a_range = line_range['text_range']
        self.view = self.window.active_view()
        content = get_region_by_range(self.view, line_range=line_range) if a_range else \
                        [sublime.Region(0, self.view.size())]

        read_only = False
        if self.view.file_name():
            mode = os.stat(self.view.file_name())
            read_only = (stat.S_IMODE(mode.st_mode) & stat.S_IWUSR !=
                                                                stat.S_IWUSR)

        if target_redirect:
            target = self.window.new_file()
            target.set_name(target_redirect)
        elif file_name:

            def report_error(msg):
                sublime.status_message('Vintageous: %s' % msg)

            file_path = os.path.abspath(os.path.expanduser(file_name))

            if os.path.exists(file_path) and (file_path != self.view.file_name()):
                # TODO add w! flag
                # TODO: Hook this up with ex error handling (ex/errors.py).
                msg = "File '{0}' already exists.".format(file_path)
                report_error(msg)
                return

            if not os.path.exists(os.path.dirname(file_path)):
                msg = "Directory '{0}' does not exist.".format(os.path.dirname(file_path))
                report_error(msg)
                return

            try:
                # FIXME: We need to do some work with encodings here, don't we?
                with open(file_path, 'w+') as temp_file:
                    for frag in reversed(content):
                        temp_file.write(self.view.substr(frag))
                    temp_file.close()
                    sublime.status_message("Vintageous: Saved {0}".format(file_path))

                    row, col = self.view.rowcol(self.view.sel()[0].b)
                    encoded_fn = "{0}:{1}:{2}".format(file_path, row + 1, col + 1)
                    self.view.set_scratch(True)
                    w = self.window
                    w.run_command('close')
                    w.open_file(encoded_fn, sublime.ENCODED_POSITION)
                    return
            except IOError as e:
                report_error( "Failed to create file '%s'." % file_name )
                return

            window = self.window
            window.open_file(file_path)
            return
        else:
            target = self.view

            if (read_only or self.view.is_read_only()) and not forced:
                utils.blink()
                sublime.status_message("Vintageous: Can't write read-only file.")
                return

        start = 0 if not appending else target.size()
        prefix = '\n' if appending and target.size() > 0 else ''

        if appending or target_redirect:
            for frag in reversed(content):
                target.run_command('append', {'characters': prefix + self.view.substr(frag) + '\n'})
        elif a_range:
            start_deleting = 0
            text = ''
            for frag in content:
                text += self.view.substr(frag) + '\n'
            start_deleting = len(text)
            self.view.run_command('ex_replace_file', {'start': 0, 'end': 0, 'with_what': text})
        else:
            dirname = os.path.dirname(self.view.file_name())
            if not os.path.exists(dirname):
                os.makedirs(dirname)
            self.window.run_command('save')

        # This may unluckily prevent the user from seeing ST's feedback about saving the current
        # file.
        state = State(self.window.active_view())
        if state.mode != MODE_NORMAL:
            state.enter_normal_mode()
            self.window.run_command('vi_enter_normal_mode')
예제 #42
0
 def state(self):
     return State(self.view)
class TestCaseRegisters(ViewTest):
    def setUp(self):
        super().setUp()
        sublime.set_clipboard('')
        registers._REGISTER_DATA = {}
        self.view.settings().erase('vintage')
        self.view.settings().erase('vintageous_use_sys_clipboard')
        # self.regs = Registers(view=self.view,
                              # settings=SettingsManager(view=self.view))
        self.regs = State(self.view).registers

    def testCanInitializeClass(self):
        self.assertEqual(self.regs.view, self.view)
        self.assertTrue(getattr(self.regs, 'settings'))

    def testCanSetUnanmedRegister(self):
        self.regs._set_default_register(["foo"])
        self.assertEqual(registers._REGISTER_DATA[registers.REG_UNNAMED],
                         ["foo"])

    def testSettingLongRegisterNameThrowsAssertionError(self):
        self.assertRaises(AssertionError, self.regs.set, "aa", "foo")

    def testSettingNonListValueThrowsAssertionError(self):
        self.assertRaises(AssertionError, self.regs.set, "a", "foo")

    @unittest.skip("Not implemented.")
    def testUnknownRegisterNameThrowsException(self):
        # XXX Doesn't pass at the moment.
        self.assertRaises(Exception, self.regs.set, "~", "foo")

    def testRegisterDataIsAlwaysStoredAsString(self):
        self.regs.set('"', [100])
        self.assertEqual(registers._REGISTER_DATA[registers.REG_UNNAMED],
                         ["100"])

    def testSettingBlackHoleRegisterDoesNothing(self):
        registers._REGISTER_DATA[registers.REG_UNNAMED] = ["bar"]
        # In this case it doesn't matter whether we're setting a list or not,
        # because we are discarding the value anyway.
        self.regs.set(registers.REG_BLACK_HOLE, "foo")
        self.assertTrue(registers.REG_BLACK_HOLE not in registers._REGISTER_DATA)
        self.assertTrue(registers._REGISTER_DATA[registers.REG_UNNAMED], ["bar"])

    def testSettingExpressionRegisterDoesntPopulateUnnamedRegister(self):
        self.regs.set("=", [100])
        self.assertTrue(registers.REG_UNNAMED not in registers._REGISTER_DATA)
        self.assertEqual(registers._REGISTER_DATA[registers.REG_EXPRESSION],
                        ["100"])

    def testCanSetNormalRegisters(self):
        for name in registers.REG_VALID_NAMES:
            self.regs.set(name, [name])

        for number in registers.REG_VALID_NUMBERS:
            self.regs.set(number, [number])

        for name in registers.REG_VALID_NAMES:
            self.assertEqual(registers._REGISTER_DATA[name], [name])

        for number in registers.REG_VALID_NUMBERS:
            self.assertEqual(registers._REGISTER_DATA[number], [number])

    def testSettingNormalRegisterSetsUnnamedRegisterToo(self):
        self.regs.set('a', [100])
        self.assertEqual(registers._REGISTER_DATA[registers.REG_UNNAMED], ['100'])

        self.regs.set('0', [200])
        self.assertEqual(registers._REGISTER_DATA[registers.REG_UNNAMED], ['200'])

    def testSettingRegisterSetsClipboardIfNeeded(self):
        self.regs.settings.view['vintageous_use_sys_clipboard'] = True
        self.regs.set('a', [100])
        self.assertEqual(sublime.get_clipboard(), '100')

    def testCanAppendToSingleValue(self):
        self.regs.set('a', ['foo'])
        self.regs.append_to('A', ['bar'])
        self.assertEqual(registers._REGISTER_DATA['a'], ['foobar'])

    def testCanAppendToMultipleBalancedValues(self):
        self.regs.set('a', ['foo', 'bar'])
        self.regs.append_to('A', ['fizz', 'buzz'])
        self.assertEqual(registers._REGISTER_DATA['a'], ['foofizz', 'barbuzz'])

    def testCanAppendToMultipleValuesMoreExistingValues(self):
        self.regs.set('a', ['foo', 'bar'])
        self.regs.append_to('A', ['fizz'])
        self.assertEqual(registers._REGISTER_DATA['a'], ['foofizz', 'bar'])

    def testCanAppendToMultipleValuesMoreNewValues(self):
        self.regs.set('a', ['foo'])
        self.regs.append_to('A', ['fizz', 'buzz'])
        self.assertEqual(registers._REGISTER_DATA['a'], ['foofizz', 'buzz'])

    def testAppendingSetsDefaultRegister(self):
        self.regs.set('a', ['foo'])
        self.regs.append_to('A', ['bar'])
        self.assertEqual(registers._REGISTER_DATA[registers.REG_UNNAMED],
                         ['foobar'])

    def testAppendSetsClipboardIfNeeded(self):
        self.regs.settings.view['vintageous_use_sys_clipboard'] = True
        self.regs.set('a', ['foo'])
        self.regs.append_to('A', ['bar'])
        self.assertEqual(sublime.get_clipboard(), 'foobar')

    def testGetDefaultToUnnamedRegister(self):
        registers._REGISTER_DATA['"'] = ['foo']
        self.view.settings().set('vintageous_use_sys_clipboard', False)
        self.assertEqual(self.regs.get(), ['foo'])

    def testGettingBlackHoleRegisterReturnsNone(self):
        self.assertEqual(self.regs.get(registers.REG_BLACK_HOLE), None)

    def testCanGetFileNameRegister(self):
        fname = self.regs.get(registers.REG_FILE_NAME)
        self.assertEqual(fname, [self.view.file_name()])

    def testCanGetClipboardRegisters(self):
        self.regs.set(registers.REG_SYS_CLIPBOARD_1, ['foo'])
        self.assertEqual(self.regs.get(registers.REG_SYS_CLIPBOARD_1), ['foo'])
        self.assertEqual(self.regs.get(registers.REG_SYS_CLIPBOARD_2), ['foo'])

        self.regs.set(registers.REG_SYS_CLIPBOARD_2, ['bar'])
        self.assertEqual(self.regs.get(registers.REG_SYS_CLIPBOARD_1), ['bar'])
        self.assertEqual(self.regs.get(registers.REG_SYS_CLIPBOARD_2), ['bar'])

    def testGetSysClipboardAlwaysIfRequested(self):
        self.regs.settings.view['vintageous_use_sys_clipboard'] = True
        sublime.set_clipboard('foo')
        self.assertEqual(self.regs.get(), ['foo'])

    def testGettingExpressionRegisterClearsExpressionRegister(self):
        registers._REGISTER_DATA[registers.REG_EXPRESSION] = ['100']
        self.view.settings().set('vintageous_use_sys_clipboard', False)
        self.assertEqual(self.regs.get(), ['100'])
        self.assertEqual(registers._REGISTER_DATA[registers.REG_EXPRESSION], '')

    def testCanGetNumberRegister(self):
        registers._REGISTER_DATA['5'] = ['foo']
        self.assertEqual(self.regs.get('5'), ['foo'])

    def testCanGetRegisterEvenIfRequestingItThroughACapitalLetter(self):
        registers._REGISTER_DATA['a'] = ['foo']
        self.assertEqual(self.regs.get('A'), ['foo'])

    def testCanGetRegistersWithDictSyntax(self):
        registers._REGISTER_DATA['a'] = ['foo']
        self.assertEqual(self.regs.get('a'), self.regs['a'])

    def testCanSetRegistersWithDictSyntax(self):
        self.regs['a'] = ['100']
        self.assertEqual(self.regs['a'], ['100'])

    def testCanAppendToRegisteWithDictSyntax(self):
        self.regs['a'] = ['100']
        self.regs['A'] = ['100']
        self.assertEqual(self.regs['a'], ['100100'])

    def testCanConvertToDict(self):
        self.regs['a'] = ['100']
        self.regs['b'] = ['200']
        values = {name: self.regs.get(name) for name in registers.REG_ALL}
        values.update({'a': ['100'], 'b': ['200']})
        self.assertEqual(self.regs.to_dict(), values)

    def testGettingEmptyRegisterReturnsNone(self):
        self.assertEqual(self.regs.get('a'), None)

    def testCanSetSmallDeleteRegister(self):
        self.regs[registers.REG_SMALL_DELETE] = ['foo']
        self.assertEqual(registers._REGISTER_DATA[registers.REG_SMALL_DELETE], ['foo'])

    def testCanGetSmallDeleteRegister(self):
        registers._REGISTER_DATA[registers.REG_SMALL_DELETE] = ['foo']
        self.assertEqual(self.regs.get(registers.REG_SMALL_DELETE), ['foo'])
예제 #44
0
    def run(self,
            line_range=None,
            forced=False,
            file_name='',
            plusplus_args='',
            operator='',
            target_redirect='',
            subcmd=''):

        if file_name and target_redirect:
            sublime.status_message('Vintageous: Too many arguments.')
            return

        appending = operator == '>>'
        a_range = line_range['text_range']
        self.view = self.window.active_view()
        content = get_region_by_range(self.view, line_range=line_range) if a_range else \
                        [sublime.Region(0, self.view.size())]

        read_only = False
        if self.view.file_name():
            mode = os.stat(self.view.file_name())
            read_only = (stat.S_IMODE(mode.st_mode) & stat.S_IWUSR !=
                         stat.S_IWUSR)

        if target_redirect:
            target = self.window.new_file()
            target.set_name(target_redirect)
        elif file_name:

            def report_error(msg):
                sublime.status_message('Vintageous: %s' % msg)

            file_path = os.path.abspath(os.path.expanduser(file_name))

            if os.path.exists(file_path) and (file_path !=
                                              self.view.file_name()):
                # TODO add w! flag
                # TODO: Hook this up with ex error handling (ex/errors.py).
                msg = "File '{0}' already exists.".format(file_path)
                report_error(msg)
                return

            if not os.path.exists(os.path.dirname(file_path)):
                msg = "Directory '{0}' does not exist.".format(
                    os.path.dirname(file_path))
                report_error(msg)
                return

            try:
                # FIXME: We need to do some work with encodings here, don't we?
                with open(file_path, 'w+') as temp_file:
                    for frag in reversed(content):
                        temp_file.write(self.view.substr(frag))
                    temp_file.close()
                    sublime.status_message(
                        "Vintageous: Saved {0}".format(file_path))

                    row, col = self.view.rowcol(self.view.sel()[0].b)
                    encoded_fn = "{0}:{1}:{2}".format(file_path, row + 1,
                                                      col + 1)
                    self.view.set_scratch(True)
                    w = self.window
                    w.run_command('close')
                    w.open_file(encoded_fn, sublime.ENCODED_POSITION)
                    return
            except IOError as e:
                report_error("Failed to create file '%s'." % file_name)
                return

            window = self.window
            window.open_file(file_path)
            return
        else:
            target = self.view

            if (read_only or self.view.is_read_only()) and not forced:
                utils.blink()
                sublime.status_message(
                    "Vintageous: Can't write read-only file.")
                return

        start = 0 if not appending else target.size()
        prefix = '\n' if appending and target.size() > 0 else ''

        if appending or target_redirect:
            for frag in reversed(content):
                target.run_command(
                    'append',
                    {'characters': prefix + self.view.substr(frag) + '\n'})
        elif a_range:
            start_deleting = 0
            text = ''
            for frag in content:
                text += self.view.substr(frag) + '\n'
            start_deleting = len(text)
            self.view.run_command('ex_replace_file', {
                'start': 0,
                'end': 0,
                'with_what': text
            })
        else:
            dirname = os.path.dirname(self.view.file_name())
            if not os.path.exists(dirname):
                os.makedirs(dirname)
            self.window.run_command('save')

        # This may unluckily prevent the user from seeing ST's feedback about saving the current
        # file.
        state = State(self.window.active_view())
        if state.mode != MODE_NORMAL:
            state.enter_normal_mode()
            self.window.run_command('vi_enter_normal_mode')
예제 #45
0
 def run(self):
     state = State(self.view)
     sublime.status_message(os.getcwd())
class Test_get_selected_text(ViewTest):
    def setUp(self):
        super().setUp()
        sublime.set_clipboard('')
        registers._REGISTER_DATA = {}
        self.view.settings().erase('vintage')
        self.view.settings().erase('vintageous_use_sys_clipboard')
        self.regs = State(self.view).registers
        self.regs.view = mock.Mock()

    def testExtractsSubstrings(self):
        self.regs.view.sel.return_value = [10, 20, 30]

        class vi_cmd_data:
            _synthetize_new_line_at_eof = False
            _yanks_linewise = False

        self.regs.get_selected_text(vi_cmd_data)
        self.assertEqual(self.regs.view.substr.call_count, 3)

    def testReturnsFragments(self):
        self.regs.view.sel.return_value = [10, 20, 30]
        self.regs.view.substr.side_effect = lambda x: x

        class vi_cmd_data:
            _synthetize_new_line_at_eof = False
            _yanks_linewise = False

        rv = self.regs.get_selected_text(vi_cmd_data)
        self.assertEqual(rv, [10, 20, 30])

    def testCanSynthetizeNewLineAtEof(self):
        self.regs.view.substr.return_value = "AAA"
        self.regs.view.sel.return_value = [sublime.Region(10, 10), sublime.Region(10, 10)]
        self.regs.view.size.return_value = 0

        class vi_cmd_data:
            _synthetize_new_line_at_eof = True
            _yanks_linewise = False

        rv = self.regs.get_selected_text(vi_cmd_data)
        self.assertEqual(rv, ["AAA", "AAA\n"])

    def testDoesntSynthetizeNewLineAtEofIfNotNeeded(self):
        self.regs.view.substr.return_value = "AAA\n"
        self.regs.view.sel.return_value = [sublime.Region(10, 10), sublime.Region(10, 10)]
        self.regs.view.size.return_value = 0

        class vi_cmd_data:
            _synthetize_new_line_at_eof = True
            _yanks_linewise = False

        rv = self.regs.get_selected_text(vi_cmd_data)
        self.assertEqual(rv, ["AAA\n", "AAA\n"])

    def testDoesntSynthetizeNewLineAtEofIfNotAtEof(self):
        self.regs.view.substr.return_value = "AAA"
        self.regs.view.sel.return_value = [sublime.Region(10, 10), sublime.Region(10, 10)]
        self.regs.view.size.return_value = 100

        class vi_cmd_data:
            _synthetize_new_line_at_eof = True
            _yanks_linewise = False

        rv = self.regs.get_selected_text(vi_cmd_data)
        self.assertEqual(rv, ["AAA", "AAA"])

    def testCanYankLinewise(self):
        self.regs.view.substr.return_value = "AAA"
        self.regs.view.sel.return_value = [sublime.Region(10, 10), sublime.Region(10, 10)]

        class vi_cmd_data:
            _synthetize_new_line_at_eof = False
            _yanks_linewise = True

        rv = self.regs.get_selected_text(vi_cmd_data)
        self.assertEqual(rv, ["AAA\n", "AAA\n"])

    def testDoesNotYankLinewiseIfNonEmptyStringFollowedByNewLine(self):
        self.regs.view.substr.return_value = "AAA\n"
        self.regs.view.sel.return_value = [sublime.Region(10, 10), sublime.Region(10, 10)]

        class vi_cmd_data:
            _synthetize_new_line_at_eof = False
            _yanks_linewise = True

        rv = self.regs.get_selected_text(vi_cmd_data)
        self.assertEqual(rv, ["AAA\n", "AAA\n"])

    def testYankLinewiseIfEmptyStringFollowedByNewLine(self):
        self.regs.view.substr.return_value = "\n"
        self.regs.view.sel.return_value = [sublime.Region(10, 10), sublime.Region(10, 10)]

        class vi_cmd_data:
            _synthetize_new_line_at_eof = False
            _yanks_linewise = True

        rv = self.regs.get_selected_text(vi_cmd_data)
        self.assertEqual(rv, ["\n\n", "\n\n"])

    def testYankLinewiseIfTwoTrailingNewLines(self):
        self.regs.view.substr.return_value = "\n\n"
        self.regs.view.sel.return_value = [sublime.Region(10, 10), sublime.Region(10, 10)]

        class vi_cmd_data:
            _synthetize_new_line_at_eof = False
            _yanks_linewise = True

        rv = self.regs.get_selected_text(vi_cmd_data)
        self.assertEqual(rv, ["\n\n\n", "\n\n\n"])
예제 #47
0
class MarksTests(ViewTest):
    def setUp(self):
        super().setUp()
        marks._MARKS = {}
        self.view.sel().clear()
        self.view.sel().add(sublime.Region(0, 0))
        self.marks = State(self.view).marks

    def testCanSetMark(self):
        self.marks.add('a', self.view)
        expected_win, expected_view, expected_region = (self.view.window(), self.view, (0, 0))
        actual_win, actual_view, actual_region = marks._MARKS['a']
        self.assertEqual((actual_win.id(), actual_view.view_id, actual_region),
                         (expected_win.id(), expected_view.view_id, expected_region))

    def testCanRetrieveMarkInTheCurrentBufferAsTuple(self):
        self.marks.add('a', self.view)
        # The caret's at the beginning of the buffer.
        self.assertEqual(self.marks.get_as_encoded_address('a'), sublime.Region(0, 0))

    def testCanRetrieveMarkInTheCurrentBufferAsTuple2(self):
        set_text(self.view, ''.join(('foo bar\n') * 10))
        self.view.sel().clear()
        self.view.sel().add(sublime.Region(30, 30))
        self.marks.add('a', self.view)
        self.assertEqual(self.marks.get_as_encoded_address('a'), sublime.Region(24, 24))

    def testCanRetrieveMarkInADifferentBufferAsEncodedMark(self):
        view = View(id_=self.view.view_id + 1, fname=r'C:\foo.txt')

        marks._MARKS['a'] = (Window(), view, (0, 0))
        expected = "{0}:{1}".format(r'C:\foo.txt', "0:0")
        self.assertEqual(self.marks.get_as_encoded_address('a'), expected)

    def testCanRetrieveMarkInAnUntitledBufferAsEncodedMark(self):
        view = View(id_=self.view.view_id + 1, fname='', buffer_id=999)

        marks._MARKS['a'] = (Window(), view, (0, 0))
        expected = "<untitled {0}>:{1}".format(999, "0:0")
        self.assertEqual(self.marks.get_as_encoded_address('a'), expected)

    def testCanRetrieveSingleQuoteMark(self):
        location = self.marks.get_as_encoded_address("'")
        self.assertEqual(location, '<command _vi_double_single_quote>')
예제 #48
0
 def run(self, key=None):
     state = State(self.window.active_view())
     if not state.user_input:
         state.user_input = utils.translate_char(key)
class Test_yank(ViewTest):
    def setUp(self):
        super().setUp()
        sublime.set_clipboard('')
        registers._REGISTER_DATA = {}
        self.view.settings().erase('vintage')
        self.view.settings().erase('vintageous_use_sys_clipboard')
        self.regs = State(self.view).registers
        self.regs.view = mock.Mock()

    def testDontYankIfWeDontHaveTo(self):
        class vi_cmd_data:
            _can_yank = False
            _populates_small_delete_register = False

        self.regs.yank(vi_cmd_data)
        self.assertEqual(registers._REGISTER_DATA, {})

    def testYanksToUnnamedRegisterIfNoRegisterNameProvided(self):
        class vi_cmd_data:
            _can_yank = True
            _synthetize_new_line_at_eof = False
            _yanks_linewise = True
            register = None
            _populates_small_delete_register = False

        with mock.patch.object(self.regs, 'get_selected_text') as gst:
            gst.return_value = ['foo']
            self.regs.yank(vi_cmd_data)
            self.assertEqual(registers._REGISTER_DATA, {'"': ['foo']})

    def testYanksToRegisters(self):
        class vi_cmd_data:
            _can_yank = True
            _populates_small_delete_register = False

        with mock.patch.object(self.regs, 'get_selected_text') as gst:
            gst.return_value = ['foo']
            self.regs.yank(vi_cmd_data, register='a')
            self.assertEqual(registers._REGISTER_DATA, {'"': ['foo'], 'a': ['foo']})

    def testCanPopulateSmallDeleteRegister(self):
        class vi_cmd_data:
            _can_yank = True
            _populates_small_delete_register = True

        with mock.patch.object(builtins, 'all') as a, \
             mock.patch.object(self.regs, 'get_selected_text') as gst:
                gst.return_value = ['foo']
                self.regs.view.sel.return_value = range(1)
                a.return_value = True
                self.regs.yank(vi_cmd_data)
                self.assertEqual(registers._REGISTER_DATA, {'"': ['foo'], '-': ['foo']})

    def testDoesNotPopulateSmallDeleteRegisterIfWeShouldNot(self):
        class vi_cmd_data:
            _can_yank = False
            _populates_small_delete_register = False

        with mock.patch.object(builtins, 'all') as a, \
             mock.patch.object(self.regs, 'get_selected_text') as gst:
                gst.return_value = ['foo']
                self.regs.view.sel.return_value = range(1)
                a.return_value = False
                self.regs.yank(vi_cmd_data)
                self.assertEqual(registers._REGISTER_DATA, {})
예제 #50
0
 def setUp(self):
     super().setUp()
     marks._MARKS = {}
     self.view.sel().clear()
     self.view.sel().add(sublime.Region(0, 0))
     self.marks = State(self.view).marks
예제 #51
0
 def set_mode(self):
     state = State(self.view)
     state.enter_normal_mode()
     self.view.run_command('vi_enter_normal_mode')
예제 #52
0
 def run(self, key=None):
     state = State(self.window.active_view())
     state.motion = cmd_defs.ViSearchBackwardImpl()
     state.last_buffer_search = state.motion._inp or state.last_buffer_search