vim call a function from inside a vmap

前端 未结 1 1184
北恋
北恋 2020-12-21 11:07

I have created a vmap text object for selecting the text of a single LaTeX \\item:

vmap im ?\\\\itemo/\\\\item\\\\|\\\\end{itemize}b$


        
相关标签:
1条回答
  • 2020-12-21 11:27

    I've used the doc on operatorfunc to come up with the following, which should be (close to) what you want1:

    function! ItemizeTextObject(type, ...)
        let sel_save = &selection
        let &selection = "inclusive"
        let reg_save = @@
    
        if a:0  " Invoked from Visual mode, use '< and '> marks.
            silent! 1,+1?\\item
            norm v | " use V for linewise visual mode
            "" use V for linewise visual mode:
            "norm V
            silent! /\\item\|\\end{itemize}
        "elseif a:type == 'line'
        "elseif a:type == 'block'
        else
           silent! 1,+1?\\item
           norm v
           silent! /\\item
        endif
    
        norm b$
    
        let &selection = sel_save
        let @@ = reg_save
    endfunction
    
    silent! unmap in
    
    xnoremap <silent> in :<C-U>call ItemizeTextObject(visualmode(), 1)<CR>
    

    If you want the mapping in both visual and select modes, you should use vnoremap

    Notes of things to address:

    • you can now implement the motion from another mode (fill in the branches in the function)
    • if wrapscan is on, no search should wrap (perhaps temporarily set nowrapscan?)
    • you might want to make the operator repeating so you can extend the selection by saying vininin (see https://stackoverflow.com/a/7292271/85371 for an example)
    • it looks like you want 'linewise' behaviour (due to b$?)
      • consider using norm V (see comment)

    Edit I compared the behaviour with this simple mapping:

    xnoremap <silent>in ?\\item<CR>o/\\item\\|\\end{itemize}<CR>b$
    

    1 Disclaimer: I don't know LateX

    0 讨论(0)
提交回复
热议问题