Ejemplo n.º 1
0
    def file_to_edit(self, ft):
        """ Gets a file to edit based on the given filetype.
        If no filetype is given, uses the current filetype from Vim.

        Checks 'g:UltiSnipsSnippetsDir' and uses it if it exists
        If a non-shipped file already exists, it uses it.
        Otherwise uses a file in ~/.vim/ or ~/vimfiles
        """
        edit = None
        existing = self.base_snippet_files_for(ft, False)
        filename = ft + ".snippets"

        if _vim.eval("exists('g:UltiSnipsSnippetsDir')") == "1":
            snipdir = _vim.eval("g:UltiSnipsSnippetsDir")
            edit = os.path.join(snipdir, filename)
        elif existing:
            edit = existing[-1] # last sourced/highest priority
        else:
            home = "C:\\vim\\vimfiles\\bundle\\ultisnips"
            snippet_dirs = ["UltiSnips"] + _vim.eval("g:UltiSnipsSnippetDirectories")
            us = snippet_dirs[-1]

            path = os.path.join(home, us)

            if not os.path.isdir(path):
                os.mkdir(path)

            edit = os.path.join(path, filename)

        return edit
Ejemplo n.º 2
0
    def _handle_failure(self, trigger):
        """Mainly make sure that we play well with SuperTab."""
        if trigger.lower() == "<tab>":
            feedkey = "\\" + trigger
        elif trigger.lower() == "<s-tab>":
            feedkey = "\\" + trigger
        else:
            feedkey = None
        mode = "n"
        if not self._supertab_keys:
            if _vim.eval("exists('g:SuperTabMappingForward')") != "0":
                self._supertab_keys = (
                    _vim.eval("g:SuperTabMappingForward"),
                    _vim.eval("g:SuperTabMappingBackward"),
                )
            else:
                self._supertab_keys = ['', '']

        for idx, sttrig in enumerate(self._supertab_keys):
            if trigger.lower() == sttrig.lower():
                if idx == 0:
                    feedkey = r"\<Plug>SuperTabForward"
                    mode = "n"
                elif idx == 1:
                    feedkey = r"\<Plug>SuperTabBackward"
                    mode = "p"
                # Use remap mode so SuperTab mappings will be invoked.
                break

        if (feedkey == r"\<Plug>SuperTabForward" or
                feedkey == r"\<Plug>SuperTabBackward"):
            _vim.command("return SuperTab(%s)" % _vim.escape(mode))
        elif feedkey:
            _vim.command("return %s" % _vim.escape(feedkey))
Ejemplo n.º 3
0
def guess_edit(initial_line, lt, ct, vs):
    """
    Try to guess what the user might have done by heuristically looking at cursor movement
    number of changed lines and if they got longer or shorter. This will detect most simple
    movements like insertion, deletion of a line or carriage return.
    """
    if not len(lt) and not len(ct): return True, ()
    pos = vs.pos
    ppos = vs.ppos
    if len(lt) and (not ct or (len(ct) == 1 and not ct[0])):  # All text deleted?
        es = []
        if not ct: ct = ['']
        for i in lt:
            es.append(("D", initial_line, 0, i))
            es.append(("D", initial_line, 0, "\n"))
        es.pop() # Remove final \n because it is not really removed
        if is_complete_edit(initial_line, lt, ct, es): return True, es
    if ppos.mode == 'v': # Maybe selectmode?
        sv = list(map(int, _vim.eval("""getpos("'<")"""))); sv = Position(sv[1]-1,sv[2]-1)
        ev = list(map(int, _vim.eval("""getpos("'>")"""))); ev = Position(ev[1]-1,ev[2]-1)
        if "exclusive" in _vim.eval("&selection"):
            ppos.col -= 1 # We want to be inclusive, sorry.
            ev.col -= 1
        es = []
        if sv.line == ev.line:
            es.append(("D", sv.line, sv.col, lt[sv.line - initial_line][sv.col:ev.col+1]))
            if sv != pos and sv.line == pos.line:
                es.append(("I", sv.line, sv.col, ct[sv.line - initial_line][sv.col:pos.col+1]))
        if is_complete_edit(initial_line, lt, ct, es): return True, es
    if pos.line == ppos.line:
        if len(lt) == len(ct): # Movement only in one line
            llen = len(lt[ppos.line - initial_line])
            clen = len(ct[pos.line - initial_line])
            if ppos < pos and clen > llen: # Likely that only characters have been added
                es = (
                    ("I", ppos.line, ppos.col, ct[ppos.line - initial_line][ppos.col:pos.col]),
                )
                if is_complete_edit(initial_line, lt, ct, es): return True, es
            if clen < llen:
                if ppos == pos: # 'x' or DEL or dt or something
                    es = (
                        ("D", pos.line, pos.col, lt[ppos.line - initial_line][ppos.col:ppos.col + (llen - clen)]),
                    )
                    if is_complete_edit(initial_line, lt, ct, es): return True, es
                if pos < ppos: # Backspacing or dT dF?
                    es = (
                        ("D", pos.line, pos.col, lt[pos.line - initial_line][pos.col:pos.col + llen - clen]),
                    )
                    if is_complete_edit(initial_line, lt, ct, es): return True, es
        elif len(ct) < len(lt): # Maybe some lines were deleted? (dd or so)
            es = []
            for i in range(len(lt)-len(ct)):
                es.append( ("D", pos.line, 0, lt[pos.line - initial_line + i]))
                es.append( ("D", pos.line, 0, '\n'))
            if is_complete_edit(initial_line, lt, ct, es): return True, es
    else: # Movement in more than one line
        if ppos.line + 1 == pos.line and pos.col == 0: # Carriage return?
            es = (("I", ppos.line, ppos.col, "\n"),)
            if is_complete_edit(initial_line, lt, ct, es): return True, es
    return False, None
Ejemplo n.º 4
0
    def __init__(self, expand_trigger, forward_trigger, backward_trigger):
        self.expand_trigger = expand_trigger
        self.forward_trigger = forward_trigger
        self.backward_trigger = backward_trigger
        self._inner_state_up = False
        self._supertab_keys = None

        self._csnippets = []
        self._buffer_filetypes = defaultdict(lambda: ["all"])

        self._vstate = VimState()
        self._visual_content = VisualContentPreserver()

        self._snippet_sources = []

        self._snip_expanded_in_action = False
        self._inside_action = False

        self._last_inserted_char = ""

        self._added_snippets_source = AddedSnippetsSource()
        self.register_snippet_source("ultisnips_files", UltiSnipsFileSource())
        self.register_snippet_source("added", self._added_snippets_source)

        enable_snipmate = "1"
        if _vim.eval("exists('g:UltiSnipsEnableSnipMate')") == "1":
            enable_snipmate = _vim.eval("g:UltiSnipsEnableSnipMate")
        if enable_snipmate == "1":
            self.register_snippet_source("snipmate_files", SnipMateFileSource())

        self._reinit()
