示例#1
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)
示例#2
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)
示例#3
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')
示例#4
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])
示例#5
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
                         }]]
                    })
示例#6
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)
示例#7
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)
示例#8
0
    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()
示例#9
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()
示例#10
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
示例#11
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.')
示例#12
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))
示例#13
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)
示例#14
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
示例#15
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
示例#16
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)
示例#17
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)
示例#18
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]
示例#19
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)
示例#20
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)
示例#21
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
            })
示例#22
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]
示例#23
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))
示例#24
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)
示例#25
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)
示例#26
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
示例#27
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
示例#28
0
 def state(self):
     return State(self.view)
示例#29
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')
示例#30
0
 def run(self):
     state = State(self.view)
     sublime.status_message(os.getcwd())