6

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?

ib.
  • 27,830
  • 11
  • 80
  • 100
simplfuzz
  • 12,479
  • 24
  • 84
  • 137

2 Answers2

8

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.

Prince Goulash
  • 15,295
  • 2
  • 46
  • 47
  • Amazing! That's all I can say. Still I am greedy/lazy enough to ask you for more. If there are more than one possible expansions : e.g. myCamelCase myCamelCart, the last one is chosen. Instead, can it be made to behave like Ctrl-P keyword completion in vim? Again, Amazing! – simplfuzz Jul 04 '11 at 06:29
  • I'm glad it worked! Handling multiple matches should just be a matter of getting Expand_Camel_Initials() to return a list of solutions and then setting the `completefunc` to let you choose between then. I'll try and have a look at it later this week. – Prince Goulash Jul 04 '11 at 07:13
  • Okay, it wasn't as painful as I thought... I have edited my answer and it should now work as you wish. Let me know if you have any problems (I haven't had a chance to test it properly). – Prince Goulash Jul 04 '11 at 08:04
  • Sorry I missed this comment. I will give it a try and feed you back. Is there a way to get notified for the comments? – simplfuzz Jul 21 '11 at 09:13
0

There is a plugin for this in Vim called vim-abolish. Use the map crc to expand to camel case.

adelarsq
  • 3,718
  • 4
  • 37
  • 47