vim: Join all lines in paragraph
I'm trying without success to join all lines in a paragraph (block of text) using a vimscript.
I want to do this for every paragraph (block of text) and want to keep the empty lines between them. (I don't want to use macros)When I use the }w
command to go to the first word in the next paragraph I noted that it does not recognize empty lines with spaces or multiple empty lines between paragraphs.
That's not what I want.
So I tried this:
do a search:\(^.*\S\+.*\n\)\{2,}
do:
normal vipgJ
do above search again etc.
It works fine when I do it manually, but I can't put this in a script.
I tried this:
function! <SID>JoinParagraphs()
let i = 1
normal gg
while i <= 200
call search("\\(^.*\\S\\+.*\\n\\)\\{2,})", "")
normal vipgJ
let i=i+1
endwhile
endfunction
Doesn't work...
I tried als开发者_运维知识库o to change the linecall search...
for
let @/ = "\\(^.*\\S\\+.*\\n\\)\\{2,})"
but that does a Join of all lines together (doesn't keep the empty lines).
What did I do wrong?
Just found this answer
:set tw=1000000
gggqG
Which is the absolute winner IMHO.
It executes gq
on the motion from gg
(start) to G
(end of document), using a textwidth of 1000000.
Replace all newlines followed by something other than a newline with the second matched character:
:%s/\(\S\)\n\(\S\)/\1 \2/
Another approach:
:%s/\n\([^\n]\)/\1/
Click: Pragmatic approach added
much underrated command mode and :global
Update Fixed after a correct comment. It happened with whitespace-only lines containing Tab-character(s)... sry bout that.
:g#\v[^\s\t]#normal vipJ
How does that work for you? (perhaps replacing vipJ
-> vipgJ
if you like)
Update Here is one that not uses normal mode (inspired by Peter's comment)
The big benefit is that it reuses the same pattern in negative and positive sense; That way it can be genericized to
:let @/='\v^\s*$'
:v//.,//-1 join
Now the second line shows the simplicity of the this approach (for every nonmatching line, join up until the next matching line). The best thing is that you can use any odd search pattern instead
Of course you could write this particular task as one line, but it wouldn't quite be as elegant:
:v#\v^\s*$#.,//-1 join
Another approach that has been around since Berkeley UNIX, before vim existed... If you're on a linux/unix system, you can invoke the fmt command like so:
:%!fmt -w 9999
That will do it on the whole file, which might screw up stuff like numbered lists. You can do it by paragraph with:
!}fmt -w 9999
or do it from the command line outside of vi:
$ fmt -w 9999 file.txt
I like this approach because I don't have to remember to reset textwidth=80
as was touched on in the function the easiest way is to use
vipJ
Visual select inner paragraph join
精彩评论