Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vim: Create custom command that takes a movement

Tags:

vim

I often transform lines of texts to arrays. For example, this:

Monday
Tuesday
Wednesday

Becomes:

[
  'Monday',
  'Tuesday',
  'Wednesday',
]

I can make a map that changes one of the lines (e.g. Monday to 'Monday',) like so:

:nnoremap gsa ^i'<Esc>A,

What I'd like to do is have that command take a movement or a text object so that I can execute it like gsaip or gsip3j.

How can I accomplish this?

like image 869
sdeleon28 Avatar asked Feb 24 '17 12:02

sdeleon28


2 Answers

You can use 'operatorfunc' with g@ to have a map with a motion. The help gives a full explanation and example under the :map-operator topic. Basically you set the function you want to call in your map and use g@. Vim will wait to a motion and then set the marks '[ and '] and call your function.

Inside your function you can go creative, here I just made a quick example of how you could apply this principle to what you need.

:nnoremap <silent> gsa :set opfunc=TransformToArray<cr>g@

function! TransformToArray(type)
  if a:type == 'line'
    let s=line("'[") " saving beginning mark
    ']s/\(\s*\).*\zs/\r\1]
    exec s ",']-1s/\\s*\\zs.*/  '&',"
    exec s 's/\(\s*\)\zs\ze  /[\r\1'
  elseif a:type == 'char'
    " ...
  endif
endfunction
like image 70
sidyll Avatar answered Nov 04 '22 20:11

sidyll


Put this into your .vimrc file :

vnoremap <silent> gsa :call Brackets()<CR>

function! Brackets()
    execute "normal! I'"
    if line(".") == a:lastline
        execute "normal! A'\<cr>]"
        execute a:firstline."s:^:[\r:" 
    else
        execute "normal! A',"
    endif
endfunction

Select the visual-line block you want for example vip and then press gsa.

like image 39
Meninx - メネンックス Avatar answered Nov 04 '22 19:11

Meninx - メネンックス