I'm trying to define an insert mapping like this:

inoremap <expr><buffer>  ; (Test(expand('<cWORD>'))).";"

in which the Test function is defined as:

func! Test(a)
    echom "cword: "."\"".a:a."\""

For example, if the current position of the cursor is like:


When I type ;, I'm expecting a message says: cword: "apple",

But currently, I can only get an empty result like: cword: ""

The question is, why the expand() function here always returns an empty string?

  • I'm using gvim version 8.0 – wangkaibule Aug 28 '18 at 2:42
  • in insert mode the cursor is really located here: apple[ ]. so it's not over the word at all. – Mass Aug 28 '18 at 2:53
  • @Mass Oh, okay then. So there's a specific way to retrieve the word "before" the cursor? Or I need to manually split the word from getline(.)? – wangkaibule Aug 28 '18 at 2:58
  • if you leave insert mode, the cursor should be on the last letter and then cword should be valid again. – Christian Brabandt Aug 28 '18 at 7:03

As others have said, if you stay in insert mode, the cursor will be one character too far for expand('<cword>') to return anything useful.

That's why a long time ago I wrote these functions, now part of lh-vim-lib. Typically you'd be interested in

function! lh#ui#GetCurrentWord()
  let c = col ('.')-1
  let l = line('.')
  let ll = getline(l)
  let ll1 = strpart(ll,0,c)
  let ll1 = matchstr(ll1,'\S*$')
  if strlen(ll1) == 0
    return ll1
    let ll2 = strpart(ll,c,strlen(ll)-c+1)
    let ll2 = strpart(ll2,0,match(ll2,'$\|\s'))
    return ll1.ll2

The code is quite old and could be simplified.

| improve this answer | |
  • I accidentally downvoted it and cannot undo... – Liu Sha Nov 23 '18 at 10:19
  • The variable names are confusing at best, incidentally. – D. Ben Knoble Dec 23 '18 at 1:54

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.