Creating a list or tuple out of one word-per-line in vim

限于喜欢 提交于 2020-06-17 09:34:09

问题


I come across the following pattern quite frequently, where I have to copy-paste a bunch of items (usually in excel) into something like a SQL query and often the simplest way to do this is copy-paste the data into vim and then run a macro/command on it to format it. Here is an example of input data:

This involves three steps for me:

  • Delete empty lines: :g!/\S/d
  • Add quotes around it and a , separator: :% s/\v(\S+)/"\1",
  • Put it onto one line and add a wrapping [...] or (...): ggVG (select all), J (condense-all), 0i(CTRL-o$)

Is there a way I can put all this into a function or macro, or what's the best way that I could take the above input and enter some keyboard shortcut, such as s and it formats everything in the above way?

While it might seem overkill, this is something that I can do pretty easily and quickly (without really thinking) in an editor like TextMate where I can use a multi-cursor.


回答1:


So what's the problem? Put this stuff into your vimrc and you're done.

function s:do_stuff() abort
    %join
    s/\S\+/"&",/g
    s/^/(
    s/$/)
endfunction

nnoremap <silent><leader>s :call <SID>do_stuff()<CR>



回答2:


My initial reflex is to start with

echo '['.join(map(filter(getline(1, '$'), '!empty(v:val)'), 'string(v:val)'),', ').']'

Which can be turned into

%d
call append(line('.')-1, '['.join(map(filter(getreg('"', 1, 1), '!empty(v:val)'), '"\"".v:val."\""'),', ').']')

And thus into the command

command! -range=% ToTuple 
\ <line1>,<line2>d
\|call append(<line1>-1, '['.join(map(filter(getreg('"', 1, 1), '!empty(v:val)'), '"\"".v:val."\""'),', ').']')

Note that

echo string(filter(getreg('"', 1, 1), '!empty(v:val)')

Would be much simpler, but then single-quotes would be used instead of double-quotes -- it may make a big difference with some languages.




回答3:


I figured another option:

:%s/\v(\w+)\n+/"\1",/g | norm $x | exec "norm! I(\<Esc>A)"

As a command line option:

vim -c ':%s/\v(\w+)\n+/"\1",/g | norm $x | s/.*/(&)/g' -c wq target.txt

-c ........... vim command line (interactive shell)
\v ........... very magic (simple regex system)
\w+ .......... one or more words per line
\n+ .......... one or more line breaks 
() ........... regex group
\1 ........... repeat the first regex group
normal $x .... deletes the last character of the remaining single line

Once I am using only the words \w+ inside the regex group, the line breaks are ignored in the substitution. In the last substitution we dont need more % because at this point we have a single line.



来源:https://stackoverflow.com/questions/62069376/creating-a-list-or-tuple-out-of-one-word-per-line-in-vim

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!