Ejemplo n.º 5
0
    def __init__(self, expand_trigger, forward_trigger, backward_trigger):
        self.expand_trigger = expand_trigger
        self.forward_trigger = forward_trigger
        self.backward_trigger = backward_trigger
        self._inner_state_up = False
        self._supertab_keys = None

        self._csnippets = []
        self._buffer_filetypes = defaultdict(lambda: ['all'])

        self._vstate = VimState()
        self._visual_content = VisualContentPreserver()

        self._snippet_sources = []

        self._snip_expanded_in_action = False
        self._inside_action = False

        self._last_inserted_char = ''

        self._added_snippets_source = AddedSnippetsSource()
        self.register_snippet_source('ultisnips_files', UltiSnipsFileSource())
        self.register_snippet_source('added', self._added_snippets_source)

        enable_snipmate = '1'
        if _vim.eval("exists('g:UltiSnipsEnableSnipMate')") == '1':
            enable_snipmate = _vim.eval('g:UltiSnipsEnableSnipMate')
        if enable_snipmate == '1':
            self.register_snippet_source('snipmate_files',
                                         SnipMateFileSource())

        self._should_update_textobjects = False
        self._should_reset_visual = False

        self._reinit()
Ejemplo n.º 6
0
    def __init__(self, expand_trigger, forward_trigger, backward_trigger):
        self.expand_trigger = expand_trigger
        self.forward_trigger = forward_trigger
        self.backward_trigger = backward_trigger
        self._inner_mappings_in_place = False
        self._supertab_keys = None

        self._csnippets = []
        self._buffer_filetypes = defaultdict(lambda: ['all'])

        self._vstate = VimState()
        self._visual_content = VisualContentPreserver()

        self._snippet_sources = []

        self._added_snippets_source = AddedSnippetsSource()
        self.register_snippet_source('ultisnips_files', UltiSnipsFileSource())
        self.register_snippet_source('added', self._added_snippets_source)

        enable_snipmate = True
        if _vim.eval("exists('g:UltiSnipsEnableSnipMate')") == '1':
            enable_snipmate = _vim.eval('g:UltiSnipsEnableSnipMate')
        if enable_snipmate == '1':
            self.register_snippet_source('snipmate_files',
                                         SnipMateFileSource())

        self._reinit()
Ejemplo n.º 7
0
    def __init__(self, expand_trigger, forward_trigger, backward_trigger):
        self.expand_trigger = expand_trigger
        self.forward_trigger = forward_trigger
        self.backward_trigger = backward_trigger
        self._inner_mappings_in_place = False
        self._supertab_keys = None

        self._csnippets = []
        self._buffer_filetypes = defaultdict(lambda: ['all'])

        self._vstate = VimState()
        self._visual_content = VisualContentPreserver()

        self._snippet_sources = []

        self._added_snippets_source = AddedSnippetsSource()
        self.register_snippet_source("ultisnips_files", UltiSnipsFileSource())
        self.register_snippet_source("added", self._added_snippets_source)

        if _vim.eval("exists('g:UltiSnipsDisableSnipMate')") == "1":
            disable_snipmate = _vim.eval("g:UltiSnipsDisableSnipMate")
        else:
            disable_snipmate = "0"
        if disable_snipmate != "1":
            self.register_snippet_source("snipmate_files",
                SnipMateFileSource())

        self._reinit()
Ejemplo n.º 8
0
def find_all_snippet_files(ft):
    """Returns all snippet files matching 'ft' in the given runtime path
    directory."""
    if _vim.eval("exists('b:UltiSnipsSnippetDirectories')") == "1":
        snippet_dirs = _vim.eval("b:UltiSnipsSnippetDirectories")
    else:
        snippet_dirs = _vim.eval("g:UltiSnipsSnippetDirectories")
    if len(snippet_dirs) == 1 and os.path.isabs(snippet_dirs[0]):
        check_dirs = ['']
    else:
        check_dirs = _vim.eval("&runtimepath").split(',')
    patterns = ["%s.snippets", "%s_*.snippets", os.path.join("%s", "*")]
    ret = set()
    for rtp in check_dirs:
        for snippet_dir in snippet_dirs:
            if snippet_dir == "snippets":
                raise RuntimeError(
                    "You have 'snippets' in UltiSnipsSnippetDirectories. This "
                    "directory is reserved for snipMate snippets. Use another "
                    "directory for UltiSnips snippets.")
            pth = os.path.realpath(os.path.expanduser(
                os.path.join(rtp, snippet_dir)))
            for pattern in patterns:
                for fn in glob.glob(os.path.join(pth, pattern % ft)):
                    ret.add(fn)
    return ret
Ejemplo n.º 9
0
    def base_snippet_files_for(self, ft, default=True):
        """ Returns a list of snippet files matching the given filetype (ft).
        If default is set to false, it doesn't include shipped files.

        Searches through each path in 'runtimepath' in reverse order,
        in each of these, it searches each directory name listed in
        'g:UltiSnipsSnippetDirectories' in order, then looks for files in these
        directories called 'ft.snippets' or '*_ft.snippets' replacing ft with
        the filetype.
        """

        snippet_dirs = _vim.eval("g:UltiSnipsSnippetDirectories")
        base_snippets = os.path.realpath(os.path.join(__file__, "../../../UltiSnips"))
        ret = []

        paths = _vim.eval("&runtimepath").split(',')

        if _vim.eval("exists('g:UltiSnipsDontReverseSearchPath')") == "0" or \
           _vim.eval("g:UltiSnipsDontReverseSearchPath") == "0":
            paths = paths[::-1]

        for rtp in paths:
            for snippet_dir in snippet_dirs:
                pth = os.path.realpath(os.path.expanduser(os.path.join(rtp, snippet_dir)))

                patterns = ["%s.snippets", "%s_*.snippets", os.path.join("%s","*")]
                if not default and pth == base_snippets:
                    patterns.remove("%s.snippets")

                for pattern in patterns:
                    for fn in glob.glob(os.path.join(pth, pattern % ft)):
                        if fn not in ret:
                            ret.append(fn)

        return ret
Ejemplo n.º 10
0
def _find_all_snippet_directories():
    """Returns a list of the absolute path of all snippet directories to
    search."""

    if _vim.eval("exists('b:UltiSnipsSnippetDirectories')") == '1':
        snippet_dirs = _vim.eval('b:UltiSnipsSnippetDirectories')
    else:
        snippet_dirs = _vim.eval('g:UltiSnipsSnippetDirectories')
    if len(snippet_dirs) == 1 and os.path.isabs(snippet_dirs[0]):
        return snippet_dirs

    all_dirs = []
    check_dirs = _vim.eval('&runtimepath').split(',')
    for rtp in check_dirs:
        for snippet_dir in snippet_dirs:
            if snippet_dir == 'snippets':
                raise RuntimeError(
                    "You have 'snippets' in UltiSnipsSnippetDirectories. This "
                    'directory is reserved for snipMate snippets. Use another '
                    'directory for UltiSnips snippets.')
            pth = os.path.realpath(os.path.expanduser(
                os.path.join(rtp, snippet_dir)))
            if os.path.isdir(pth):
                all_dirs.append(pth)
    return all_dirs
Ejemplo n.º 11
0
    def file_to_edit(self, ft):
        """ Gets a file to edit based on the given filetype.
        If no filetype is given, uses the current filetype from Vim.

        Checks 'g:UltiSnipsSnippetsDir' and uses it if it exists
        If a non-shipped file already exists, it uses it.
        Otherwise uses a file in ~/.vim/ or ~/vimfiles
        """
        edit = None
        existing = self.base_snippet_files_for(ft, False)
        filename = ft + ".snippets"

        if _vim.eval("exists('g:UltiSnipsSnippetsDir')") == "1":
            snipdir = _vim.eval("g:UltiSnipsSnippetsDir")
            edit = os.path.join(snipdir, filename)
        elif existing:
            edit = existing[-1] # last sourced/highest priority
        else:
            home = _vim.eval("$HOME")
            rtp = [ os.path.realpath(os.path.expanduser(p)) for p in _vim.eval("&rtp").split(",") ]
            snippet_dirs = ["UltiSnips"] + _vim.eval("g:UltiSnipsSnippetDirectories")
            us = snippet_dirs[-1]

            path = os.path.join(home, ".vim", us)
            for dirname in [".vim", "vimfiles"]:
                pth = os.path.join(home, dirname)
                if pth in rtp:
                    path = os.path.join(pth, us)

            if not os.path.isdir(path):
                os.mkdir(path)

            edit = os.path.join(path, filename)

        return edit
Ejemplo n.º 12
0
def base_snippet_files_for(ft, default=True):
    """Returns a list of snippet files matching the given filetype (ft).
    If default is set to false, it doesn't include shipped files.

    Searches through each path in 'runtimepath' in reverse order,
    in each of these, it searches each directory name listed in
    'g:UltiSnipsSnippetDirectories' in order, then looks for files in these
    directories called 'ft.snippets' or '*_ft.snippets' replacing ft with
    the filetype.
    """
    if _vim.eval("exists('b:UltiSnipsSnippetDirectories')") == "1":
        snippet_dirs = _vim.eval("b:UltiSnipsSnippetDirectories")
    else:
        snippet_dirs = _vim.eval("g:UltiSnipsSnippetDirectories")

    base_snippets = os.path.realpath(os.path.join(_plugin_dir(), "UltiSnips"))
    ret = []
    for rtp in _vim.eval("&runtimepath").split(','):
        for snippet_dir in snippet_dirs:
            if snippet_dir == "snippets":
                raise RuntimeError(
                    "You have 'snippets' in UltiSnipsSnippetDirectories. This "
                    "directory is reserved for snipMate snippets. Use another "
                    "directory for UltiSnips snippets.")
            pth = os.path.realpath(os.path.expanduser(
                os.path.join(rtp, snippet_dir)))
            patterns = ["%s.snippets", "%s_*.snippets", os.path.join("%s", "*")]
            if not default and pth == base_snippets:
                patterns.remove("%s.snippets")

            for pattern in patterns:
                for fn in glob.glob(os.path.join(pth, pattern % ft)):
                    if fn not in ret:
                        ret.append(fn)
    return ret
Ejemplo n.º 13
0
    def _handle_failure(self, trigger):
        """
        Mainly make sure that we play well with SuperTab
        """
        if trigger.lower() == "<tab>":
            feedkey = "\\" + trigger
        else:
            feedkey = None
        mode = "n"
        if not self._supertab_keys:
            if _vim.eval("exists('g:SuperTabMappingForward')") != "0":
                self._supertab_keys = (
                    _vim.eval("g:SuperTabMappingForward"),
                    _vim.eval("g:SuperTabMappingBackward"),
                )
            else:
                self._supertab_keys = [ '', '' ]

        for idx, sttrig in enumerate(self._supertab_keys):
            if trigger.lower() == sttrig.lower():
                if idx == 0:
                    feedkey= r"\<c-n>"
                elif idx == 1:
                    feedkey = r"\<c-p>"
                # Use remap mode so SuperTab mappings will be invoked.
                mode = "m"
                break

        if feedkey:
            _vim.feedkeys(feedkey, mode)
Ejemplo n.º 14
0
 def opt(self, option, default=None):  # pylint:disable=no-self-use
     """Gets a Vim variable."""
     if _vim.eval("exists('%s')" % option) == '1':
         try:
             return _vim.eval(option)
         except _vim.error:
             pass
     return default
Ejemplo n.º 15
0
 def opt(self, option, default=None):
     """ Gets a Vim variable. """
     if _vim.eval("exists('%s')" % option) == "1":
         try:
             return _vim.eval(option)
         except _vim.error:
             pass
     return default
Ejemplo n.º 16
0
Archivo: util.py Proyecto: rupa/.vim
    def reset(self):
        """ Gets the spacing properties from Vim. """
        self.sw = int(_vim.eval("&sw"))
        self.sts = int(_vim.eval("&sts"))
        self.et = _vim.eval("&expandtab") == "1"
        self.ts = int(_vim.eval("&ts"))

        # The amount added when pressing tab in insert mode
        self.ind_len = self.sts or self.ts
Ejemplo n.º 17
0
def _should_reverse_search_path():
    """ If the user defined g:UltiSnipsDontReverseSearchPath then return True
    or False based on the value of that variable, else defer to
    _snippets_dir_is_before_plugin_dir to determine whether this is True or
    False.
    """
    if _vim.eval("exists('g:UltiSnipsDontReverseSearchPath')") != "0":
       return _vim.eval("g:UltiSnipsDontReverseSearchPath") != "0"
    return not _snippets_dir_is_before_plugin_dir()
Ejemplo n.º 18
0
    def _file_to_edit(self, requested_ft, bang):  # pylint: disable=no-self-use
        """Returns a file to be edited for the given requested_ft.

        If 'bang' is
        empty only private files in g:UltiSnipsSnippetsDir are considered,
        otherwise all files are considered and the user gets to choose.

        """
        # This method is not using self, but is called by UltiSnips.vim and is
        # therefore in this class because it is the facade to Vim.
        potentials = set()

        if _vim.eval("exists('g:UltiSnipsSnippetsDir')") == '1':
            snippet_dir = _vim.eval('g:UltiSnipsSnippetsDir')
        else:
            home = _vim.eval('$HOME')
            if platform.system() == 'Windows':
                snippet_dir = os.path.join(home, 'vimfiles', 'UltiSnips')
            elif _vim.eval("has('nvim')") == '1':
                xdg_home_config = _vim.eval('$XDG_CONFIG_HOME') or os.path.join(home, ".config")
                snippet_dir = os.path.join(xdg_home_config, 'nvim', 'UltiSnips')
            else:
                snippet_dir = os.path.join(home, '.vim', 'UltiSnips')

        filetypes = []
        if requested_ft:
            filetypes.append(requested_ft)
        else:
            if bang:
                filetypes.extend(self._buffer_filetypes[_vim.buf.number])
            else:
                filetypes.append(self._buffer_filetypes[_vim.buf.number][0])

        for ft in filetypes:
            potentials.update(find_snippet_files(ft, snippet_dir))
            potentials.add(os.path.join(snippet_dir,
                                        ft + '.snippets'))
            if bang:
                potentials.update(find_all_snippet_files(ft))

        potentials = set(os.path.realpath(os.path.expanduser(p))
                         for p in potentials)

        if len(potentials) > 1:
            files = sorted(potentials)
            formatted = [as_unicode('%i: %s') % (i, escape(fn, '\\')) for
                         i, fn in enumerate(files, 1)]
            file_to_edit = _ask_user(files, formatted)
            if file_to_edit is None:
                return ''
        else:
            file_to_edit = potentials.pop()

        dirname = os.path.dirname(file_to_edit)
        if not os.path.exists(dirname):
            os.makedirs(dirname)
        return file_to_edit
Ejemplo n.º 19
0
    def _needs_update(self, ft):
        do_hash = _vim.eval('exists("g:UltiSnipsDoHash")') == "0" or _vim.eval("g:UltiSnipsDoHash") != "0"

        if ft not in self._snippets:
            return True
        elif do_hash and self.snippet_dict(ft).needs_update():
            return True
        elif do_hash:
            cur_snips = set(self.base_snippet_files_for(ft))
            old_snips = set(self.snippet_dict(ft).files)

            if cur_snips - old_snips:
                return True

        return False
