18

I have a quite big text file formed of blocks like

Short line.
Really long line.
Short line.

separated by empty lines, and I would like to use vim (on Linux) to break down the long lines and obtain blocks like

Short line.
This was
part of
a long line.
Short line.

My problem with gq (and gw) is that it reflows each block as an entire paragraph, i.e. it doesn't preserve the two line breaks within each block, and according to :help fo-table none of gq's format options would allow me to do what I want. I also thought that I could achieve my goal if I could define new-line characters to be paragraph delimiters, but according to :help paragraph those are hard-coded.

Edit: I know that I could use gq or gw to format each long line one by one, but since my file runs over a few thousand lines I am looking for a way to achieve this automatically.

3
  • By the way: I looked for solutions to my problem in vim's documentation, here on SU, and on the web, coming up empty. I will gladly delete this question if I overlooked something obvious.
    – A.P.
    Mar 30, 2015 at 13:10
  • There is Can I justify text in Vim? at vi.sx. Apr 3, 2015 at 12:26
  • @MartinSchröder: Glad to know there's a vi SE! Those answers don't address my issue, though, since I already knew about gq and gw. I'm also glad I didn't stop there, otherwise I wouldn't have learned about the :g command. :)
    – A.P.
    Apr 3, 2015 at 12:33

4 Answers 4

20
:%norm! gww

This applies the normal command gww (which formats the current line as with gw) on the entire buffer, without taking customized mappings into account (to avoid problems if e.g. gw has been mapped to something else).

See

  • :help :%
  • :help :norm
  • :help gww

This alternative is as per Ben's suggestion in the comments, and is more straightforward than the original solution, which is saved below since it might fit better in other similar circumstances due to the regular expression matching ability. In the "match all lines" case, it is unnecessarily brute, though.


Applying gww on every individual line in the buffer programmatically:

:g/^/norm gww

See :help :g and :help norm. ^ matches the beginning of a line, which in practice makes this match every line.

One can also opt to select only lines longer than e.g. 60 characters with

:g/\%>60v/norm gww

(see :help \%<) but in practice gww will only reformat lines longer than textwidth anyway, so it might not matter much in neither speed nor result.

(I am using v for "virtual column" instead of c for "column", since the latter really calculates a certain number of bytes into the line. This can lead to unexpected results when using multibyte encodings, which is often a reason to be wary. In practice it is not a real issue for the same reason as above, regarding that gww will not reformat lines shorter than textwidth anyway.)

7
  • Apparently :g fails without a pattern, so :g//norm gww doesn't work but :g/.*/norm gww does.
    – A.P.
    Mar 30, 2015 at 17:01
  • @A.P.: Huh, works for me. I am using Vim 7.4.488-6 from Debian Unstable. Mar 30, 2015 at 18:32
  • 4
    :g// reuses the last search pattern; if there's none, it fails. Use :g/^/ to apply to all lines. Mar 30, 2015 at 18:35
  • @IngoKarkat: Ah, makes sense, since my last pattern during the tests was the line length aware one I demonstrated later. I will update the answer. Do you know where in the help this "empty pattern" behavior is mentioned? I can not trivially find it. Mar 30, 2015 at 18:39
  • Looking through the manual, it is probably implied that the information given in :help last-pattern for normal searching applies to the :global command as well. Mar 30, 2015 at 18:55
4

Since you’ve already read the manual for the gq and gw commands, I figure you probably want something more convenient than manually moving to the long lines and then using gw0, gw$ or another gw command to only format the current line.

I don’t know an easy way of breaking long lines in Vim over a block of text. However, since you’ve mentioned that your using Vim on a GNU/Linux system, I’d suggest filtering your text through the GNU fmt command.

For the whole file:

:%!fmt --width=75 --split-only

For the current paragraph (using short options):

:'{,'}!fmt -75 -s

Explanation of the relevant fmt options are:

  • -w, --width=WIDTH – maximum line width (default of 75 columns). The option -WIDTH is an abbreviated form of --width=DIGITS (if using this abbreviated version, it must be the first option).

  • -s, --split-only – split long lines, but do not refill; this is the option that preserves your pre-existing hard line breaks.

2
  • Thanks for mentioning fmt. I preferred to accept the other answer, though, because it requires only vim.
    – A.P.
    Mar 30, 2015 at 17:03
  • @A.P. No worries. It's a great answer and I'd have accepted it, myself. Both it and your question merit upvotes. Mar 30, 2015 at 22:39
1

From:

Short line.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Short line.

Putting the marker on the "lorem ipsum" line and pressing gww yields (with textwidth=40 for clarity):

Short line.
Lorem ipsum dolor sit amet, consectetur
adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.
Short line.

which to me seems like what you are asking for. If not, please feel free to clarify.

1
  • Yes but no, because you solution imply that he has to do that a lot of times going on all the "long lines"; that way the solution is on selection to :norm gqq Apr 5, 2022 at 18:13
0

I figure out this do the job:

:%s/\(\(\w\+\s\)\{1}\)/\r\1/g

Then, change 1 for your desired number of words to split.

Will produce:

Short line.

Really 
long line.

Short line.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .