Example #1
0
    def ComputeCandidatesInner(self, request_data):
        if not self._omnifunc:
            return []

        # Calling directly the omnifunc may move the cursor position. This is the
        # case with the default Vim omnifunc for C-family languages
        # (ccomplete#Complete) which calls searchdecl to find a declaration. This
        # function is supposed to move the cursor to the found declaration but it
        # doesn't when called through the omni completion mapping (CTRL-X CTRL-O).
        # So, we restore the cursor position after the omnifunc calls.
        line, column = vimsupport.CurrentLineAndColumn()

        try:
            start_column = vimsupport.GetIntValue(self._omnifunc + '(1,"")')
            if start_column < 0:
                # FIXME: Technically, if the returned value is -1 we should raise an
                # error.
                return []

            # Use the start column calculated by the omnifunc, rather than our own
            # interpretation. This is important for certain languages where our
            # identifier detection is either incorrect or not compatible with the
            # behaviour of the omnifunc. Note: do this before calling the omnifunc
            # because it affects the value returned by 'query'.
            request_data['start_column'] = start_column + 1

            # Vim internally moves the cursor to the start column before calling again
            # the omnifunc. Some omnifuncs like the one defined by the
            # LanguageClient-neovim plugin depend on this behavior to compute the list
            # of candidates.
            vimsupport.SetCurrentLineAndColumn(line, start_column)

            omnifunc_call = [
                self._omnifunc, "(0,'",
                vimsupport.EscapeForVim(request_data['query']), "')"
            ]
            items = vim.eval(''.join(omnifunc_call))

            if isinstance(items, dict) and 'words' in items:
                items = items['words']

            if not hasattr(items, '__iter__'):
                raise TypeError(OMNIFUNC_NOT_LIST)

            return list(filter(bool, items))

        except (TypeError, ValueError, vim.error) as error:
            vimsupport.PostVimMessage(OMNIFUNC_RETURNED_BAD_VALUE + ' ' +
                                      str(error))
            return []

        finally:
            vimsupport.SetCurrentLineAndColumn(line, column)
Example #2
0
 def Omnifunc(findstart, base):
     vimsupport.SetCurrentLineAndColumn(0, 0)
     if findstart:
         return 5
     return ['length']
Example #3
0
    def ComputeCandidatesInner(self, request_data):
        if not self._omnifunc:
            return []

        # Calling directly the omnifunc may move the cursor position. This is the
        # case with the default Vim omnifunc for C-family languages
        # (ccomplete#Complete) which calls searchdecl to find a declaration. This
        # function is supposed to move the cursor to the found declaration but it
        # doesn't when called through the omni completion mapping (CTRL-X CTRL-O).
        # So, we restore the cursor position after the omnifunc calls.
        line, column = vimsupport.CurrentLineAndColumn()

        try:
            start_column = vimsupport.GetIntValue(self._omnifunc + '(1,"")')

            # Vim only stops completion if the value returned by the omnifunc is -3 or
            # -2. In other cases, if the value is negative or greater than the current
            # column, the start column is set to the current column; otherwise, the
            # value is used as the start column.
            if start_column in (-3, -2):
                return []
            if start_column < 0 or start_column > column:
                start_column = column

            # Use the start column calculated by the omnifunc, rather than our own
            # interpretation. This is important for certain languages where our
            # identifier detection is either incorrect or not compatible with the
            # behaviour of the omnifunc. Note: do this before calling the omnifunc
            # because it affects the value returned by 'query'.
            request_data['start_column'] = start_column + 1

            # Vim internally moves the cursor to the start column before calling again
            # the omnifunc. Some omnifuncs like the one defined by the
            # LanguageClient-neovim plugin depend on this behavior to compute the list
            # of candidates.
            vimsupport.SetCurrentLineAndColumn(line, start_column)

            omnifunc_call = [
                self._omnifunc, "(0,'",
                vimsupport.EscapeForVim(request_data['query']), "')"
            ]
            items = vim.eval(''.join(omnifunc_call))

            if isinstance(items, dict) and 'words' in items:
                items = items['words']

            if not hasattr(items, '__iter__'):
                raise TypeError(OMNIFUNC_NOT_LIST)

            # Vim allows each item of the list to be either a string or a dictionary
            # but ycmd only supports lists where items are all strings or all
            # dictionaries. Convert all strings into dictionaries.
            for index, item in enumerate(items):
                if not isinstance(item, dict):
                    items[index] = {'word': item}

            return items

        except (TypeError, ValueError, vim.error) as error:
            vimsupport.PostVimMessage(OMNIFUNC_RETURNED_BAD_VALUE + ' ' +
                                      str(error))
            return []

        finally:
            vimsupport.SetCurrentLineAndColumn(line, column)