Ejemplo n.º 20
0
 def _parse_snippets(self, ft, filename):
     """Parse the 'filename' for the given 'ft' and watch it for changes in
     the future."""
     self._file_hashes[filename] = _hash_file(filename)
     file_data = compatibility.open_ascii_file(filename, "r").read()
     for event, data in self._parse_snippet_file(file_data, filename):
         if event == "error":
             msg, line_index = data
             filename = _vim.eval("""fnamemodify(%s, ":~:.")""" %
                     _vim.escape(filename))
             raise SnippetSyntaxError(filename, line_index, msg)
         elif event == "clearsnippets":
             # TODO(sirver): clear snippets should clear for
             # more sources, not only ultisnips files.
             triggers, = data
             self._snippets[ft].clear_snippets(triggers)
         elif event == "extends":
             # TODO(sirver): extends information is more global
             # than one snippet source.
             filetypes, = data
             self._add_extending_info(ft, filetypes)
         elif event == "snippet":
             snippet, = data
             self._snippets[ft].add_snippet(snippet)
         else:
             assert False, "Unhandled %s: %r" % (event, data)
Ejemplo n.º 21
0
    def _update(self, done, not_done):
        path = _vim.eval('expand("%")')
        if path is None:
            path = ""
        fn = os.path.basename(path)

        ct = self.current_text
        self._snip._reset(ct)
        local_d = self._locals

        local_d.update({
            't': _Tabs(self._parent),
            'fn': fn,
            'path': path,
            'cur': ct,
            'res': ct,
            'i': self._snip.i,
            'snip' : self._snip,
        })

        compatible_exec(self._code, self._globals, local_d)

        rv = as_unicode(self._snip.rv if self._snip._rv_changed
                else as_unicode(local_d['res']))

        if ct != rv:
            self.overwrite(rv)
            return False
        return True
Ejemplo n.º 22
0
    def _track_change(self):
        self._should_update_textobjects = True

        try:
            inserted_char = _vim.as_unicode(_vim.eval('v:char'))
        except UnicodeDecodeError:
            return

        if sys.version_info >= (3, 0):
            if isinstance(inserted_char, bytes):
                return
        else:
            if not isinstance(inserted_char, unicode):
                return

        try:
            if inserted_char == '':
                before = _vim.buf.line_till_cursor

                if before and before[-1] == self._last_change[0] or \
                        self._last_change[1] != vim.current.window.cursor[0]:
                    self._try_expand(autotrigger_only=True)
        finally:
            self._last_change = (inserted_char, vim.current.window.cursor[0])

        if self._should_reset_visual and self._visual_content.mode == '':
            self._visual_content.reset()

        self._should_reset_visual = True
Ejemplo n.º 23
0
 def _parse_snippets(self, ft, filename):
     """Parse the file 'filename' for the given 'ft' and watch it for
     changes in the future. 'file_data' can be injected in tests."""
     current_snippet_priority = 0
     self._snippets[ft].addfile(filename)
     file_data = open(filename, "r").read()
     for event, data in parse_snippets_file(file_data):
         if event == "error":
             msg, line_index = data
             filename = _vim.eval("""fnamemodify(%s, ":~:.")""" %
                     _vim.escape(filename))
             raise SnippetSyntaxError(filename, line_index, msg)
         elif event == "clearsnippets":
             # TODO(sirver): clear snippets should clear for
             # more providers, not only ultisnips files.
             triggers, = data
             self._snippets[ft].clear_snippets(triggers)
         elif event == "extends":
             # TODO(sirver): extends information is more global
             # than one snippet provider.
             filetypes, = data
             self._add_extending_info(ft, filetypes)
         elif event == "snippet":
             trigger, value, description, options, global_pythons = data
             self._snippets[ft].add_snippet(
                 SnippetDefinition(current_snippet_priority, trigger, value,
                     description, options, global_pythons), filename
             )
         elif event == "priority":
             priority, = data
             current_snippet_priority = priority
         else:
             assert False, "Unhandled %s: %r" % (event, data)
Ejemplo n.º 24
0
    def _update(self, done, buf):
        path = _vim.eval('expand("%")') or ''
        ct = self.current_text
        self._locals.update({
            't': _Tabs(self._parent),
            'fn': os.path.basename(path),
            'path': path,
            'cur': ct,
            'res': ct,
            'snip': self._snip,
        })
        self._snip._reset(ct)  # pylint:disable=protected-access

        for code in self._codes:
            try:
                exec(code, self._locals)  # pylint:disable=exec-used
            except Exception as e:
                e.snippet_code = code
                raise

        rv = as_unicode(
            self._snip.rv if self._snip._rv_changed  # pylint:disable=protected-access
            else as_unicode(self._locals['res'])
        )

        if ct != rv:
            self.overwrite(buf, rv)
            return False
        return True
Ejemplo n.º 25
0
    def _handle_failure(self, trigger):
        """
        Mainly make sure that we play well with SuperTab or pre-existing keymaps
        """
        if trigger.lower() == _vim.eval("g:UltiSnipsExpandTrigger").lower() and _vim.eval("g:UltiSnipsExpandTriggerOverrides") != "":
            feedkey = "" + _vim.eval("g:UltiSnipsExpandTriggerOverrides")
            mode = "i"
        elif trigger.lower() == _vim.eval("g:UltiSnipsJumpForwardTrigger").lower() and _vim.eval("g:UltiSnipsJumpForwardTriggerOverrides") != "":
            feedkey = "" + _vim.eval("g:UltiSnipsJumpForwardTriggerOverrides")
            mode = "i"
        elif trigger.lower() == _vim.eval("g:UltiSnipsJumpBackwardTrigger").lower() and _vim.eval("g:UltiSnipsJumpBackwardTriggerOverrides") != "":
            feedkey = "" + _vim.eval("g:UltiSnipsJumpBackwardTriggerOverrides")
            mode = "i"
        elif trigger.lower() == "<tab>":
            feedkey = "\\" + trigger
            mode = "n"
        elif trigger.lower() == "<s-tab>":
            feedkey = "\\" + trigger
            mode = "n"
        else:
            feedkey = None
            mode = "n"
        if not self._supertab_keys:
            if _vim.eval("exists('g:SuperTabMappingForward')") != '0':
                self._supertab_keys = (
                    _vim.eval('g:SuperTabMappingForward'),
                    _vim.eval('g:SuperTabMappingBackward'),
                )
            else:
                self._supertab_keys = ['', '']

        for idx, sttrig in enumerate(self._supertab_keys):
            if trigger.lower() == sttrig.lower():
                if idx == 0:
                    feedkey = r"\<Plug>SuperTabForward"
                    mode = 'n'
                elif idx == 1:
                    feedkey = r"\<Plug>SuperTabBackward"
                    mode = 'p'
                # Use remap mode so SuperTab mappings will be invoked.
                break

        if (feedkey == r"\<Plug>SuperTabForward" or
                feedkey == r"\<Plug>SuperTabBackward"):
            _vim.command('return SuperTab(%s)' % _vim.escape(mode))
        elif feedkey:
            _vim.command('return %s' % _vim.escape(feedkey))
