3

This is probably a really simple question but I can't seem to figure it out myself. I'm using a command from this answer on Stackoverflow to "unwrap" text. The person who answered gave the command:

:g/./,-/\n$/j

for unwrapping all paragraphs in a file but keeping the empty line between them. Does it match the whole paragraph somehow? I'm guessing so since the last part seems to match "empty line". The part that I really can't understand is /,-/.

1 Answer 1

4

It's actually quite subtle. Here is a step-by-step derivation.

First off, the pattern \n$ matches the ends of paragraphs. It's end-of-line, followed by an end-of-line- the only way this can happen is if the end of a line precedes an empty line. This is roughly equivalent to \n\ze\n, except that doesn't work at the end of the buffer.

Recognize that ,-/{re}/ denotes a range, starting from the current result of :g/./ (because of the empty string before the comma). Together ,-/\n$/j denotes the ranged command :join. This is not the normal command J. (!)

g/./{cmd} collects all lines containing any characters (i.e., not empty) and runs the ranged command on them. The real clever bit is that you don't have to worry about going over lines multiple times because we're joining them. Try

:g/./,-/\n$/p

You will see that at first this prints the entire paragraph which we want to join, but then it starts printing successive sub-paragraphs. Since we're joining this doesn't matter. g/ works over its matches one-by-one.

There is one remaining detail- what is the - for? If you try

:g/./,/\n$/p

this almost works, but it sometimes adds white-space after paragraphs. This is because the / inside a range is defined as the next line that includes the pattern. The - moves the end range up by one before searching so the potential empty line is not joined in. This would also be equivalent:

:g/./,-1/\n$/p
2
  • Thanks for the explanation! There is still one thing I'm wondering. The range doesn't seem to have a beginning. I expected a starting position before the comma but the range just starts with a comma here. Does leaving the start out have a special meaning?
    – user.S
    Commented Dec 16, 2017 at 19:55
  • Ah, good point. Starting a range with a comma means starting at the current line (where the g/./ brings us).
    – Mass
    Commented Dec 16, 2017 at 20:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.