Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CamelCase Expansion in Vim like Intellij Idea?

In Intellij Idea, there's a feature. Let's say I have used a variable myCamelCase somewhere in my code. Then if I type mCC and press Ctrl-Enter or some such key combination, it expands to myCamelCase. Is there something similar in Vim?

like image 962
simplfuzz Avatar asked Jul 01 '11 13:07

simplfuzz


1 Answers

Okay, forgive me for answering twice, but since my first attempt missed the point, I'll have another go. This is more complicated than I thought, but possibly not as complicated as I have made it (!).

This is now modified to suggest all matching variable names.

First of all, here's a function to generate the 'mCC' abbreviation from the 'myCamelCase' string:

function! Camel_Initials(camel)
    let first_char = matchstr(a:camel,"^.")
    let other_char = substitute(a:camel,"\\U","","g")
    return first_char . other_char
endfunction

Now, here's a function that takes an abbreviation ('mCC') and scans the current buffer (backwards from the current line) for "words" that have this abbreviation. A list of all matches is returned:

function! Expand_Camel_Initials(abbrev)
    let winview=winsaveview()
    let candidate=a:abbrev
    let matches=[]
    try
        let resline = line(".")
        while resline >= 1
            let sstr = '\<' . matchstr(a:abbrev,"^.") . '[a-zA-Z]*\>'
            keepjumps let resline=search(sstr,"bW")
            let candidate=expand("<cword>")
            if candidate != a:abbrev && Camel_Initials(candidate) == a:abbrev
                call add( matches, candidate )
            endif
        endwhile
    finally
        call winrestview(winview)
        if len(matches) == 0
            echo "No expansion found"
        endif
        return sort(candidate)
    endtry
endfunction

Next, here's a custom-completion function that reads the word under the cursor and suggests the matches returned by the above functions:

function! Camel_Complete( findstart, base )
    if a:findstart
        let line = getline('.')
        let start = col('.') - 1
        while start > 0 && line[start - 1] =~ '[A-Za-z_]'
            let start -= 1
        endwhile
        return start
    else
        return Expand_Camel_Initials( a:base )
    endif
endfunction

To make use of this, you must define the "completefunc":

setlocal completefunc=Camel_Complete

To use insert-mode completion, type CTRL-X CTRL-U, but I usually map this to CTRL-L:

inoremap <c-l> <c-x><c-u>

With this code in your vimrc you should find that typing mCC followed by CTRL-L will make the expected replacement. If no matching expansion is found, the abbreviation is unchanged.

The code isn't water-tight, but it works in all the simple cases I tested. Hope it helps. Let me know if anything needs elucidating.

like image 152
Prince Goulash Avatar answered Sep 30 '22 03:09

Prince Goulash