Ejemplo n.º 26
0
    def conserve(self):
        sl, sc = map(int, (_vim.eval("""line("'<")"""), _vim.eval("""virtcol("'<")""")))
        el, ec = map(int, (_vim.eval("""line("'>")"""), _vim.eval("""virtcol("'>")""")))
        self._mode = _vim.eval("visualmode()")

        def _vim_line_with_eol(ln):
            return _vim.buf[ln] + '\n'

        if sl == el:
            text = _vim_line_with_eol(sl-1)[sc-1:ec]
        else:
            text = _vim_line_with_eol(sl-1)[sc-1:]
            for cl in range(sl,el-1):
                text += _vim_line_with_eol(cl)
            text += _vim_line_with_eol(el-1)[:ec]

        self._text = text
Ejemplo n.º 27
0
    def conserve(self):
        """Save the last visual selection ond the mode it was made in."""
        sl, sbyte = map(int, (_vim.eval("""line("'<")"""), _vim.eval("""col("'<")""")))
        el, ebyte = map(int, (_vim.eval("""line("'>")"""), _vim.eval("""col("'>")""")))
        sc = byte2col(sl, sbyte - 1)
        ec = byte2col(el, ebyte - 1)
        self._mode = _vim.eval("visualmode()")

        _vim_line_with_eol = lambda ln: _vim.buf[ln] + "\n"

        if sl == el:
            text = _vim_line_with_eol(sl - 1)[sc : ec + 1]
        else:
            text = _vim_line_with_eol(sl - 1)[sc:]
            for cl in range(sl, el - 1):
                text += _vim_line_with_eol(cl)
            text += _vim_line_with_eol(el - 1)[: ec + 1]
        self._text = text
Ejemplo n.º 28
0
 def _track_change(self):
     inserted_char = _vim.eval("v:char")
     try:
         if inserted_char == "":
             before = _vim.buf.line_till_cursor
             if before and before[-1] == self._last_inserted_char:
                 self._try_expand(autotrigger_only=True)
     finally:
         self._last_inserted_char = inserted_char
Ejemplo n.º 29
0
    def cursor_moved(self):
        self._vstate.remember_position()
        if _vim.eval("mode()") not in 'in':
            return

        if self._ignore_movements:
            self._ignore_movements = False
            return

        if self._csnippets:
            cstart = self._csnippets[0].start.line
            cend = self._csnippets[0].end.line + self._vstate.diff_in_buffer_length
            ct = _vim.buf[cstart:cend + 1]
            lt = self._vstate.remembered_buffer
            pos = _vim.buf.cursor

            lt_span = [0, len(lt)]
            ct_span = [0, len(ct)]
            initial_line = cstart

            # Cut down on lines searched for changes. Start from behind and
            # remove all equal lines. Then do the same from the front.
            if lt and ct:
                while (lt[lt_span[1]-1] == ct[ct_span[1]-1] and
                        self._vstate.ppos.line < initial_line + lt_span[1]-1 and pos.line < initial_line + ct_span[1]-1 and
                       (lt_span[0] < lt_span[1]) and
                       (ct_span[0] < ct_span[1])):
                    ct_span[1] -= 1
                    lt_span[1] -= 1
                while (lt_span[0] < lt_span[1] and
                       ct_span[0] < ct_span[1] and
                       lt[lt_span[0]] == ct[ct_span[0]] and
                       self._vstate.ppos.line >= initial_line and pos.line >= initial_line):
                    ct_span[0] += 1
                    lt_span[0] += 1
                    initial_line += 1
            ct_span[0] = max(0, ct_span[0] - 1)
            lt_span[0] = max(0, lt_span[0] - 1)
            initial_line = max(cstart, initial_line - 1)

            lt = lt[lt_span[0]:lt_span[1]]
            ct = ct[ct_span[0]:ct_span[1]]

            try:
                rv, es = guess_edit(initial_line, lt, ct, self._vstate)
                if not rv:
                    lt = '\n'.join(lt)
                    ct = '\n'.join(ct)
                    es = diff(lt, ct, initial_line)
                self._csnippets[0].replay_user_edits(es)
            except IndexError:
                pass # Rather do nothing than throwing an error. It will be correct most of the time

        self._check_if_still_inside_snippet()
        if self._csnippets:
            self._csnippets[0].update_textobjects()
            self._vstate.remember_buffer(self._csnippets[0])
Ejemplo n.º 30
0
def _snippets_dir_is_before_plugin_dir():
    """ Returns True if the snippets directory comes before the plugin
    directory in Vim's runtime path. False otherwise.
    """
    paths = [ os.path.realpath(os.path.expanduser(p)).rstrip(os.path.sep)
        for p in _vim.eval("&runtimepath").split(',') ]
    home = _vim.eval("$HOME")
    def vim_path_index(suffix):
        path = os.path.realpath(os.path.join(home, suffix)).rstrip(os.path.sep)
        try:
            return paths.index(path)
        except ValueError:
            return -1
    try:
        real_vim_path_index = max(vim_path_index(".vim"), vim_path_index("vimfiles"))
        plugin_path_index = paths.index(_plugin_dir())
        return plugin_path_index < real_vim_path_index
    except ValueError:
        return False
Ejemplo n.º 31
0
    def matches(self, before):
        """Returns True if this snippet matches 'before'."""
        # If user supplies both "w" and "i", it should perhaps be an
        # error, but if permitted it seems that "w" should take precedence
        # (since matching at word boundary and within a word == matching at word
        # boundary).
        self._matched = ''

        words = _words_for_line(self._trigger, before)

        if 'r' in self._opts:
            match = self._re_match(before)
        elif 'w' in self._opts:
            words_len = len(self._trigger)
            words_prefix = words[:-words_len]
            words_suffix = words[-words_len:]
            match = (words_suffix == self._trigger)
            if match and words_prefix:
                # Require a word boundary between prefix and suffix.
                boundary_chars = escape(words_prefix[-1:] + words_suffix[:1],
                                        r'\"')
                match = _vim.eval(
                    '"%s" =~# "\\\\v.<."' % boundary_chars) != '0'
        elif 'i' in self._opts:
            match = words.endswith(self._trigger)
        else:
            match = (words == self._trigger)

        # By default, we match the whole trigger
        if match and not self._matched:
            self._matched = self._trigger

        # Ensure the match was on a word boundry if needed
        if 'b' in self._opts and match:
            text_before = before.rstrip()[:-len(self._matched)]
            if text_before.strip(' \t') != '':
                self._matched = ''
                return False

        self._context = None
        if match and self._context_code:
            self._context = self._context_match()
            if not self.context:
                match = False

        return match
Ejemplo n.º 32
0
    def could_match(self, trigger):
        """Return True if this snippet could match the (partial) 'trigger'."""
        self._matched = ''

        # List all on whitespace.
        if trigger and trigger[-1] in (' ', '\t'):
            trigger = ''
        if trigger and trigger.rstrip() is not trigger:
            return False

        words = _words_for_line(self._trigger, trigger)

        if 'r' in self._opts:
            # Test for full match only
            match = self._re_match(trigger)
        elif 'w' in self._opts:
            # Trim non-empty prefix up to word boundary, if present.
            qwords = escape(words, r'\"')
            words_suffix = _vim.eval(
                'substitute("%s", "\\\\v^.+<(.+)", "\\\\1", "")' % qwords)
            match = self._trigger.startswith(words_suffix)
            self._matched = words_suffix

            # TODO: list_snippets() function cannot handle partial-trigger
            # matches yet, so for now fail if we trimmed the prefix.
            if words_suffix != words:
                match = False
        elif 'i' in self._opts:
            # TODO: It is hard to define when a inword snippet could match,
            # therefore we check only for full-word trigger.
            match = self._trigger.startswith(words)
        else:
            match = self._trigger.startswith(words)

        # By default, we match the words from the trigger
        if match and not self._matched:
            self._matched = words

        # Ensure the match was on a word boundry if needed
        if 'b' in self._opts and match:
            text_before = trigger.rstrip()[:-len(self._matched)]
            if text_before.strip(' \t') != '':
                self._matched = ''
                return False

        return match
