views:

665

answers:

5

I want to format srt subtitle text files to avoid wrapping problems on my media player.

I need to set a line wrap width to a number of characters e.g. 43

I can do this with Editplus, its a built in function and works well. The reason I want to do it in Vim, firstly Editplus is only available on the PC and the secondly Vim is badass.

I have found the following solution on the net..

:set tw=43
gggqG

It does work, but not exactly how I want it.

E.g.

I have this text:

557
00:47:39,487 --> 00:47:42,453
I will have to complete some procedures,
and I asked you to check out what they are for me

after I format it, I get:

557 00:47:39,487 --> 00:47:42,453 I will
have to complete some procedures, and I
asked you to check out what they are for
me

It seems to ignore line breaks/CRs. As you can see the "I will" has been added to the first line.

How do I get it to not ignore line breaks?

EDIT: apoligies about the formatting, first time using stackoverflow!

A: 

I can't see exactly what the issue is due to the formatting of your post, but you might want to checkout the 'formatoptions' setting in vim's help, specifically :he fo-table which contains a bunch of customization flags.

This link might be useful.

Gavin Gilmour
+1  A: 

With the following text (i.e. only 3 lines):

557
00:47:39,487 --> 00:47:42,453
I will have to complete some procedures, and I asked you to check out what they are for me

Use gqq (format current line) on the 3rd line after setting tw. Formatting by paragraph will not work since vim will treat all 3 lines as part of the same paragraph (paragraphs only end with a blank line).

p00ya
This unfortunately won't be suitable as a single text file will be made up of hundreds of 'blocks'. From the example that is the 577th! So editing a paragraph will be time consuming. I am looking for a way to automate the process for the whole file, like what gggqG does.
Jon
+2  A: 

If the only lines you want to wrap are the ones that start with text (ignore the ones that start with numbers) you can use the following.

:g/^[a-zA-Z]/normal gqq

This will run p00ya's command on each text line in the file.

rampion
+1  A: 

While not exactly robust (or elegant), if you can assume that the subtitle lines do not begin with numbers, you can configure Vim to treat them as comments.

:set comments=:0,:1,:2,:3,:4,:5,:6,:7,:8,:9
gggqG

Lines starting with 0-9 will be treated as comments and won't be merged together with the text.

erichui
+2  A: 

You could use the whitespace option of formatoptions and make the lines you want to wrap end in whitespace.

:set tw=43
:set fo+=w
:g/^\a/s/$/ /
gggqG

The third line adds a space on the end of any line starting with a letter and fo+=w stops gq from joining lines that don't end in spaces.

See:

:help fo-table
:help 'formatoptions'
:help gq
:help :g

Edit in response to comments

:g/^\a/s/$/ /

This translates to:

:g/   " Search the file
^\a   " For lines starting (^) with an alphabetic character (\a - equivalent to [A-Za-z])
/     " Then on each line that the regexp matches (i.e. each line starting with an alphabetic character)
s/    " Substitute...
$     " The end of line (zero-width match at the end of the line)
/ /   " With a space (slashes are delimiters)

The global (:g) command will only operate on the current file, but the textwidth and formatoptions lines will last for the whole session. If you want those options to only be used on the current buffer, use :setlocal instead:

:setlocal tw=43
:setlocal fo+=w
:help :setlocal
Al
Great! This now imitates the behaviour of Editplus. However there are aspects of erichui's answer which works even better. Because this solution still accounts for line breaks, if a word is past 43 char mark, it is pushed onto the line below, but it will still maintain the original line break so therefore one line could potentially only have one word on it followed by another line, just looks strange. But thats just being fussy now! Thanks Al :)
Jon
And what exactly does ":g/^\a/s/$/ /" mean? Also once I have run that command, Vim seems to remember it for any document I open in that session, how do reset it back to default without reopening Vim?
Jon
@Jon: I've added an explanation of :g///. Also an explanation of how to make the settings buffer local. I'm not sure I understand the comment about a line with one word on it: as far as I understand it, if all the lines end in space, gq should sort them out. Perhaps you could give an example?
Al