问题
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