Ejemplo n.º 33
0
def _ask_user(a, formatted):
    """Asks the user using inputlist() and returns the selected element or
    None."""
    try:
        rv = _vim.eval('inputlist(%s)' % _vim.escape(formatted))
        if rv is None or rv == '0':
            return None
        rv = int(rv)
        if rv > len(a):
            rv = len(a)
        return a[rv - 1]
    except _vim.error:
        # Likely "invalid expression", but might be translated. We have no way
        # of knowing the exact error, therefore, we ignore all errors silently.
        return None
    except KeyboardInterrupt:
        return None
Ejemplo n.º 34
0
    def could_match(self, trigger):
        self._matched = ""

        # List all on whitespace.
        if trigger and trigger[-1] in (" ", "\t"):
            trigger = ""
        if trigger and trigger.rstrip() is not trigger:
            return False

        words = self._words_for_line(trigger)

        if "r" in self._opts:
            # Test for full match only
            match = self._re_match(trigger)
        elif "w" in self._opts:
            # Trim non-empty prefix up to word boundary, if present.
            qwords = words.replace('"', '\\"')
            words_suffix = _vim.eval(
                'substitute("%s", "\\\\v^.+<(.+)", "\\\\1", "")' % qwords)
            match = self._t.startswith(words_suffix)
            self._matched = words_suffix

            # TODO: list_snippets() function cannot handle partial-trigger
            # matches yet, so for now fail if we trimmed the prefix.
            if words_suffix != words:
                match = False
        elif "i" in self._opts:
            # TODO: It is hard to define when a inword snippet could match,
            # therefore we check only for full-word trigger.
            match = self._t.startswith(words)
        else:
            match = self._t.startswith(words)

        # By default, we match the words from the trigger
        if match and not self._matched:
            self._matched = words

        # Ensure the match was on a word boundry if needed
        if "b" in self._opts and match:
            text_before = trigger.rstrip()[:-len(self._matched)]
            if text_before.strip(" \t") != '':
                self._matched = ""
                return False

        return match
Ejemplo n.º 35
0
def snipmate_files_for(ft):
    """Returns all snipMate files we need to look at for 'ft'."""
    if ft == "all":
        ft = "_"
    patterns = [
            "%s.snippets" % ft,
            os.path.join(ft, "*.snippets"),
            os.path.join(ft, "*.snippet"),
            os.path.join(ft, "*/*.snippet"),
    ]
    ret = set()
    for rtp in _vim.eval("&runtimepath").split(','):
        path = os.path.realpath(os.path.expanduser(
                os.path.join(rtp, "snippets")))
        for pattern in patterns:
            for fn in glob.glob(os.path.join(path, pattern)):
                ret.add(fn)
    return ret
Ejemplo n.º 36
0
def snipmate_files_for(ft):
    """Returns all snipMate files we need to look at for 'ft'."""
    if ft == 'all':
        ft = '_'
    patterns = [
        '%s.snippets' % ft,
        os.path.join(ft, '*.snippets'),
        os.path.join(ft, '*.snippet'),
        os.path.join(ft, '*/*.snippet'),
    ]
    ret = set()
    for rtp in _vim.eval('&runtimepath').split(','):
        path = os.path.realpath(
            os.path.expanduser(os.path.join(rtp, 'snippets')))
        for pattern in patterns:
            for fn in glob.glob(os.path.join(path, pattern)):
                ret.add(fn)
    return ret
Ejemplo n.º 37
0
    def _track_change(self):
        self._should_update_textobjects = True

        inserted_char = _vim.eval('v:char')
        try:
            if inserted_char == '':
                before = _vim.buf.line_till_cursor
                if before and before[-1] == self._last_change[0] or \
                        self._last_change[1] != vim.current.window.cursor[0]:
                    self._try_expand(autotrigger_only=True)

        finally:
            self._last_change = (inserted_char, vim.current.window.cursor[0])

        if self._should_reset_visual and self._visual_content.mode == '':
            self._visual_content.reset()

        self._should_reset_visual = True
Ejemplo n.º 38
0
    def _ask_snippets(self, snippets):
        """ Given a list of snippets, ask the user which one they
        want to use, and return it.
        """
        # make a python list
        display = [ as_unicode("%i: %s") % (i+1,s.description) for i,s in enumerate(snippets)]

        try:
            rv = _vim.eval("inputlist(%s)" % _vim.escape(display))
            if rv is None or rv == '0':
                return None
            rv = int(rv)
            if rv > len(snippets):
                rv = len(snippets)
            return snippets[rv-1]
        except _vim.error as e:
            # Likely "invalid expression", but might be translated. We have no way
            # of knowing the exact error, therefore, we ignore all errors silently.
            return None
Ejemplo n.º 39
0
    def _ask_snippets(self, snippets):
        """ Given a list of snippets, ask the user which one they
        want to use, and return it.
        """
        # make a python list
        display = [ as_unicode("%i: %s") % (i+1,s.description) for i,s in enumerate(snippets)]

        try:
            rv = _vim.eval("inputlist(%s)" % _vim.escape(display))
            if rv is None or rv == '0':
                return None
            rv = int(rv)
            if rv > len(snippets):
                rv = len(snippets)
            return snippets[rv-1]
        except _vim.error as e:
            if str(e) == 'invalid expression':
                return None
            raise
Ejemplo n.º 40
0
    def matches(self, trigger):
        """Returns True if this snippet matches 'trigger'."""
        # If user supplies both "w" and "i", it should perhaps be an
        # error, but if permitted it seems that "w" should take precedence
        # (since matching at word boundary and within a word == matching at word
        # boundary).
        self._matched = ""

        # Don't expand on whitespace
        if trigger and trigger.rstrip() != trigger:
            return False

        words = _words_for_line(self._trigger, trigger)

        if "r" in self._opts:
            match = self._re_match(trigger)
        elif "w" in self._opts:
            words_len = len(self._trigger)
            words_prefix = words[:-words_len]
            words_suffix = words[-words_len:]
            match = (words_suffix == self._trigger)
            if match and words_prefix:
                # Require a word boundary between prefix and suffix.
                boundary_chars = escape(words_prefix[-1:] + \
                        words_suffix[:1], r'\"')
                match = _vim.eval(
                    '"%s" =~# "\\\\v.<."' % boundary_chars) != '0'
        elif "i" in self._opts:
            match = words.endswith(self._trigger)
        else:
            match = (words == self._trigger)

        # By default, we match the whole trigger
        if match and not self._matched:
            self._matched = self._trigger

        # Ensure the match was on a word boundry if needed
        if "b" in self._opts and match:
            text_before = trigger.rstrip()[:-len(self._matched)]
            if text_before.strip(" \t") != '':
                self._matched = ""
                return False
        return match
