开发者

Discarding count in <expr> mappings

For example, I have the following expression mapping:

    function! DelNthSpace()
        let col=match(getline('.'), '[[:blank:] ]', col('.'), v:count1)
        return virtcol([line('.'), col+1])."|s \e"
    endfunction
    nnoremap  s DelNthSpace()
You see, v:count1 is already handled here. But if I try to replace second space with such function that is located, for example, at virtual column 35 (it will be if you place cursor on the return statement), then this tries to go to column 235 and replace it because this will be transformed from 2s to 2{DelNthSpace()} -> 235|s ^[. Now I am prepending bare useless | at the start of return statement which consumes unneeded count, but I do not like this solution as it uses two movements instead of one.

UPDATE: I should have provided 开发者_开发百科more context:

function! ToNthSpace()
    let col=match(getline('.'), '[[:blank:] ]', col('.'), v:count1)
    return virtcol([line('.'), col+1])."|"
endfunction
noremap <expr> s ToNthSpace()

There are a bunch of functions that are using these, one imitates replace command, but transliterates its argument (so, while calling r$ii will replace character with $ and insert i, \tr$ii will replace character with , same relation between t and \tt and some others), others are motions. As these functions define motions, I can't use :<C-u>, it will leave visual mode (or I will have to add a hack which will tell from which mode function was called). I do not know this hack and I can't define different mappings for normal and visual modes.


There is no way to make vim ignore the count for the <expr> mapping, however you can easily change your mapping to make your function work:

nnoremap s :<C-U>exe 'normal!' DelNthSpace()<CR>

See :help v:count for info about using CTRL+U to erase the count.


To summarize what is mentioned by @Alexey and also my test on operator-pending mode, you can do the following

nnoremap <expr> s "@_" . ToNthSpace()
vnoremap <expr> s "@_" . ToNthSpace()
onoremap <expr> s printf(":normal %s\<cr>", ToNthSpace())

Then the 2 already typed in your example will have no effect

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