Vim:创建一个移动的自定义命令

时间:2017-02-24 12:34:38

标签: vim

我经常将文本行转换为数组。例如,这个:

Monday
Tuesday
Wednesday

变为:

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

我可以制作一张地图,更改其中一行(例如Monday'Monday',),如下所示:

:nnoremap gsa ^i'<Esc>A,

我想要做的是让该命令采用移动或文本对象,以便我可以像gsaipgsip3j那样执行它。

我该如何做到这一点?

4 个答案:

答案 0 :(得分:3)

您可以'operatorfunc'g@一起使用带有地图的地图 运动。帮助给出了完整的解释和示例 :map-operator主题。基本上你设置你想要的功能 在您的地图中调用并使用g@。 Vim将等待一个动作然后设置 标记'[']并调用您的函数。

在你的功能中,你可以发挥创意,在这里我只是做了一个快速 如何将此原则应用于您所需的示例。

: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

答案 1 :(得分:1)

将其放入.vimrc文件中:

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

选择所需的可视线条,例如vip,然后按gsa

答案 2 :(得分:0)

准确地说,您似乎希望将映射应用于动画或文本对象所涵盖的每条线。

您可以通过可视模式建立此类范围vipv2j。然后,您可以使用:normal gsa(键入;如果从可视模式进入命令行模式,Vim会自动插入所选范围(:'<,'>),以将自定义映射应用于每个行(光标)根据{{​​1}})列在每一行的第一列。

答案 3 :(得分:0)

如果你真的想在最后一个项目之后添加一个逗号,我会这样做,以便保持寄存器不变。

function! s:to_list() range abort
  let words = getline(a:firstline, a:lastline)
  exe a:firstline.','.a:lastline.'d _' " remove the "_" to fill the unnamed register
  let lines = ['['] + map(words, '"  ".string(v:val).","') + [']']
  call append(a:firstline-1, lines)
endfunction

command! -nargs=0 -range=% ToList <line1>,<line2>call s:to_list()

为了摆脱最后两行,我已编辑map()结果的最后一项或使用join()

  let lines = "[\n" . join(map(words, '"  ".string(v:val)'), ",\n") . "\n]"
  put!=lines