Ejemplo n.º 41
0
    def snippet_sources(self):
        # a snippet source is anything having a .snippets method returning a
        # list of snippets
        list = []

        snippet_files_by_type = _vim.eval('call(g:UltiSnips.SnippetFilesForCurrentExpansion, [&filetype])')

        # allow UltiSnips overriding snipmate : TODO which order is correct?
        for type_ in ["UltiSnips", "snipmate"]:
            if type_ in snippet_files_by_type:
                for file in snippet_files_by_type[type_]:
                    if not file in self.snippet_file_cache:
                        self.snippet_file_cache[file] = SnippetFileCache(file, type_)
                    list.append(self.snippet_file_cache[file])
        # TODO: add additional snippet sources
        # TODO: allow post processing?

        # now if we have errors tell the user by populating quickfix or error list

        return list
Ejemplo n.º 42
0
 def _parse_snippets(self, ft, filename):
     """Parse the 'filename' for the given 'ft'."""
     file_data = compatibility.open_ascii_file(filename, 'r').read()
     self._snippets[ft]  # Make sure the dictionary exists
     for event, data in self._parse_snippet_file(file_data, filename):
         if event == 'error':
             msg, line_index = data
             filename = _vim.eval("""fnamemodify(%s, ":~:.")""" %
                                  _vim.escape(filename))
             raise SnippetSyntaxError(filename, line_index, msg)
         elif event == 'clearsnippets':
             priority, triggers = data
             self._snippets[ft].clear_snippets(priority, triggers)
         elif event == 'extends':
             # TODO(sirver): extends information is more global
             # than one snippet source.
             filetypes, = data
             self.update_extends(ft, filetypes)
         elif event == 'snippet':
             snippet, = data
             self._snippets[ft].add_snippet(snippet)
         else:
             assert False, 'Unhandled %s: %r' % (event, data)
Ejemplo n.º 43
0
    def _update(self, done):
        path = _vim.eval('expand("%")') or ''
        ct = self.current_text
        self._locals.update({
            't': _Tabs(self._parent),
            'fn': os.path.basename(path),
            'path': path,
            'cur': ct,
            'res': ct,
            'snip': self._snip,
        })
        self._snip._reset(ct)  # pylint:disable=protected-access

        for code in self._codes:
            exec(code, self._locals)  # pylint:disable=exec-used

        rv = as_unicode(self._snip.rv if self._snip._rv_changed  # pylint:disable=protected-access
                        else as_unicode(self._locals['res']))

        if ct != rv:
            self.overwrite(rv)
            return False
        return True
Ejemplo n.º 44
0
    def add_buffer_filetypes(self, ft):
        """ Checks for changes in the list of snippet files or the contents
        of the snippet files and reloads them if necessary.
        """
        buf_fts = self._filetypes[_vim.buf.nr]
        idx = -1
        fts = ft.split(".")

        # eruby subfiletype
        if 'eruby' in fts:
            subft = str(_vim.eval('get(b:,"eruby_subtype", "")'))
            if subft != '':
                fts.append(subft)

        for ft in fts:
            ft = ft.strip()
            if not ft: continue
            try:
                idx = buf_fts.index(ft)
            except ValueError:
                self._filetypes[_vim.buf.nr].insert(idx + 1, ft)
                idx += 1

        self._ensure_all_loaded()
Ejemplo n.º 45
0
 def _parse_snippets(self, ft, filename):
     """Parse the 'filename' for the given 'ft' and watch it for changes in
     the future."""
     self._file_hashes[filename] = _hash_file(filename)
     file_data = compatibility.open_ascii_file(filename, "r").read()
     for event, data in self._parse_snippet_file(file_data, filename):
         if event == "error":
             msg, line_index = data
             filename = _vim.eval("""fnamemodify(%s, ":~:.")""" %
                                  _vim.escape(filename))
             raise SnippetSyntaxError(filename, line_index, msg)
         elif event == "clearsnippets":
             priority, triggers = data
             self._snippets[ft].clear_snippets(priority, triggers)
         elif event == "extends":
             # TODO(sirver): extends information is more global
             # than one snippet source.
             filetypes, = data
             self.update_extends(ft, filetypes)
         elif event == "snippet":
             snippet, = data
             self._snippets[ft].add_snippet(snippet)
         else:
             assert False, "Unhandled %s: %r" % (event, data)
Ejemplo n.º 46
0
    def base_snippet_files_for(self, ft, default=True):
        """ Returns a list of snippet files matching the given filetype (ft).
        If default is set to false, it doesn't include shipped files.

        Searches through each path in 'runtimepath' in reverse order,
        in each of these, it searches each directory name listed in
        'g:UltiSnipsSnippetDirectories' in order, then looks for files in these
        directories called 'ft.snippets' or '*_ft.snippets' replacing ft with
        the filetype.
        """

        if _vim.eval("exists('b:UltiSnipsSnippetDirectories')") == "1":
            snippet_dirs = _vim.eval("b:UltiSnipsSnippetDirectories")
        else:
            snippet_dirs = _vim.eval("g:UltiSnipsSnippetDirectories")
        base_snippets = os.path.realpath(
            os.path.join(__file__, "../../../UltiSnips"))
        ret = []

        paths = _vim.eval("&runtimepath").split(',')

        if _vim.eval("exists('g:UltiSnipsDontReverseSearchPath')") == "0" or \
           _vim.eval("g:UltiSnipsDontReverseSearchPath") == "0":
            paths = paths[::-1]

        for rtp in paths:
            for snippet_dir in snippet_dirs:
                pth = os.path.realpath(
                    os.path.expanduser(os.path.join(rtp, snippet_dir)))

                patterns = [
                    "%s.snippets", "%s_*.snippets",
                    os.path.join("%s", "*")
                ]
                if not default and pth == base_snippets:
                    patterns.remove("%s.snippets")

                for pattern in patterns:
                    for fn in glob.glob(os.path.join(pth, pattern % ft)):
                        if fn not in ret:
                            ret.append(fn)

        return ret
Ejemplo n.º 47
0
 def __init__(self):
     pos = _vim.buf.cursor
     self._mode = _vim.eval('mode()')
     Position.__init__(self, pos.line, pos.col)
Ejemplo n.º 48
0
    def _cursor_moved(self):
        """Called whenever the cursor moved."""
        self._should_update_textobjects = False

        if not self._csnippets and self._inner_state_up:
            self._teardown_inner_state()
        self._vstate.remember_position()
        if _vim.eval('mode()') not in 'in':
            return


        if self._ignore_movements:
            self._ignore_movements = False
            return

        if self._csnippets:
            cstart = self._csnippets[0].start.line
            cend = self._csnippets[0].end.line + \
                self._vstate.diff_in_buffer_length
            ct = _vim.buf[cstart:cend + 1]
            lt = self._vstate.remembered_buffer
            pos = _vim.buf.cursor

            lt_span = [0, len(lt)]
            ct_span = [0, len(ct)]
            initial_line = cstart

            # Cut down on lines searched for changes. Start from behind and
            # remove all equal lines. Then do the same from the front.
            if lt and ct:
                while (lt[lt_span[1] - 1] == ct[ct_span[1] - 1] and
                        self._vstate.ppos.line < initial_line + lt_span[1] - 1 and
                        pos.line < initial_line + ct_span[1] - 1 and
                        (lt_span[0] < lt_span[1]) and
                        (ct_span[0] < ct_span[1])):
                    ct_span[1] -= 1
                    lt_span[1] -= 1
                while (lt_span[0] < lt_span[1] and
                       ct_span[0] < ct_span[1] and
                       lt[lt_span[0]] == ct[ct_span[0]] and
                       self._vstate.ppos.line >= initial_line and
                       pos.line >= initial_line):
                    ct_span[0] += 1
                    lt_span[0] += 1
                    initial_line += 1
            ct_span[0] = max(0, ct_span[0] - 1)
            lt_span[0] = max(0, lt_span[0] - 1)
            initial_line = max(cstart, initial_line - 1)

            lt = lt[lt_span[0]:lt_span[1]]
            ct = ct[ct_span[0]:ct_span[1]]

            try:
                rv, es = guess_edit(initial_line, lt, ct, self._vstate)
                if not rv:
                    lt = '\n'.join(lt)
                    ct = '\n'.join(ct)
                    es = diff(lt, ct, initial_line)
                self._csnippets[0].replay_user_edits(es, self._ctab)
            except IndexError:
                # Rather do nothing than throwing an error. It will be correct
                # most of the time
                pass

        self._check_if_still_inside_snippet()
        if self._csnippets:
            self._csnippets[0].update_textobjects()
            self._vstate.remember_buffer(self._csnippets[0])
