1

I have several lines in my code. I am aware that Ctrl+x,Ctrl+l shows suggestions for completing a line, based on the similar lines available in the script.

Now, I want only the part of a line, delimited by a character, to be shown as suggestions.

Example:

   Print "Verifying the contents again";
   .
   .
   .
   Print "Verifying the output to be shown"; // line 2

When I type "Verify", it has to show the remaining part of string in the quotes as suggestion. So, both the lines should be shown.

  • 1
    This can't be done without some kind of plugin. Did you try vim.org? – romainl May 5 '16 at 8:01
  • Not yet. I will try – SibiCoder May 5 '16 at 8:06
2

It wasn't tested very long and it doesn't take into account the fact that the group of words may be on several lines, but you could try the following code:

set completefunc=CompleteInsideSymbols

function! CompleteInsideSymbols(findstart, base) abort
    if a:findstart
        return searchpos('["''[]', 'bc', line('.'))[1] - 1
    else
        let groups_of_words = []
        sil! %s/\v(".{-1,}"|'.{-1,}'|\[.{-1,}\])/\=add(groups_of_words,submatch(0))/gn
        return filter(groups_of_words, 'v:val =~ "^" . a:base')
    endif
endfunction

It defines a custom completion function which is triggered when you hit <C-X><C-U>.

The behavior of such a function is described in :h complete-functions. Basically, when you hit the mapping once, the function whose name is defined by the option 'completefunc' is called twice, consecutively, each time with 2 arguments.

The 1st time, Vim gives to the function the arguments 1 and '' (empty string).
The 2nd time, it gives the arguments 0 and the text you want to complete.

Inside your function, you can call the 2 arguments however you like, but in the help they use findstart and base.

When you write the function, you have to wrap the whole code inside an if/else/endif block which tests the value of findstart:

  • if it's 1, the function must return the byte index of the first character of the text you want to complete ;
  • if it's 0, it must return the suggestions you want to see in the popup menu

The autocompletion function CompleteInsideSymbols() is built around such a block:

if a:findstart
    ...
else
    ...
endif

Here's what the function does when it's called for the 1st time:

    return searchpos('["''[]', 'bcn', line('.'))[1] - 1

It returns the byte index (byte index = column number - 1) of the previous single quote, double quote, or opening bracket before the cursor.

searchpos() is a function which returns the line and column numbers of the next or previous occurrence of a pattern.

You can pass 3 arguments to searchpos():

  1. a pattern
  2. some flags which change the behavior of the search
  3. a stopline which is the number of a line beyond which the search must stop

Here the pattern is ["''[] which matches a double quote, a single quote or an opening bracket.

Since the pattern is already surrounded by single quotes, the single quote it contains must be doubled. Besides, the opening and closing brackets are here to group the 3 characters as a collection (see :h /[]).

The flags are bc which respectively mean look backward and accept a match at current cursor position.

Finally, the stopline is line('.') which is the current line number and means that searchpos() won't look beyond the current line.


Here's what CompleteInsideSymbols() does when it's automatically called the 2nd time:

    let groups_of_words = []

Initialize an empty list inside the variable groups_of_words whose purpose will be to contain all the groups of words which are inside double quotes, single quotes, or brackets.

    sil! %s/\v(".{-1,}"|'.{-1,}'|\[.{-1,}\])/\=add(groups_of_words,submatch(0))/gn

Call the substitution command :s to look for the pattern \v(".{-1,}"|'.{-1,}'|\[.{-1,}\]) which should match all the groups of words which are surrounded by quotes and brackets.

The pattern contains the non-greedy multi {-1,}, which allows you to repeat the previous atom 1 or more times, as few as possible.

Whenever this pattern is found, :s evaluates the expression add(groups_of_words, submatch(0)) (see :h sub-replace-expression and :h submatch() for more information on this).
As a result of this evaluation, the group of words is added as an item of the list groups_of_words, but no substitution is made thanks to the n flag (see :h :s_flags).

    return filter(groups_of_words, 'v:val =~ "^" . a:base')

Return the groups of words whose beginning match the text you want to complete.

|improve this answer|||||
2

There is a plugin named StringComplete.vim in Github. It shows all the quoted strings in the current file as suggestions.

If you would have typed part of string and press Ctrl-j, it will show the suggestions based on it. If nothing is typed and Ctrl+j is pressed, it will show all quoted strings.

Works well for single line strings in single or double quotes.

The plugin can be customized for words within brackets like (,{,[,< also.

|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.