开发者

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 line call 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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