Ejemplo n.º 49
0
def guess_edit(initial_line, last_text, current_text, vim_state):
    """
    Try to guess what the user might have done by heuristically looking at
    cursor movement, number of changed lines and if they got longer or shorter.
    This will detect most simple movements like insertion, deletion of a line
    or carriage return. 'initial_text' is the index of where the comparison
    starts, 'last_text' is the last text of the snippet, 'current_text' is the
    current text of the snippet and 'vim_state' is the cached vim state.

    Returns (True, edit_cmds) when the edit could be guessed, (False, None)
    otherwise.
    """
    if not len(last_text) and not len(current_text):
        return True, ()
    pos = vim_state.pos
    ppos = vim_state.ppos

    # All text deleted?
    if (len(last_text) and (not current_text or
                            (len(current_text) == 1 and not current_text[0]))):
        es = []
        if not current_text:
            current_text = ['']
        for i in last_text:
            es.append(("D", initial_line, 0, i))
            es.append(("D", initial_line, 0, "\n"))
        es.pop()  # Remove final \n because it is not really removed
        if is_complete_edit(initial_line, last_text, current_text, es):
            return True, es
    if ppos.mode == 'v':  # Maybe selectmode?
        sv = list(map(int, _vim.eval("""getpos("'<")""")))
        sv = Position(sv[1] - 1, sv[2] - 1)
        ev = list(map(int, _vim.eval("""getpos("'>")""")))
        ev = Position(ev[1] - 1, ev[2] - 1)
        if "exclusive" in _vim.eval("&selection"):
            ppos.col -= 1  # We want to be inclusive, sorry.
            ev.col -= 1
        es = []
        if sv.line == ev.line:
            es.append(("D", sv.line, sv.col,
                       last_text[sv.line - initial_line][sv.col:ev.col + 1]))
            if sv != pos and sv.line == pos.line:
                es.append(
                    ("I", sv.line, sv.col,
                     current_text[sv.line - initial_line][sv.col:pos.col + 1]))
        if is_complete_edit(initial_line, last_text, current_text, es):
            return True, es
    if pos.line == ppos.line:
        if len(last_text) == len(current_text):  # Movement only in one line
            llen = len(last_text[ppos.line - initial_line])
            clen = len(current_text[pos.line - initial_line])
            if ppos < pos and clen > llen:  # maybe only chars have been added
                es = (("I", ppos.line, ppos.col,
                       current_text[ppos.line -
                                    initial_line][ppos.col:pos.col]), )
                if is_complete_edit(initial_line, last_text, current_text, es):
                    return True, es
            if clen < llen:
                if ppos == pos:  # 'x' or DEL or dt or something
                    es = (("D", pos.line, pos.col,
                           last_text[ppos.line -
                                     initial_line][ppos.col:ppos.col +
                                                   (llen - clen)]), )
                    if is_complete_edit(initial_line, last_text, current_text,
                                        es):
                        return True, es
                if pos < ppos:  # Backspacing or dT dF?
                    es = (("D", pos.line, pos.col,
                           last_text[pos.line - initial_line][pos.col:pos.col +
                                                              llen - clen]), )
                    if is_complete_edit(initial_line, last_text, current_text,
                                        es):
                        return True, es
        elif len(current_text) < len(last_text):
            # where some lines deleted? (dd or so)
            es = []
            for i in range(len(last_text) - len(current_text)):
                es.append(
                    ("D", pos.line, 0, last_text[pos.line - initial_line + i]))
                es.append(("D", pos.line, 0, '\n'))
            if is_complete_edit(initial_line, last_text, current_text, es):
                return True, es
    else:
        # Movement in more than one line
        if ppos.line + 1 == pos.line and pos.col == 0:  # Carriage return?
            es = (("I", ppos.line, ppos.col, "\n"), )
            if is_complete_edit(initial_line, last_text, current_text, es):
                return True, es
    return False, None
Ejemplo n.º 50
0
 def basename(self):
     """ The filename without extension. """
     return _vim.eval('expand("%:t:r")') or ""
Ejemplo n.º 51
0
 def path(self):
     """The path to the file"""
     return _vim.eval('expand("%")') or ''
Ejemplo n.º 52
0
    def _filetypes(self, dotft=None):
        if dotft is None:
            dotft = _vim.eval("&filetype")

        fts = dotft.split(".") + [ "all" ]
        return [ft for ft in fts[::-1] if ft]
Ejemplo n.º 53
0
 def fn(self):
     """ The filename. """
     return _vim.eval('expand("%:t")') or ""
Ejemplo n.º 54
0
 def basename(self):  # pylint:disable=no-self-use
     """The filename without extension."""
     return _vim.eval('expand("%:t:r")') or ''
Ejemplo n.º 55
0
 def reset(self):
     """ Gets the spacing properties from Vim. """
     self.sw = int(_vim.eval("&sw"))
     self.sts = int(_vim.eval("&sts"))
     self.et = (_vim.eval("&expandtab") == "1")
     self.ts = int(_vim.eval("&ts"))
Ejemplo n.º 56
0
 def fn(self):  # pylint:disable=no-self-use,invalid-name
     """The filename."""
     return _vim.eval('expand("%:t")') or ''
Ejemplo n.º 57
0
 def __init__(self):
     pos = _vim.buf.cursor
     self._mode = _vim.eval("mode()")
     self._visualmode = _vim.eval("visualmode()")
     Position.__init__(self, pos.line, pos.col)
Ejemplo n.º 58
0
 def _error(self, msg):
     fn = _vim.eval("""fnamemodify(%s, ":~:.")""" % _vim.escape(self._fn))
     self._sm._error("%s in %s(%d)" % (msg, fn, self._idx + 1))
Ejemplo n.º 59
0
 def reset(self):
     """ Gets the spacing properties from Vim. """
     self.shiftwidth = int(
         _vim.eval("exists('*shiftwidth') ? shiftwidth() : &shiftwidth"))
     self._expandtab = (_vim.eval("&expandtab") == "1")
     self._tabstop = int(_vim.eval("&tabstop"))
Ejemplo n.º 60
0
 def _update(self, done, not_done):
     self.overwrite(_vim.eval(self._code))
     return True